diff options
author | Paul Gilbert | 2016-08-27 13:59:08 -0400 |
---|---|---|
committer | Paul Gilbert | 2016-08-27 13:59:08 -0400 |
commit | f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7 (patch) | |
tree | 771a8d2b3fddf96c17a1d81d42cb08dfba09d110 /engines | |
parent | 873d555add9aaf5eb0d021518f5134142e2c2ff6 (diff) | |
parent | 5ea32efbb0ecb3e6b8336ad3c2edd3905ea5b89a (diff) | |
download | scummvm-rg350-f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7.tar.gz scummvm-rg350-f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7.tar.bz2 scummvm-rg350-f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7.zip |
Merge branch 'master' into xeen
Diffstat (limited to 'engines')
1288 files changed, 141213 insertions, 5556 deletions
diff --git a/engines/access/access.cpp b/engines/access/access.cpp index 6f91bd76dd..ea2144459d 100644 --- a/engines/access/access.cpp +++ b/engines/access/access.cpp @@ -34,6 +34,12 @@ namespace Access { AccessEngine::AccessEngine(OSystem *syst, const AccessGameDescription *gameDesc) : _gameDescription(gameDesc), Engine(syst), _randomSource("Access"), _useItem(_flags[99]), _startup(_flags[170]), _manScaleOff(_flags[172]) { + // Set up debug channels + DebugMan.addDebugChannel(kDebugPath, "path", "Pathfinding debug level"); + DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); + DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); + _aboutBox = nullptr; _animation = nullptr; _bubbleBox = nullptr; @@ -151,12 +157,6 @@ void AccessEngine::setVGA() { } void AccessEngine::initialize() { - // Set up debug channels - DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); - DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); - DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); - DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); - if (isCD()) { const Common::FSNode gameDataDir(ConfMan.get("path")); // The CD version contains two versions of the game. diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp index b6af54962e..19595606e1 100644 --- a/engines/adl/adl.cpp +++ b/engines/adl/adl.cpp @@ -520,6 +520,8 @@ void AdlEngine::dropItem(byte noun) { } Common::Error AdlEngine::run() { + initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true); + _console = new Console(this); _speaker = new Speaker(); _display = new Display(); @@ -659,6 +661,11 @@ Common::Error AdlEngine::loadGameState(int slot) { _state.rooms[i].isFirstTime = inFile->readByte(); } + // NOTE: _state.curPicture is part of the save state in the original engine. We + // reconstruct it instead. This is believed to be safe for at least hires 0-2, but + // this may need to be re-evaluated for later games. + _state.curPicture = _state.rooms[_state.room].curPicture; + size = inFile->readUint32BE(); if (size != _state.items.size()) error("Item count mismatch (expected %i; found %i)", _state.items.size(), size); @@ -949,7 +956,7 @@ int AdlEngine::o1_isVarEQ(ScriptEnv &e) { int AdlEngine::o1_isCurPicEQ(ScriptEnv &e) { OP_DEBUG_1("\t&& GET_CURPIC() == %d", e.arg(1)); - if (getCurRoom().curPicture == e.arg(1)) + if (_state.curPicture == e.arg(1)) return 1; return -1; diff --git a/engines/adl/adl.h b/engines/adl/adl.h index c9d77fcc62..89cdabe384 100644 --- a/engines/adl/adl.h +++ b/engines/adl/adl.h @@ -165,11 +165,12 @@ struct State { Common::Array<byte> vars; byte room; + byte curPicture; uint16 moves; bool isDark; Time time; - State() : room(1), moves(1), isDark(false) { } + State() : room(1), curPicture(0), moves(1), isDark(false) { } }; typedef Common::List<Command> Commands; diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp index 4fdf796701..e18f3339f8 100644 --- a/engines/adl/adl_v2.cpp +++ b/engines/adl/adl_v2.cpp @@ -79,9 +79,9 @@ void AdlEngine_v2::setupOpcodeTables() { Opcode(o1_listInv); Opcode(o2_moveItem); Opcode(o1_setRoom); - Opcode(o1_setCurPic); + Opcode(o2_setCurPic); // 0x08 - Opcode(o1_setPic); + Opcode(o2_setPic); Opcode(o1_printMsg); Opcode(o1_setLight); Opcode(o1_setDark); @@ -250,6 +250,8 @@ void AdlEngine_v2::loadRoom(byte roomNr) { void AdlEngine_v2::showRoom() { bool redrawPic = false; + _state.curPicture = getCurRoom().curPicture; + if (_state.room != _roomOnScreen) { loadRoom(_state.room); clearScreen(); @@ -257,15 +259,15 @@ void AdlEngine_v2::showRoom() { if (!_state.isDark) redrawPic = true; } else { - if (getCurRoom().curPicture != _picOnScreen || _itemRemoved) + if (_state.curPicture != _picOnScreen || _itemRemoved) redrawPic = true; } if (redrawPic) { _roomOnScreen = _state.room; - _picOnScreen = getCurRoom().curPicture; + _picOnScreen = _state.curPicture; - drawPic(getCurRoom().curPicture); + drawPic(_state.curPicture); _itemRemoved = false; _itemsOnScreen = 0; @@ -336,7 +338,7 @@ void AdlEngine_v2::drawItems() { Common::Array<byte>::const_iterator pic; for (pic = item->roomPictures.begin(); pic != item->roomPictures.end(); ++pic) { - if (*pic == getCurRoom().curPicture || *pic == IDI_ANY) { + if (*pic == _state.curPicture || *pic == IDI_ANY) { drawItem(*item, item->position); break; } @@ -425,6 +427,20 @@ int AdlEngine_v2::o2_moveItem(ScriptEnv &e) { return 2; } +int AdlEngine_v2::o2_setCurPic(ScriptEnv &e) { + OP_DEBUG_1("\tSET_CURPIC(%d)", e.arg(1)); + + getCurRoom().curPicture = _state.curPicture = e.arg(1); + return 1; +} + +int AdlEngine_v2::o2_setPic(ScriptEnv &e) { + OP_DEBUG_1("\tSET_PIC(%d)", e.arg(1)); + + getCurRoom().picture = getCurRoom().curPicture = _state.curPicture = e.arg(1); + return 1; +} + int AdlEngine_v2::o2_moveAllItems(ScriptEnv &e) { OP_DEBUG_2("\tMOVE_ALL_ITEMS(%s, %s)", itemRoomStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); diff --git a/engines/adl/adl_v2.h b/engines/adl/adl_v2.h index f18972b74b..327b36e913 100644 --- a/engines/adl/adl_v2.h +++ b/engines/adl/adl_v2.h @@ -25,9 +25,6 @@ #include "adl/adl.h" -// Note: this version of ADL redraws only when necessary, but -// this is not currently implemented. - namespace Common { class RandomSource; } @@ -64,6 +61,8 @@ protected: int o2_isCarryingSomething(ScriptEnv &e); int o2_moveItem(ScriptEnv &e); + int o2_setCurPic(ScriptEnv &e); + int o2_setPic(ScriptEnv &e); int o2_moveAllItems(ScriptEnv &e); int o2_save(ScriptEnv &e); int o2_restore(ScriptEnv &e); diff --git a/engines/adl/adl_v3.cpp b/engines/adl/adl_v3.cpp index 623db661bc..6b93acde61 100644 --- a/engines/adl/adl_v3.cpp +++ b/engines/adl/adl_v3.cpp @@ -20,162 +20,26 @@ * */ -#include "common/random.h" -#include "common/error.h" - #include "adl/adl_v3.h" -#include "adl/display.h" -#include "adl/graphics.h" namespace Adl { AdlEngine_v3::AdlEngine_v3(OSystem *syst, const AdlGameDescription *gd) : - AdlEngine_v2(syst, gd), - _curDisk(0) { -} - -Common::String AdlEngine_v3::loadMessage(uint idx) const { - Common::String str = AdlEngine_v2::loadMessage(idx); - - for (uint i = 0; i < str.size(); ++i) { - const char *xorStr = "AVISDURGAN"; - str.setChar(str[i] ^ xorStr[i % strlen(xorStr)], i); - } - - return str; + AdlEngine_v2(syst, gd) { } Common::String AdlEngine_v3::getItemDescription(const Item &item) const { - return _itemDesc[item.id - 1]; -} - -void AdlEngine_v3::applyDiskOffset(byte &track, byte §or) const { - sector += _diskOffsets[_curDisk].sector; - if (sector >= 16) { - sector -= 16; - ++track; - } - - track += _diskOffsets[_curDisk].track; -} - -DataBlockPtr AdlEngine_v3::readDataBlockPtr(Common::ReadStream &f) const { - byte track = f.readByte(); - byte sector = f.readByte(); - byte offset = f.readByte(); - byte size = f.readByte(); - - if (f.eos() || f.err()) - error("Error reading DataBlockPtr"); - - if (track == 0 && sector == 0 && offset == 0 && size == 0) - return DataBlockPtr(); - - applyDiskOffset(track, sector); - - return _disk->getDataBlock(track, sector, offset, size); + return _itemDesc[item.description - 1]; } typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v3> OpcodeV3; -#define SetOpcodeTable(x) table = &x; -#define Opcode(x) table->push_back(new OpcodeV3(this, &AdlEngine_v3::x)) -#define OpcodeUnImpl() table->push_back(new OpcodeV3(this, 0)) void AdlEngine_v3::setupOpcodeTables() { - Common::Array<const Opcode *> *table = 0; - - SetOpcodeTable(_condOpcodes); - // 0x00 - OpcodeUnImpl(); - Opcode(o2_isFirstTime); - Opcode(o2_isRandomGT); - Opcode(o3_isItemInRoom); - // 0x04 - Opcode(o3_isNounNotInRoom); - Opcode(o1_isMovesGT); - Opcode(o1_isVarEQ); - Opcode(o2_isCarryingSomething); - // 0x08 - Opcode(o3_isVarGT); - Opcode(o1_isCurPicEQ); - Opcode(o3_skipOneCommand); - - SetOpcodeTable(_actOpcodes); - // 0x00 - OpcodeUnImpl(); - Opcode(o1_varAdd); - Opcode(o1_varSub); - Opcode(o1_varSet); - // 0x04 - Opcode(o1_listInv); - Opcode(o3_moveItem); - Opcode(o1_setRoom); - Opcode(o1_setCurPic); - // 0x08 - Opcode(o1_setPic); - Opcode(o1_printMsg); - Opcode(o3_dummy); - Opcode(o3_setTextMode); - // 0x0c - Opcode(o2_moveAllItems); - Opcode(o1_quit); - Opcode(o3_dummy); - Opcode(o2_save); - // 0x10 - Opcode(o2_restore); - Opcode(o1_restart); - Opcode(o3_setDisk); - Opcode(o3_dummy); - // 0x14 - Opcode(o1_resetPic); - Opcode(o1_goDirection<IDI_DIR_NORTH>); - Opcode(o1_goDirection<IDI_DIR_SOUTH>); - Opcode(o1_goDirection<IDI_DIR_EAST>); - // 0x18 - Opcode(o1_goDirection<IDI_DIR_WEST>); - Opcode(o1_goDirection<IDI_DIR_UP>); - Opcode(o1_goDirection<IDI_DIR_DOWN>); - Opcode(o1_takeItem); - // 0x1c - Opcode(o1_dropItem); - Opcode(o1_setRoomPic); - Opcode(o3_sound); - OpcodeUnImpl(); - // 0x20 - Opcode(o2_initDisk); -} - -int AdlEngine_v3::o3_isVarGT(ScriptEnv &e) { - OP_DEBUG_2("\t&& VARS[%d] > %d", e.arg(1), e.arg(2)); - - if (getVar(e.arg(1)) > e.arg(2)) - return 2; - - return -1; -} - -int AdlEngine_v3::o3_skipOneCommand(ScriptEnv &e) { - OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()"); - - _skipOneCommand = true; - setVar(2, 0); - - return -1; -} - -// FIXME: Rename "isLineArt" and look at code duplication -int AdlEngine_v3::o3_isItemInRoom(ScriptEnv &e) { - OP_DEBUG_2("\t&& GET_ITEM_ROOM(%s) == %s", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); - - const Item &item = getItem(e.arg(1)); - - if (e.arg(2) != IDI_ANY && item.isLineArt != _curDisk) - return -1; - - if (item.room == roomArg(e.arg(2))) - return 2; - - return -1; + AdlEngine_v2::setupOpcodeTables(); + delete _condOpcodes[0x04]; + _condOpcodes[0x04] = new OpcodeV3(this, &AdlEngine_v3::o3_isNounNotInRoom); + delete _actOpcodes[0x04]; + _actOpcodes[0x04] = new OpcodeV3(this, &AdlEngine_v3::o3_listInv); } int AdlEngine_v3::o3_isNounNotInRoom(ScriptEnv &e) { @@ -183,75 +47,28 @@ int AdlEngine_v3::o3_isNounNotInRoom(ScriptEnv &e) { Common::List<Item>::const_iterator item; - setVar(24, 0); + bool isAnItem = false; - for (item = _state.items.begin(); item != _state.items.end(); ++item) + for (item = _state.items.begin(); item != _state.items.end(); ++item) { if (item->noun == e.getNoun()) { - setVar(24, 1); + isAnItem = true; if (item->room == roomArg(e.arg(1))) return -1; } - - return 1; -} - -int AdlEngine_v3::o3_moveItem(ScriptEnv &e) { - OP_DEBUG_2("\tSET_ITEM_ROOM(%s, %s)", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); - - byte room = roomArg(e.arg(2)); - - Item &item = getItem(e.arg(1)); - - if (item.room == _roomOnScreen) - _picOnScreen = 0; - - // Set items that move from inventory to a room to state "dropped" - if (item.room == IDI_ANY && room != IDI_VOID_ROOM) - item.state = IDI_ITEM_DROPPED; - - item.room = room; - item.isLineArt = _curDisk; - return 2; -} - -int AdlEngine_v3::o3_dummy(ScriptEnv &e) { - OP_DEBUG_0("\tDUMMY()"); - - return 0; -} - -int AdlEngine_v3::o3_setTextMode(ScriptEnv &e) { - OP_DEBUG_1("\tSET_TEXT_MODE(%d)", e.arg(1)); - - // TODO - // 1: 4-line mode - // 2: 24-line mode - - switch (e.arg(1)) { - case 3: - // We re-use the restarting flag here, to simulate a long jump - _isRestarting = true; - return -1; } - return 1; + return (isAnItem ? 1 : -1); } -int AdlEngine_v3::o3_setDisk(ScriptEnv &e) { - OP_DEBUG_2("\tSET_DISK(%d, %d)", e.arg(1), e.arg(2)); - - // TODO - // Arg 1: disk - // Arg 2: room - - return 2; -} +int AdlEngine_v3::o3_listInv(ScriptEnv &e) { + OP_DEBUG_0("\tLIST_INVENTORY()"); -int AdlEngine_v3::o3_sound(ScriptEnv &e) { - OP_DEBUG_0("\tSOUND()"); + Common::List<Item>::const_iterator item; - // TODO + for (item = _state.items.begin(); item != _state.items.end(); ++item) + if (item->room == IDI_ANY) + printString(_itemDesc[item->description - 1]); return 0; } diff --git a/engines/adl/adl_v3.h b/engines/adl/adl_v3.h index 61dd5852e7..759b17cc6f 100644 --- a/engines/adl/adl_v3.h +++ b/engines/adl/adl_v3.h @@ -25,18 +25,6 @@ #include "adl/adl_v2.h" -// Note: this version of ADL redraws only when necessary, but -// this is not currently implemented. - -namespace Common { -class RandomSource; -} - -struct DiskOffset { - byte track; - byte sector; -}; - namespace Adl { class AdlEngine_v3 : public AdlEngine_v2 { @@ -48,27 +36,12 @@ protected: // AdlEngine virtual void setupOpcodeTables(); - virtual Common::String loadMessage(uint idx) const; Common::String getItemDescription(const Item &item) const; - // AdlEngine_v2 - virtual DataBlockPtr readDataBlockPtr(Common::ReadStream &f) const; - - void applyDiskOffset(byte &track, byte §or) const; - - int o3_isVarGT(ScriptEnv &e); - int o3_isItemInRoom(ScriptEnv &e); int o3_isNounNotInRoom(ScriptEnv &e); - int o3_skipOneCommand(ScriptEnv &e); - int o3_moveItem(ScriptEnv &e); - int o3_dummy(ScriptEnv &e); - int o3_setTextMode(ScriptEnv &e); - int o3_setDisk(ScriptEnv &e); - int o3_sound(ScriptEnv &e); + int o3_listInv(ScriptEnv &e); Common::Array<Common::String> _itemDesc; - byte _curDisk; - Common::Array<DiskOffset> _diskOffsets; }; } // End of namespace Adl diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp new file mode 100644 index 0000000000..602ee25683 --- /dev/null +++ b/engines/adl/adl_v4.cpp @@ -0,0 +1,271 @@ +/* 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/random.h" +#include "common/error.h" + +#include "adl/adl_v4.h" +#include "adl/display.h" +#include "adl/graphics.h" + +namespace Adl { + +AdlEngine_v4::AdlEngine_v4(OSystem *syst, const AdlGameDescription *gd) : + AdlEngine_v3(syst, gd), + _curDisk(0) { +} + +Common::String AdlEngine_v4::loadMessage(uint idx) const { + Common::String str = AdlEngine_v2::loadMessage(idx); + + for (uint i = 0; i < str.size(); ++i) { + const char *xorStr = "AVISDURGAN"; + str.setChar(str[i] ^ xorStr[i % strlen(xorStr)], i); + } + + return str; +} + +Common::String AdlEngine_v4::getItemDescription(const Item &item) const { + return _itemDesc[item.id - 1]; +} + +void AdlEngine_v4::applyDiskOffset(byte &track, byte §or) const { + sector += _diskOffsets[_curDisk].sector; + if (sector >= 16) { + sector -= 16; + ++track; + } + + track += _diskOffsets[_curDisk].track; +} + +DataBlockPtr AdlEngine_v4::readDataBlockPtr(Common::ReadStream &f) const { + byte track = f.readByte(); + byte sector = f.readByte(); + byte offset = f.readByte(); + byte size = f.readByte(); + + if (f.eos() || f.err()) + error("Error reading DataBlockPtr"); + + if (track == 0 && sector == 0 && offset == 0 && size == 0) + return DataBlockPtr(); + + applyDiskOffset(track, sector); + + return _disk->getDataBlock(track, sector, offset, size); +} + +typedef Common::Functor1Mem<ScriptEnv &, int, AdlEngine_v4> OpcodeV4; +#define SetOpcodeTable(x) table = &x; +#define Opcode(x) table->push_back(new OpcodeV4(this, &AdlEngine_v4::x)) +#define OpcodeUnImpl() table->push_back(new OpcodeV4(this, 0)) + +void AdlEngine_v4::setupOpcodeTables() { + Common::Array<const Opcode *> *table = 0; + + SetOpcodeTable(_condOpcodes); + // 0x00 + OpcodeUnImpl(); + Opcode(o2_isFirstTime); + Opcode(o2_isRandomGT); + Opcode(o4_isItemInRoom); + // 0x04 + Opcode(o4_isNounNotInRoom); + Opcode(o1_isMovesGT); + Opcode(o1_isVarEQ); + Opcode(o2_isCarryingSomething); + // 0x08 + Opcode(o4_isVarGT); + Opcode(o1_isCurPicEQ); + Opcode(o4_skipOneCommand); + + SetOpcodeTable(_actOpcodes); + // 0x00 + OpcodeUnImpl(); + Opcode(o1_varAdd); + Opcode(o1_varSub); + Opcode(o1_varSet); + // 0x04 + Opcode(o4_listInv); + Opcode(o4_moveItem); + Opcode(o1_setRoom); + Opcode(o2_setCurPic); + // 0x08 + Opcode(o2_setPic); + Opcode(o1_printMsg); + Opcode(o4_dummy); + Opcode(o4_setTextMode); + // 0x0c + Opcode(o2_moveAllItems); + Opcode(o1_quit); + Opcode(o4_dummy); + Opcode(o2_save); + // 0x10 + Opcode(o2_restore); + Opcode(o1_restart); + Opcode(o4_setDisk); + Opcode(o4_dummy); + // 0x14 + Opcode(o1_resetPic); + Opcode(o1_goDirection<IDI_DIR_NORTH>); + Opcode(o1_goDirection<IDI_DIR_SOUTH>); + Opcode(o1_goDirection<IDI_DIR_EAST>); + // 0x18 + Opcode(o1_goDirection<IDI_DIR_WEST>); + Opcode(o1_goDirection<IDI_DIR_UP>); + Opcode(o1_goDirection<IDI_DIR_DOWN>); + Opcode(o1_takeItem); + // 0x1c + Opcode(o1_dropItem); + Opcode(o1_setRoomPic); + Opcode(o4_sound); + OpcodeUnImpl(); + // 0x20 + Opcode(o2_initDisk); +} + +int AdlEngine_v4::o4_isVarGT(ScriptEnv &e) { + OP_DEBUG_2("\t&& VARS[%d] > %d", e.arg(1), e.arg(2)); + + if (getVar(e.arg(1)) > e.arg(2)) + return 2; + + return -1; +} + +int AdlEngine_v4::o4_skipOneCommand(ScriptEnv &e) { + OP_DEBUG_0("\t&& SKIP_ONE_COMMAND()"); + + _skipOneCommand = true; + setVar(2, 0); + + return -1; +} + +// FIXME: Rename "isLineArt" and look at code duplication +int AdlEngine_v4::o4_isItemInRoom(ScriptEnv &e) { + OP_DEBUG_2("\t&& GET_ITEM_ROOM(%s) == %s", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); + + const Item &item = getItem(e.arg(1)); + + if (e.arg(2) != IDI_ANY && item.isLineArt != _curDisk) + return -1; + + if (item.room == roomArg(e.arg(2))) + return 2; + + return -1; +} + +int AdlEngine_v4::o4_isNounNotInRoom(ScriptEnv &e) { + OP_DEBUG_1("\t&& NO_SUCH_ITEMS_IN_ROOM(%s)", itemRoomStr(e.arg(1)).c_str()); + + Common::List<Item>::const_iterator item; + + setVar(24, 0); + + for (item = _state.items.begin(); item != _state.items.end(); ++item) + if (item->noun == e.getNoun()) { + setVar(24, 1); + + if (item->room == roomArg(e.arg(1))) + return -1; + } + + return 1; +} + +int AdlEngine_v4::o4_listInv(ScriptEnv &e) { + OP_DEBUG_0("\tLIST_INVENTORY()"); + + Common::List<Item>::const_iterator item; + + for (item = _state.items.begin(); item != _state.items.end(); ++item) + if (item->room == IDI_ANY) + printString(_itemDesc[item->id - 1]); + + return 0; +} + +int AdlEngine_v4::o4_moveItem(ScriptEnv &e) { + OP_DEBUG_2("\tSET_ITEM_ROOM(%s, %s)", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); + + byte room = roomArg(e.arg(2)); + + Item &item = getItem(e.arg(1)); + + if (item.room == _roomOnScreen) + _picOnScreen = 0; + + // Set items that move from inventory to a room to state "dropped" + if (item.room == IDI_ANY && room != IDI_VOID_ROOM) + item.state = IDI_ITEM_DROPPED; + + item.room = room; + item.isLineArt = _curDisk; + return 2; +} + +int AdlEngine_v4::o4_dummy(ScriptEnv &e) { + OP_DEBUG_0("\tDUMMY()"); + + return 0; +} + +int AdlEngine_v4::o4_setTextMode(ScriptEnv &e) { + OP_DEBUG_1("\tSET_TEXT_MODE(%d)", e.arg(1)); + + // TODO + // 1: 4-line mode + // 2: 24-line mode + + switch (e.arg(1)) { + case 3: + // We re-use the restarting flag here, to simulate a long jump + _isRestarting = true; + return -1; + } + + return 1; +} + +int AdlEngine_v4::o4_setDisk(ScriptEnv &e) { + OP_DEBUG_2("\tSET_DISK(%d, %d)", e.arg(1), e.arg(2)); + + // TODO + // Arg 1: disk + // Arg 2: room + + return 2; +} + +int AdlEngine_v4::o4_sound(ScriptEnv &e) { + OP_DEBUG_0("\tSOUND()"); + + // TODO + + return 0; +} + +} // End of namespace Adl diff --git a/engines/adl/adl_v4.h b/engines/adl/adl_v4.h new file mode 100644 index 0000000000..dc9a27501e --- /dev/null +++ b/engines/adl/adl_v4.h @@ -0,0 +1,73 @@ +/* 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 ADL_ADL_V4_H +#define ADL_ADL_V4_H + +#include "adl/adl_v3.h" + +namespace Common { +class RandomSource; +} + +struct DiskOffset { + byte track; + byte sector; +}; + +namespace Adl { + +class AdlEngine_v4 : public AdlEngine_v3 { +public: + virtual ~AdlEngine_v4() { } + +protected: + AdlEngine_v4(OSystem *syst, const AdlGameDescription *gd); + + // AdlEngine + virtual void setupOpcodeTables(); + virtual Common::String loadMessage(uint idx) const; + Common::String getItemDescription(const Item &item) const; + + // AdlEngine_v2 + virtual DataBlockPtr readDataBlockPtr(Common::ReadStream &f) const; + + void applyDiskOffset(byte &track, byte §or) const; + + int o4_isVarGT(ScriptEnv &e); + int o4_isItemInRoom(ScriptEnv &e); + int o4_isNounNotInRoom(ScriptEnv &e); + int o4_skipOneCommand(ScriptEnv &e); + int o4_listInv(ScriptEnv &e); + int o4_moveItem(ScriptEnv &e); + int o4_dummy(ScriptEnv &e); + int o4_setTextMode(ScriptEnv &e); + int o4_setDisk(ScriptEnv &e); + int o4_sound(ScriptEnv &e); + + byte _curDisk; + Common::Array<DiskOffset> _diskOffsets; +}; + +} // End of namespace Adl + +#endif diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp index 12405e7c5e..be9165b127 100644 --- a/engines/adl/detection.cpp +++ b/engines/adl/detection.cpp @@ -32,13 +32,15 @@ namespace Adl { -#define GAMEOPTION_COLOR GUIO_GAMEOPTIONS1 -#define GAMEOPTION_SCANLINES GUIO_GAMEOPTIONS2 -#define GAMEOPTION_MONO GUIO_GAMEOPTIONS3 +// Mystery House was designed for monochrome display, so we default to +// monochrome mode there. All the other games default to color mode. +#define GAMEOPTION_COLOR_DEFAULT_OFF GUIO_GAMEOPTIONS1 +#define GAMEOPTION_SCANLINES GUIO_GAMEOPTIONS2 +#define GAMEOPTION_COLOR_DEFAULT_ON GUIO_GAMEOPTIONS3 static const ADExtraGuiOptionsMap optionsList[] = { { - GAMEOPTION_COLOR, + GAMEOPTION_COLOR_DEFAULT_OFF, { _s("Color mode"), _s("Use color graphics"), @@ -48,7 +50,7 @@ static const ADExtraGuiOptionsMap optionsList[] = { }, { - GAMEOPTION_MONO, + GAMEOPTION_COLOR_DEFAULT_ON, { _s("Color mode"), _s("Use color graphics"), @@ -74,6 +76,7 @@ static const PlainGameDescriptor adlGames[] = { { "hires0", "Hi-Res Adventure #0: Mission Asteroid" }, { "hires1", "Hi-Res Adventure #1: Mystery House" }, { "hires2", "Hi-Res Adventure #2: Wizard and the Princess" }, + { "hires4", "Hi-Res Adventure #4: Ulysses and the Golden Fleece" }, { "hires6", "Hi-Res Adventure #6: The Dark Crystal" }, { 0, 0 } }; @@ -89,9 +92,9 @@ static const AdlGameDescription gameDescriptions[] = { AD_LISTEND }, Common::EN_ANY, - Common::kPlatformApple2GS, // FIXME - ADGF_UNSTABLE, - GUIO2(GAMEOPTION_COLOR, GAMEOPTION_SCANLINES) + Common::kPlatformApple2, + ADGF_TESTING, + GUIO2(GAMEOPTION_COLOR_DEFAULT_OFF, GAMEOPTION_SCANLINES) }, GAME_TYPE_HIRES1 }, @@ -103,9 +106,9 @@ static const AdlGameDescription gameDescriptions[] = { AD_LISTEND }, Common::EN_ANY, - Common::kPlatformApple2GS, // FIXME - ADGF_UNSTABLE, - GUIO2(GAMEOPTION_COLOR, GAMEOPTION_SCANLINES) + Common::kPlatformApple2, + ADGF_TESTING, + GUIO2(GAMEOPTION_COLOR_DEFAULT_OFF, GAMEOPTION_SCANLINES) }, GAME_TYPE_HIRES1 }, @@ -117,9 +120,9 @@ static const AdlGameDescription gameDescriptions[] = { AD_LISTEND }, Common::EN_ANY, - Common::kPlatformApple2GS, // FIXME - ADGF_UNSTABLE, - GUIO2(GAMEOPTION_MONO, GAMEOPTION_SCANLINES) + Common::kPlatformApple2, + ADGF_TESTING, + GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, GAME_TYPE_HIRES2 }, @@ -131,12 +134,27 @@ static const AdlGameDescription gameDescriptions[] = { AD_LISTEND }, Common::EN_ANY, - Common::kPlatformApple2GS, // FIXME - ADGF_UNSTABLE, - GUIO2(GAMEOPTION_MONO, GAMEOPTION_SCANLINES) + Common::kPlatformApple2, + ADGF_TESTING, + GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, GAME_TYPE_HIRES0 }, + { // Hi-Res Adventure #4: Ulysses and the Golden Fleece - Atari 8-bit - Re-release + { + "hires4", 0, + { + { "ULYS1A.XFD", 0, "26365d2b06509fd21e7a7919e33f7199", 92160 }, + // FIXME: Add sides 1B and 2C + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformAtariST, // FIXME + ADGF_UNSTABLE, + GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) + }, + GAME_TYPE_HIRES4 + }, { // Hi-Res Adventure #6: The Dark Crystal - Apple II - Roberta Williams Anthology { "hires6", 0, @@ -148,9 +166,9 @@ static const AdlGameDescription gameDescriptions[] = { AD_LISTEND }, Common::EN_ANY, - Common::kPlatformApple2GS, // FIXME + Common::kPlatformApple2, ADGF_UNSTABLE, - GUIO2(GAMEOPTION_MONO, GAMEOPTION_SCANLINES) + GUIO2(GAMEOPTION_COLOR_DEFAULT_ON, GAMEOPTION_SCANLINES) }, GAME_TYPE_HIRES6 }, @@ -294,6 +312,8 @@ void AdlMetaEngine::removeSaveState(const char *target, int slot) const { Engine *HiRes1Engine_create(OSystem *syst, const AdlGameDescription *gd); Engine *HiRes2Engine_create(OSystem *syst, const AdlGameDescription *gd); +Engine *HiRes0Engine_create(OSystem *syst, const AdlGameDescription *gd); +Engine *HiRes4Engine_create(OSystem *syst, const AdlGameDescription *gd); Engine *HiRes6Engine_create(OSystem *syst, const AdlGameDescription *gd); bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const { @@ -309,6 +329,12 @@ bool AdlMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD case GAME_TYPE_HIRES2: *engine = HiRes2Engine_create(syst, adlGd); break; + case GAME_TYPE_HIRES0: + *engine = HiRes0Engine_create(syst, adlGd); + break; + case GAME_TYPE_HIRES4: + *engine = HiRes4Engine_create(syst, adlGd); + break; case GAME_TYPE_HIRES6: *engine = HiRes6Engine_create(syst, adlGd); break; diff --git a/engines/adl/detection.h b/engines/adl/detection.h index 533466c094..b4dc3c430f 100644 --- a/engines/adl/detection.h +++ b/engines/adl/detection.h @@ -35,6 +35,7 @@ enum GameType { GAME_TYPE_HIRES0, GAME_TYPE_HIRES1, GAME_TYPE_HIRES2, + GAME_TYPE_HIRES4, GAME_TYPE_HIRES6 }; diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp index 214f76aeae..49e01f9d0f 100644 --- a/engines/adl/disk.cpp +++ b/engines/adl/disk.cpp @@ -28,98 +28,63 @@ namespace Adl { -const DataBlockPtr DiskImage_DSK::getDataBlock(uint track, uint sector, uint offset, uint size) const { - return Common::SharedPtr<DiskImage::DataBlock>(new DiskImage::DataBlock(this, track, sector, offset, size)); -} - -Common::SeekableReadStream *DiskImage_DSK::createReadStream(uint track, uint sector, uint offset, uint size) const { - _f->seek((track * _sectorsPerTrack + sector) * _bytesPerSector + offset); - Common::SeekableReadStream *stream = _f->readStream(size * _bytesPerSector + _bytesPerSector - offset); - - if (_f->eos() || _f->err()) - error("Error reading disk image"); - - return stream; -} - -bool DiskImage_DSK::open(const Common::String &filename) { - assert(!_f->isOpen()); - - if (!_f->open(filename)) - return false; - - uint filesize = _f->size(); - switch (filesize) { - case 143360: - _tracks = 35; - _sectorsPerTrack = 16; - _bytesPerSector = 256; - break; - default: - warning("Unrecognized disk image '%s' of size %d bytes", filename.c_str(), filesize); - return false; +#define TRACKS 35 +// The Apple II uses either 13- or 16-sector disks. We currently pad out +// 13-sector disks, so we set SECTORS_PER_TRACK to 16 here. +#define SECTORS_PER_TRACK 16 +#define BYTES_PER_SECTOR 256 +#define RAW_IMAGE_SIZE(S) (TRACKS * (S) * BYTES_PER_SECTOR) +#define NIB_IMAGE_SIZE (RAW_IMAGE_SIZE(13) * 2) + +static Common::SeekableReadStream *readImage_DSK(const Common::String &filename) { + Common::File *f = new Common::File; + + if (!f->open(filename)) { + delete f; + return nullptr; } - return true; -} - -const DataBlockPtr DiskImage_NIB::getDataBlock(uint track, uint sector, uint offset, uint size) const { - return Common::SharedPtr<DiskImage::DataBlock>(new DiskImage::DataBlock(this, track, sector, offset, size)); -} - -Common::SeekableReadStream *DiskImage_NIB::createReadStream(uint track, uint sector, uint offset, uint size) const { - _memStream->seek((track * _sectorsPerTrack + sector) * _bytesPerSector + offset); - Common::SeekableReadStream *stream = _memStream->readStream(size * _bytesPerSector + _bytesPerSector - offset); - - if (_memStream->eos() || _memStream->err()) - error("Error reading NIB image"); + if (f->size() != RAW_IMAGE_SIZE(16)) + error("Unrecognized DSK image '%s' of size %d bytes", filename.c_str(), f->size()); - return stream; + return f; } // 4-and-4 encoding (odd-even) -static uint8 read44(Common::SeekableReadStream *f) { +static uint8 read44(Common::SeekableReadStream &f) { // 1s in the other fields, so we can just AND - uint8 ret = f->readByte(); - return ((ret << 1) | 1) & f->readByte(); + uint8 ret = f.readByte(); + return ((ret << 1) | 1) & f.readByte(); } -bool DiskImage_NIB::open(const Common::String &filename) { - assert(!_f->isOpen()); +static Common::SeekableReadStream *readImage_NIB(const Common::String &filename) { + Common::File f; - if (!_f->open(filename)) - return false; + if (!f.open(filename)) + return nullptr; - uint filesize = _f->size(); - switch (filesize) { - case 232960: - _tracks = 35; - _sectorsPerTrack = 16; // we always pad it out - _bytesPerSector = 256; - break; - default: - error("Unrecognized NIB image '%s' of size %d bytes", filename.c_str(), filesize); - } + if (f.size() != NIB_IMAGE_SIZE) + error("Unrecognized NIB image '%s' of size %d bytes", filename.c_str(), f.size()); // starting at 0xaa, 32 is invalid (see below) const byte c_5and3_lookup[] = { 32, 0, 32, 1, 2, 3, 32, 32, 32, 32, 32, 4, 5, 6, 32, 32, 7, 8, 32, 9, 10, 11, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 12, 13, 32, 32, 14, 15, 32, 16, 17, 18, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 19, 20, 32, 21, 22, 23, 32, 32, 32, 32, 32, 24, 25, 26, 32, 32, 27, 28, 32, 29, 30, 31 }; // starting at 0x96, 64 is invalid (see below) const byte c_6and2_lookup[] = { 0, 1, 64, 64, 2, 3, 64, 4, 5, 6, 64, 64, 64, 64, 64, 64, 7, 8, 64, 64, 64, 9, 10, 11, 12, 13, 64, 64, 14, 15, 16, 17, 18, 19, 64, 20, 21, 22, 23, 24, 25, 26, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 27, 64, 28, 29, 30, 64, 64, 64, 31, 64, 64, 32, 33, 64, 34, 35, 36, 37, 38, 39, 40, 64, 64, 64, 64, 64, 41, 42, 43, 64, 44, 45, 46, 47, 48, 49, 50, 64, 64, 51, 52, 53, 54, 55, 56, 64, 57, 58, 59, 60, 61, 62, 63 }; - uint32 diskSize = _tracks * _sectorsPerTrack * _bytesPerSector; - byte *diskImage = (byte *)calloc(diskSize, 1); - _memStream = new Common::MemoryReadStream(diskImage, diskSize, DisposeAfterUse::YES); + // we always pad it out + const uint sectorsPerTrack = 16; + byte *diskImage = (byte *)calloc(RAW_IMAGE_SIZE(sectorsPerTrack), 1); bool sawAddress = false; uint8 volNo, track, sector; bool newStyle; - while (_f->pos() < _f->size()) { + while (f.pos() < f.size()) { // Read until we find two sync bytes. - if (_f->readByte() != 0xd5 || _f->readByte() != 0xaa) + if (f.readByte() != 0xd5 || f.readByte() != 0xaa) continue; - byte prologue = _f->readByte(); + byte prologue = f.readByte(); if (sawAddress && (prologue == 0xb5 || prologue == 0x96)) { warning("NIB: data for %02x/%02x/%02x missing", volNo, track, sector); @@ -140,21 +105,13 @@ bool DiskImage_NIB::open(const Common::String &filename) { } } - volNo = read44(_f); - track = read44(_f); - sector = read44(_f); - uint8 checksum = read44(_f); + volNo = read44(f); + track = read44(f); + sector = read44(f); + uint8 checksum = read44(f); if ((volNo ^ track ^ sector) != checksum) error("invalid NIB checksum"); - // FIXME: This is a hires0/hires2-specific hack. - if (volNo == 0xfe) { - if (track == 1) - track = 2; - else if (track == 2) - track = 1; - } - // Epilogue is de/aa plus a gap, but we don't care. continue; } @@ -163,17 +120,17 @@ bool DiskImage_NIB::open(const Common::String &filename) { // We should always find the data field after an address field. // TODO: we ignore volNo? - byte *output = diskImage + (track * _sectorsPerTrack + sector) * _bytesPerSector; + byte *output = diskImage + (track * sectorsPerTrack + sector) * BYTES_PER_SECTOR; if (newStyle) { // We hardcode the DOS 3.3 mapping here. TODO: Do we also need raw/prodos? int raw2dos[16] = { 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 }; sector = raw2dos[sector]; - output = diskImage + (track * _sectorsPerTrack + sector) * _bytesPerSector; + output = diskImage + (track * sectorsPerTrack + sector) * BYTES_PER_SECTOR; // 6-and-2 uses 342 on-disk bytes byte inbuffer[342]; - _f->read(inbuffer, 342); + f.read(inbuffer, 342); byte oldVal = 0; for (uint n = 0; n < 342; ++n) { @@ -188,7 +145,7 @@ bool DiskImage_NIB::open(const Common::String &filename) { inbuffer[n] = oldVal; } - byte checksum = _f->readByte(); + byte checksum = f.readByte(); if (checksum < 0x96 || oldVal != c_6and2_lookup[checksum - 0x96]) warning("NIB: checksum mismatch @ (%x, %x)", track, sector); @@ -208,7 +165,7 @@ bool DiskImage_NIB::open(const Common::String &filename) { } else { // 5-and-3 uses 410 on-disk bytes, decoding to just over 256 bytes byte inbuffer[410]; - _f->read(inbuffer, 410); + f.read(inbuffer, 410); bool truncated = false; byte oldVal = 0; @@ -218,16 +175,16 @@ bool DiskImage_NIB::open(const Common::String &filename) { if (inbuffer[n] == 0xd5) { // Early end of block. truncated = true; - _f->seek(-(410 - n), SEEK_CUR); - warning("NIB: early end of block @ 0x%x (%x, %x)", _f->pos(), track, sector); + f.seek(-(410 - n), SEEK_CUR); + warning("NIB: early end of block @ 0x%x (%x, %x)", f.pos(), track, sector); break; } byte val = c_5and3_lookup[inbuffer[n] - 0xaa]; if (val == 0x20) { // Badly-encoded nibbles, stop trying to decode here. truncated = true; - warning("NIB: bad nibble %02x @ 0x%x (%x, %x)", inbuffer[n], _f->pos(), track, sector); - _f->seek(-(410 - n), SEEK_CUR); + warning("NIB: bad nibble %02x @ 0x%x (%x, %x)", inbuffer[n], f.pos(), track, sector); + f.seek(-(410 - n), SEEK_CUR); break; } // undo checksum @@ -235,7 +192,7 @@ bool DiskImage_NIB::open(const Common::String &filename) { inbuffer[n] = oldVal; } if (!truncated) { - byte checksum = _f->readByte(); + byte checksum = f.readByte(); if (checksum < 0xaa || oldVal != c_5and3_lookup[checksum - 0xaa]) warning("NIB: checksum mismatch @ (%x, %x)", track, sector); } @@ -259,7 +216,52 @@ bool DiskImage_NIB::open(const Common::String &filename) { } } - return true; + return new Common::MemoryReadStream(diskImage, RAW_IMAGE_SIZE(sectorsPerTrack), DisposeAfterUse::YES); +} + +bool DiskImage::open(const Common::String &filename) { + Common::String lcName(filename); + lcName.toLowercase(); + + if (lcName.hasSuffix(".dsk")) + _stream = readImage_DSK(filename); + else if (lcName.hasSuffix(".nib")) + _stream = readImage_NIB(filename); + + return _stream != nullptr; +} + +const DataBlockPtr DiskImage::getDataBlock(uint track, uint sector, uint offset, uint size) const { + return DataBlockPtr(new DiskImage::DataBlock(this, track, sector, offset, size, _mode13)); +} + +Common::SeekableReadStream *DiskImage::createReadStream(uint track, uint sector, uint offset, uint size, uint sectorsPerTrackToRead) const { + const uint bytesToRead = size * BYTES_PER_SECTOR + BYTES_PER_SECTOR - offset; + byte *const data = (byte *)malloc(bytesToRead); + uint dataOffset = 0; + + if (sector > sectorsPerTrackToRead - 1) + error("Sector %i is out of bounds for %i-sector reading", sector, sectorsPerTrackToRead); + + while (dataOffset < bytesToRead) { + uint bytesRemInTrack = (sectorsPerTrackToRead - 1 - sector) * BYTES_PER_SECTOR + BYTES_PER_SECTOR - offset; + _stream->seek((track * SECTORS_PER_TRACK + sector) * BYTES_PER_SECTOR + offset); + + if (bytesToRead - dataOffset < bytesRemInTrack) + bytesRemInTrack = bytesToRead - dataOffset; + + if (_stream->read(data + dataOffset, bytesRemInTrack) < bytesRemInTrack) + error("Error reading disk image"); + + ++track; + + sector = 0; + offset = 0; + + dataOffset += bytesRemInTrack; + } + + return new Common::MemoryReadStream(data, bytesToRead, DisposeAfterUse::YES); } const DataBlockPtr Files_Plain::getDataBlock(const Common::String &filename, uint offset) const { @@ -449,7 +451,7 @@ Common::SeekableReadStream *Files_DOS33::createReadStream(const Common::String & } bool Files_DOS33::open(const Common::String &filename) { - _disk = new DiskImage_DSK(); + _disk = new DiskImage(); if (!_disk->open(filename)) return false; diff --git a/engines/adl/disk.h b/engines/adl/disk.h index 43b9e387ba..1041f0cebd 100644 --- a/engines/adl/disk.h +++ b/engines/adl/disk.h @@ -73,41 +73,41 @@ protected: class DiskImage { public: DiskImage() : - _tracks(0), - _sectorsPerTrack(0), - _bytesPerSector(0) { - _f = new Common::File(); - } + _stream(nullptr), + _mode13(false) { } - virtual ~DiskImage() { - delete _f; + ~DiskImage() { + delete _stream; } - virtual bool open(const Common::String &filename) = 0; - virtual const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const = 0; - virtual Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0) const = 0; + bool open(const Common::String &filename); + const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const; + Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0, uint sectorsPerTrackToRead = 16) const; + void setMode13(bool enable) { _mode13 = enable; } protected: class DataBlock : public Adl::DataBlock { public: - DataBlock(const DiskImage *disk, uint track, uint sector, uint offset, uint size) : + DataBlock(const DiskImage *disk, uint track, uint sector, uint offset, uint size, bool mode13) : _track(track), _sector(sector), _offset(offset), _size(size), + _mode13(mode13), _disk(disk) { } Common::SeekableReadStream *createReadStream() const { - return _disk->createReadStream(_track, _sector, _offset, _size); + return _disk->createReadStream(_track, _sector, _offset, _size, (_mode13 ? 13 : 16)); } private: uint _track, _sector, _offset, _size; + bool _mode13; const DiskImage *_disk; }; - Common::File *_f; - uint _tracks, _sectorsPerTrack, _bytesPerSector; + Common::SeekableReadStream *_stream; + bool _mode13; // Older 13-sector format }; // Data in plain files @@ -117,30 +117,6 @@ public: Common::SeekableReadStream *createReadStream(const Common::String &filename, uint offset = 0) const; }; -// .DSK disk image - 35 tracks, 16 sectors per track, 256 bytes per sector -class DiskImage_DSK : public DiskImage { -public: - bool open(const Common::String &filename); - const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const; - Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0) const; -}; - -// .NIB disk image -class DiskImage_NIB : public DiskImage { -public: - DiskImage_NIB() : _memStream(nullptr) { } - virtual ~DiskImage_NIB() { - delete _memStream; - } - - bool open(const Common::String &filename); - const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const; - Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0) const; - -private: - Common::SeekableReadStream *_memStream; -}; - // Data in files contained in Apple DOS 3.3 disk image class Files_DOS33 : public Files { public: diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index b7f6eb9923..2cf50f72fc 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -55,6 +55,9 @@ static const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { 0xf2, 0x5e, 0x00 }; +// Opacity of the optional scanlines (percentage) +#define SCANLINE_OPACITY 75 + // Corresponding color in second palette #define PAL2(X) ((X) | 0x04) @@ -109,8 +112,6 @@ Display::Display() : _cursorPos(0), _showCursor(false) { - initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true); - _monochrome = !ConfMan.getBool("color"); _scanlines = ConfMan.getBool("scanlines"); @@ -135,6 +136,8 @@ Display::Display() : _textBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8()); createFont(); + + _startMillis = g_system->getMillis(); } Display::~Display() { @@ -334,14 +337,16 @@ void Display::writeFrameBuffer(const Common::Point &p, byte color, byte mask) { } void Display::showScanlines(bool enable) { - byte pal[COLOR_PALETTE_ENTRIES * 3] = { }; + byte pal[COLOR_PALETTE_ENTRIES * 3]; - if (enable) - g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); - else { - g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES); - g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); + g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES); + + if (enable) { + for (uint i = 0; i < ARRAYSIZE(pal); ++i) + pal[i] = pal[i] * (100 - SCANLINE_OPACITY) / 100; } + + g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); } static byte processColorBits(uint16 &bits, bool &odd, bool secondPal) { @@ -489,7 +494,11 @@ void Display::updateTextSurface() { r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); if (!(c & 0x80)) { - if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) + // Blink text. We subtract _startMillis to make this compatible + // with the event recorder, which returns offsetted values on + // playback. + const uint32 millisPassed = g_system->getMillis() - _startMillis; + if (!(c & 0x40) || ((millisPassed / 270) & 1)) r.translate(0, 4 * 8 * 2); } diff --git a/engines/adl/display.h b/engines/adl/display.h index bc27b7cb6b..e761e63f2e 100644 --- a/engines/adl/display.h +++ b/engines/adl/display.h @@ -102,6 +102,7 @@ private: Graphics::Surface *_font; uint _cursorPos; bool _showCursor; + uint32 _startMillis; }; } // End of namespace Adl diff --git a/engines/adl/hires0.cpp b/engines/adl/hires0.cpp new file mode 100644 index 0000000000..a348779e89 --- /dev/null +++ b/engines/adl/hires0.cpp @@ -0,0 +1,168 @@ +/* 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 "adl/hires0.h" +#include "adl/graphics.h" +#include "adl/disk.h" + +namespace Adl { + +void HiRes0Engine::init() { + _graphics = new Graphics_v2(*_display); + + _disk = new DiskImage(); + if (!_disk->open(IDS_HR0_DISK_IMAGE)) + error("Failed to open disk image '" IDS_HR0_DISK_IMAGE "'"); + + _disk->setMode13(true); + + StreamPtr stream(_disk->createReadStream(0x1f, 0x2, 0x00, 2)); + + // TODO: all these strings/offsets/etc are the same as hires2 + + for (uint i = 0; i < IDI_HR0_NUM_MESSAGES; ++i) + _messages.push_back(readDataBlockPtr(*stream)); + + // Read parser messages + stream.reset(_disk->createReadStream(0x1a, 0x1)); + _strings.verbError = readStringAt(*stream, 0x4f); + _strings.nounError = readStringAt(*stream, 0x8e); + _strings.enterCommand = readStringAt(*stream, 0xbc); + + // Read time string + stream.reset(_disk->createReadStream(0x19, 0x7, 0xd7)); + _strings_v2.time = readString(*stream, 0xff); + + // Read line feeds + stream.reset(_disk->createReadStream(0x19, 0xb, 0xf8, 1)); + _strings.lineFeeds = readString(*stream); + + // Read opcode strings + stream.reset(_disk->createReadStream(0x1a, 0x6, 0x00, 2)); + _strings_v2.saveInsert = readStringAt(*stream, 0x5f); + _strings_v2.saveReplace = readStringAt(*stream, 0xe5); + _strings_v2.restoreInsert = readStringAt(*stream, 0x132); + _strings_v2.restoreReplace = readStringAt(*stream, 0x1c2); + _strings.playAgain = readStringAt(*stream, 0x225); + _strings.pressReturn = readStringAt(*stream, 0x25f); + + _messageIds.cantGoThere = IDI_HR0_MSG_CANT_GO_THERE; + _messageIds.dontUnderstand = IDI_HR0_MSG_DONT_UNDERSTAND; + _messageIds.itemDoesntMove = IDI_HR0_MSG_ITEM_DOESNT_MOVE; + _messageIds.itemNotHere = IDI_HR0_MSG_ITEM_NOT_HERE; + _messageIds.thanksForPlaying = IDI_HR0_MSG_THANKS_FOR_PLAYING; + + // Load global picture data + stream.reset(_disk->createReadStream(0x19, 0xa, 0x80, 0)); + byte picNr; + while ((picNr = stream->readByte()) != 0xff) { + if (stream->eos() || stream->err()) + error("Error reading global pic list"); + + _pictures[picNr] = readDataBlockPtr(*stream); + } + + // Load item picture data + stream.reset(_disk->createReadStream(0x1e, 0x9, 0x05)); + for (uint i = 0; i < IDI_HR0_NUM_ITEM_PICS; ++i) { + stream->readByte(); // number + _itemPics.push_back(readDataBlockPtr(*stream)); + } + + // Load commands from executable + stream.reset(_disk->createReadStream(0x1d, 0x7, 0x00, 2)); + readCommands(*stream, _roomCommands); + + stream.reset(_disk->createReadStream(0x1f, 0x7, 0x00, 3)); + readCommands(*stream, _globalCommands); + + // Load dropped item offsets + stream.reset(_disk->createReadStream(0x1b, 0x4, 0x15)); + for (uint i = 0; i < IDI_HR0_NUM_ITEM_OFFSETS; ++i) { + Common::Point p; + p.x = stream->readByte(); + p.y = stream->readByte(); + _itemOffsets.push_back(p); + } + + // Load verbs + stream.reset(_disk->createReadStream(0x19, 0x0, 0x00, 3)); + loadWords(*stream, _verbs, _priVerbs); + + // Load nouns + stream.reset(_disk->createReadStream(0x22, 0x2, 0x00, 2)); + loadWords(*stream, _nouns, _priNouns); +} + +void HiRes0Engine::initGameState() { + _state.vars.resize(IDI_HR0_NUM_VARS); + + StreamPtr stream(_disk->createReadStream(0x21, 0x5, 0x0e, 2)); + + for (uint i = 0; i < IDI_HR0_NUM_ROOMS; ++i) { + Room room; + stream->readByte(); // number + for (uint j = 0; j < 6; ++j) + room.connections[j] = stream->readByte(); + room.data = readDataBlockPtr(*stream); + room.picture = stream->readByte(); + room.curPicture = stream->readByte(); + room.isFirstTime = stream->readByte(); + _state.rooms.push_back(room); + } + + stream.reset(_disk->createReadStream(0x21, 0x0)); + + byte id; + while ((id = stream->readByte()) != 0xff) { + Item item = Item(); + item.id = id; + item.noun = stream->readByte(); + item.room = stream->readByte(); + item.picture = stream->readByte(); + item.isLineArt = stream->readByte(); + item.position.x = stream->readByte(); + item.position.y = stream->readByte(); + item.state = stream->readByte(); + item.description = stream->readByte(); + + stream->readByte(); // Struct size + + byte picListSize = stream->readByte(); + + // Flag to keep track of what has been drawn on the screen + stream->readByte(); + + for (uint i = 0; i < picListSize; ++i) + item.roomPictures.push_back(stream->readByte()); + + _state.items.push_back(item); + } +} + +Engine *HiRes0Engine_create(OSystem *syst, const AdlGameDescription *gd) { + return new HiRes0Engine(syst, gd); +} + +} // End of namespace Adl diff --git a/engines/adl/hires0.h b/engines/adl/hires0.h new file mode 100644 index 0000000000..a3d8845a4e --- /dev/null +++ b/engines/adl/hires0.h @@ -0,0 +1,59 @@ +/* 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 ADL_HIRES0_H +#define ADL_HIRES0_H + +#include "adl/adl_v2.h" + +namespace Adl { + +#define IDS_HR0_DISK_IMAGE "MISSION.NIB" + +#define IDI_HR0_NUM_ROOMS 43 +#define IDI_HR0_NUM_MESSAGES 142 +#define IDI_HR0_NUM_VARS 40 +#define IDI_HR0_NUM_ITEM_PICS 2 +#define IDI_HR0_NUM_ITEM_OFFSETS 16 + +// Messages used outside of scripts +#define IDI_HR0_MSG_CANT_GO_THERE 110 +#define IDI_HR0_MSG_DONT_UNDERSTAND 112 +#define IDI_HR0_MSG_ITEM_DOESNT_MOVE 114 +#define IDI_HR0_MSG_ITEM_NOT_HERE 115 +#define IDI_HR0_MSG_THANKS_FOR_PLAYING 113 + +class HiRes0Engine : public AdlEngine_v2 { +public: + HiRes0Engine(OSystem *syst, const AdlGameDescription *gd) : + AdlEngine_v2(syst, gd) { } + ~HiRes0Engine() { } + +private: + // AdlEngine + void init(); + void initGameState(); +}; + +} // End of namespace Adl + +#endif diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp index 096d8ef496..26565c03c3 100644 --- a/engines/adl/hires1.cpp +++ b/engines/adl/hires1.cpp @@ -338,6 +338,7 @@ void HiRes1Engine::loadRoom(byte roomNr) { } void HiRes1Engine::showRoom() { + _state.curPicture = getCurRoom().curPicture; clearScreen(); loadRoom(_state.room); diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp index d8e8a65e29..14db237d82 100644 --- a/engines/adl/hires2.cpp +++ b/engines/adl/hires2.cpp @@ -34,6 +34,10 @@ namespace Adl { void HiRes2Engine::runIntro() const { + // This only works for the 16-sector re-release. The original + // release is not supported at this time, because we don't have + // access to it. + _disk->setMode13(false); StreamPtr stream(_disk->createReadStream(0x00, 0xd, 0x17, 1)); _display->setMode(DISPLAY_MODE_TEXT); @@ -45,15 +49,19 @@ void HiRes2Engine::runIntro() const { _display->printString(str); delay(2000); + + _disk->setMode13(true); } void HiRes2Engine::init() { _graphics = new Graphics_v2(*_display); - _disk = new DiskImage_DSK(); + _disk = new DiskImage(); if (!_disk->open(IDS_HR2_DISK_IMAGE)) error("Failed to open disk image '" IDS_HR2_DISK_IMAGE "'"); + _disk->setMode13(true); + StreamPtr stream(_disk->createReadStream(0x1f, 0x2, 0x00, 4)); for (uint i = 0; i < IDI_HR2_NUM_MESSAGES; ++i) diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp new file mode 100644 index 0000000000..22fd9c2f81 --- /dev/null +++ b/engines/adl/hires4.cpp @@ -0,0 +1,50 @@ +/* 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/system.h" +#include "common/debug.h" +#include "common/error.h" +#include "common/file.h" +#include "common/stream.h" + +#include "adl/hires4.h" +#include "adl/display.h" +#include "adl/graphics.h" +#include "adl/disk.h" + +namespace Adl { + +void HiRes4Engine::runIntro() const { +} + +void HiRes4Engine::init() { + _graphics = new Graphics_v2(*_display); +} + +void HiRes4Engine::initGameState() { +} + +Engine *HiRes4Engine_create(OSystem *syst, const AdlGameDescription *gd) { + return new HiRes4Engine(syst, gd); +} + +} // End of namespace Adl diff --git a/engines/adl/hires4.h b/engines/adl/hires4.h new file mode 100644 index 0000000000..f1c429ce38 --- /dev/null +++ b/engines/adl/hires4.h @@ -0,0 +1,45 @@ +/* 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 ADL_HIRES4_H +#define ADL_HIRES4_H + +#include "common/str.h" + +#include "adl/adl_v3.h" + +namespace Adl { + +class HiRes4Engine : public AdlEngine_v3 { +public: + HiRes4Engine(OSystem *syst, const AdlGameDescription *gd) : AdlEngine_v3(syst, gd) { } + +private: + // AdlEngine + void runIntro() const; + void init(); + void initGameState(); +}; + +} // End of namespace Adl + +#endif diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp index c42b4165a6..e9df7b513a 100644 --- a/engines/adl/hires6.cpp +++ b/engines/adl/hires6.cpp @@ -69,7 +69,7 @@ static Common::MemoryReadStream *loadSectors(DiskImage *disk, byte track, byte s } void HiRes6Engine::runIntro() const { - DiskImage_DSK *boot(new DiskImage_DSK()); + DiskImage *boot(new DiskImage()); if (!boot->open(disks[0])) error("Failed to open disk image '%s'", disks[0]); @@ -109,7 +109,7 @@ void HiRes6Engine::runIntro() const { } void HiRes6Engine::init() { - _boot = new DiskImage_DSK(); + _boot = new DiskImage(); _graphics = new Graphics_v2(*_display); if (!_boot->open(disks[0])) @@ -177,7 +177,7 @@ void HiRes6Engine::init() { void HiRes6Engine::loadDisk(byte disk) { delete _disk; - _disk = new DiskImage_NIB(); + _disk = new DiskImage(); if (!_disk->open(disks[disk])) error("Failed to open disk image '%s'", disks[disk]); @@ -317,6 +317,8 @@ void HiRes6Engine::initGameState() { } void HiRes6Engine::showRoom() { + _state.curPicture = getCurRoom().curPicture; + bool redrawPic = false; if (getVar(26) == 0xfe) diff --git a/engines/adl/hires6.h b/engines/adl/hires6.h index 4bd2bcc7cc..5ff039120b 100644 --- a/engines/adl/hires6.h +++ b/engines/adl/hires6.h @@ -25,7 +25,7 @@ #include "common/str.h" -#include "adl/adl_v3.h" +#include "adl/adl_v4.h" #include "adl/disk.h" namespace Common { @@ -56,10 +56,10 @@ struct DiskDataDesc { byte volume; }; -class HiRes6Engine : public AdlEngine_v3 { +class HiRes6Engine : public AdlEngine_v4 { public: HiRes6Engine(OSystem *syst, const AdlGameDescription *gd) : - AdlEngine_v3(syst, gd), + AdlEngine_v4(syst, gd), _boot(nullptr), _currVerb(0), _currNoun(0) { @@ -82,7 +82,7 @@ private: void loadDisk(byte disk); - DiskImage_DSK *_boot; + DiskImage *_boot; byte _currVerb, _currNoun; Common::Array<DiskDataDesc> _diskDataDesc; }; diff --git a/engines/adl/module.mk b/engines/adl/module.mk index 7ab37efc67..d1de2a6c02 100644 --- a/engines/adl/module.mk +++ b/engines/adl/module.mk @@ -4,6 +4,7 @@ MODULE_OBJS := \ adl.o \ adl_v2.o \ adl_v3.o \ + adl_v4.o \ console.o \ detection.o \ disk.o \ @@ -11,8 +12,10 @@ MODULE_OBJS := \ graphics.o \ graphics_v1.o \ graphics_v2.o \ + hires0.o \ hires1.o \ hires2.o \ + hires4.o \ hires6.o \ speaker.o diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp index d2f088dcd8..414fe49eb6 100644 --- a/engines/cine/cine.cpp +++ b/engines/cine/cine.cpp @@ -49,13 +49,14 @@ CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _rnd("cine") { - // Setup mixer - syncSoundSettings(); - DebugMan.addDebugChannel(kCineDebugScript, "Script", "Script debug level"); DebugMan.addDebugChannel(kCineDebugPart, "Part", "Part debug level"); DebugMan.addDebugChannel(kCineDebugSound, "Sound", "Sound debug level"); DebugMan.addDebugChannel(kCineDebugCollision, "Collision", "Collision debug level"); + + // Setup mixer + syncSoundSettings(); + _console = new CineConsole(this); g_cine = this; diff --git a/engines/director/configure.engine b/engines/director/configure.engine new file mode 100644 index 0000000000..41f9a6249d --- /dev/null +++ b/engines/director/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine director "Macromedia Director" no diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp new file mode 100644 index 0000000000..1f2e970539 --- /dev/null +++ b/engines/director/detection.cpp @@ -0,0 +1,252 @@ +/* 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 "base/plugins.h" + +#include "engines/advancedDetector.h" +#include "common/savefile.h" +#include "common/system.h" +#include "common/textconsole.h" + +#include "director/director.h" + +namespace Director { + +struct DirectorGameDescription { + ADGameDescription desc; + + DirectorGameID gameID; + uint16 version; +}; + +DirectorGameID DirectorEngine::getGameID() const { + return _gameDescription->gameID; +} + +Common::Platform DirectorEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + +uint16 DirectorEngine::getVersion() const { + return _gameDescription->version; +} + +Common::Language DirectorEngine::getLanguage() const { + return _gameDescription->desc.language; +} + +Common::String DirectorEngine::getEXEName() const { + return _gameDescription->desc.filesDescriptions[0].fileName; +} + +bool DirectorEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL); +} + +} // End of Namespace Director + +static const PlainGameDescriptor directorGames[] = { + { "director", "Macromedia Director Game" }, + { "directortest", "Macromedia Director Test Target" }, + { "theapartment", "The Apartment, D3 interactive demo" }, + { "gundam0079", "Gundam 0079: The War for Earth" }, + { "jewels", "Jewels of the Oracle" }, + { "jman", "The Journeyman Project" }, + { "majestic", "Majestic Part I: Alien Encounter" }, + { "melements", "Masters of the Elements" }, + { "spyclub", "Spy Club" }, + { "amber", "AMBER: Journeys Beyond"}, + { "vvvampire", "Victor Vector & Yondo: The Vampire's Coffin"}, + { "vvdinosaur", "Victor Vector & Yondo: The Last Dinosaur Egg"}, + { "warlock", "Spaceship Warlock"}, + { 0, 0 } +}; + +#include "director/detection_tables.h" + +static const char *directoryGlobs[] = { + "install", + 0 +}; + +class DirectorMetaEngine : public AdvancedMetaEngine { +public: + DirectorMetaEngine() : AdvancedMetaEngine(Director::gameDescriptions, sizeof(Director::DirectorGameDescription), directorGames) { + _singleId = "director"; + _maxScanDepth = 2, + _directoryGlobs = directoryGlobs; + } + + virtual const char *getName() const { + return "Macromedia Director"; + } + + virtual const char *getOriginalCopyright() const { + return "Macromedia Director (C) Macromedia"; + } + + const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; +}; + +bool DirectorMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const Director::DirectorGameDescription *gd = (const Director::DirectorGameDescription *)desc; + + if (gd) + *engine = new Director::DirectorEngine(syst, gd); + + return (gd != 0); +} + +static Director::DirectorGameDescription s_fallbackDesc = { + { + "director", + "", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO0() + }, + Director::GID_GENERIC, + 0 +}; + +static char s_fallbackFileNameBuffer[51]; + +const ADGameDescription *DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const { + // TODO: Handle Mac fallback + + // reset fallback description + Director::DirectorGameDescription *desc = &s_fallbackDesc; + desc->desc.gameId = "director"; + desc->desc.extra = ""; + desc->desc.language = Common::UNK_LANG; + desc->desc.flags = ADGF_NO_FLAGS; + desc->desc.platform = Common::kPlatformWindows; + desc->desc.guiOptions = GUIO0(); + desc->desc.filesDescriptions[0].fileName = 0; + desc->version = 0; + desc->gameID = Director::GID_GENERIC; + + for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { + if (file->isDirectory()) + continue; + + Common::String fileName = file->getName(); + fileName.toLowercase(); + if (!fileName.hasSuffix(".exe")) + continue; + + SearchMan.clear(); + SearchMan.addDirectory(file->getParent().getName(), file->getParent()); + + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(file->getName()); + + if (!stream) + continue; + + stream->seek(-4, SEEK_END); + + uint32 offset = stream->readUint32LE(); + + if (stream->eos() || offset == 0 || offset >= (uint32)(stream->size() - 4)) { + delete stream; + continue; + } + + stream->seek(offset); + + uint32 tag = stream->readUint32LE(); + + switch (tag) { + case MKTAG('3', '9', 'J', 'P'): + desc->version = 4; + break; + case MKTAG('P', 'J', '9', '5'): + desc->version = 5; + break; + case MKTAG('P', 'J', '0', '0'): + desc->version = 7; + break; + default: + // Prior to version 4, there was no tag here. So we'll use a bit of a + // heuristic to detect. The first field is the entry count, of which + // there should only be one. + if ((tag & 0xFFFF) != 1) { + delete stream; + continue; + } + + stream->skip(3); + + uint32 mmmSize = stream->readUint32LE(); + + if (stream->eos() || mmmSize == 0) { + delete stream; + continue; + } + + byte fileNameSize = stream->readByte(); + + if (stream->eos()) { + delete stream; + continue; + } + + stream->skip(fileNameSize); + byte directoryNameSize = stream->readByte(); + + if (stream->eos()) { + delete stream; + continue; + } + + stream->skip(directoryNameSize); + + if (stream->pos() != stream->size() - 4) { + delete stream; + continue; + } + + // Assume v3 at this point (for now at least) + desc->version = 3; + } + + strncpy(s_fallbackFileNameBuffer, fileName.c_str(), 50); + s_fallbackFileNameBuffer[50] = '\0'; + desc->desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer; + + warning("Director fallback detection D%d", desc->version); + + return (ADGameDescription *)desc; + } + + return 0; +} + +#if PLUGIN_ENABLED_DYNAMIC(DIRECTOR) + REGISTER_PLUGIN_DYNAMIC(DIRECTOR, PLUGIN_TYPE_ENGINE, DirectorMetaEngine); +#else + REGISTER_PLUGIN_STATIC(DIRECTOR, PLUGIN_TYPE_ENGINE, DirectorMetaEngine); +#endif diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h new file mode 100644 index 0000000000..e03b831fa3 --- /dev/null +++ b/engines/director/detection_tables.h @@ -0,0 +1,482 @@ +/* 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 DIRECTOR_DETECTION_TABLES_H +#define DIRECTOR_DETECTION_TABLES_H + +namespace Director { + +static const DirectorGameDescription gameDescriptions[] = { + { + { + "directortest", + "", + AD_ENTRY1("lingotests.lingo", 0), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_TEST, + 3 + }, + + { // Generic D3 entry + { + "director", + "", + AD_ENTRY1("D3", 0), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + { + { + "theapartment", + "", + AD_ENTRY1s("Main Menu", "9e838fe1a6af7992d656ca325e38dee5", 47911), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "gundam0079", + "", + AD_ENTRY1("Gundam0079.exe", "1a7acbba10a7246ba58c1d53fc7203f5"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + "gundam0079", + "", + AD_ENTRY1("Gundam0079", "4c38a51a21a1ad231f218c4786ff771d"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + "jewels", + "", + AD_ENTRY1("JEWELS.EXE", "bb6d81471d166088260090472c6c3a87"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + { + { + "jewels", + "", + AD_ENTRY1("Jewels.exe", "c1a2e8b7e41fa204009324a9c7db1030"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 7 + }, + + { + { + "jewels", + "Two-Minute Demo", + AD_ENTRY1("DEMO.EXE", "ebee52d3c4280674c600177df5b09da0"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + // Note: There are four versions of the binary included on the disc. + // 5.6, 6, and 9 Meg variants all exist too. + { + { + "jewels", + "", + AD_ENTRY1("Jewels 11 Meg", "339c89a148c4ff2c5c815c62ac006325"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + { + { + "jewels", + "Two-Minute Demo", + AD_ENTRY1("Two-Minute Demo", "01be45e7241194dad07938e7059b88e3"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK | ADGF_DEMO, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + { + { + "jewels", + "", + AD_ENTRY1("Jewels of the Oracle", "fa52f0136cde568a46249ce74f01a324"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 7 + }, + + { + { + "jewels", + "Demo", + AD_ENTRY1("JEWELS.EXE", "abcc448c035e88d4edb4a29034fd1e34"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS | ADGF_DEMO, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + { + { + "jman", + "", + AD_ENTRY1s("JMAN.EXE", "7c8230a804abf9353b05627a675b5ffb", 375282), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "jman", + "", + AD_ENTRY1s("JMDEMO.EXE", "7c8230a804abf9353b05627a675b5ffb", 375305), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "jman", + "", + AD_ENTRY1("JOURNEY.EXE", "65d06b5fef155a2473434571aff5bc29"), + Common::JA_JPN, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "jman", + "Turbo!", + AD_ENTRY1("JMP Turbo\xE2\x84\xA2", "cc3321069072b90f091f220bba16e4d4"), // Trademark symbol (UTF-8) + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + { + { + "majestic", + "", + AD_ENTRY1("MAJESTIC.EXE", "624267f70253e5327981003a6fc0aeba"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 4 + }, + + { + { + // Masters of the Elements - English (from rootfather) + // Developed by IJsfontein, published by Tivola + // File version of MVM.EXE is 6.0.2.32 + // The game disc is a hybrid CD-ROM containing both the Windows and the Macintosh release. + + "melements", "", + { + {"CHECK.DXR", 0, "c31ee30eebd24a8cf31691fc9926daa4", 901820}, + {"MVM.EXE", 0, 0, 2565921}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + // Masters of the Elements - English (from rootfather) + + "melements", "", + { + {"check.dxr", 0, "36f42340e819d1532c850880afe16581", 898206}, + {"Masters of the Elements", 0, 0, 1034962}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + // Masters of the Elements - German (from rootfather) + // Released in Germany as "Meister Zufall und die Herrscher der Elemente" + // Developed by IJsfontein, published by Tivola + // File version of MVM.EXE is 6.0.2.32 + // The game disc is a hybrid CD-ROM containing both the Windows and the Macintosh release. + + "melements", "", + { + {"CHECK.DXR", 0, "d1cd0ed95b0e30597e0089bf3e5caf0f", 575414}, + {"MVM.EXE", 0, 0, 1512503}, + AD_LISTEND + }, + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + // Masters of the Elements - German (from rootfather) + + "melements", "", + { + {"check.dxr", 0, "9c81934b7616ab077f44825b8afaa83e", 575426}, + {"Meister Zufall", 0, 0, 1034962}, + AD_LISTEND + }, + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + "spyclub", + "", + AD_ENTRY1("SPYCLUB.EXE", "65d06b5fef155a2473434571aff5bc29"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "amber", + "", + AD_ENTRY1("amber_jb.exe", "1a7acbba10a7246ba58c1d53fc7203f5"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 5 + }, + + { + { + "vvvampire", + "", + AD_ENTRY1("VAMPIRE.EXE", "88f4f7406f34ec36e751a64f7c76f2c4"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "vvvampire", + "", + AD_ENTRY1("The Vampire's Coffin", "d41d8cd98f00b204e9800998ecf8427e"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "vvdinosaur", + "", + AD_ENTRY1("DINOSAUR.EXE", "4e6303630f4dd588e730d09241cf7e76"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "vvdinosaur", + "", + AD_ENTRY1("Start Game", "d41d8cd98f00b204e9800998ecf8427e"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 3 + }, + + { + { + "warlock", + "", + AD_ENTRY1s("Spaceship Warlock.bin", "cfa68a1bc49251497ebde18e5fc9c217", 271107), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_MACRESFORK, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 2 + }, + + { + { + "warlock", + "", + AD_ENTRY1s("SSWARLCK.EXE", "65d06b5fef155a2473434571aff5bc29", 370867), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 2 + }, + + { + { + "warlock", + "", + AD_ENTRY1s("SSWDEMO.EXE", "65d06b5fef155a2473434571aff5bc29", 370934), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + GUIO1(GUIO_NOASPECT) + }, + GID_GENERIC, + 2 + }, + + { AD_TABLE_END_MARKER, GID_GENERIC, 0 } +}; + +} // End of Namespace Director + +#endif diff --git a/engines/director/director.cpp b/engines/director/director.cpp new file mode 100644 index 0000000000..cf66c851cd --- /dev/null +++ b/engines/director/director.cpp @@ -0,0 +1,367 @@ +/* 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/config-manager.h" +#include "common/debug-channels.h" +#include "common/error.h" +#include "common/macresman.h" + +#include "graphics/macgui/macwindowmanager.h" + +#include "director/director.h" +#include "director/images.h" +#include "director/resource.h" +#include "director/score.h" +#include "director/sound.h" +#include "director/lingo/lingo.h" + +namespace Director { + +DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), + _rnd("director") { + DebugMan.addDebugChannel(kDebugLingoExec, "lingoexec", "Lingo Execution"); + DebugMan.addDebugChannel(kDebugLingoCompile, "lingocompile", "Lingo Compilation"); + DebugMan.addDebugChannel(kDebugLoading, "loading", "Loading"); + DebugMan.addDebugChannel(kDebugImages, "images", "Image drawing"); + + if (!_mixer->isReady()) + error("Sound initialization failed"); + + // Setup mixer + syncSoundSettings(); + + _sharedCasts = nullptr; + _sharedSound = nullptr; + _sharedBMP = nullptr; + _sharedSTXT = nullptr; + _sharedDIB = nullptr; + + _currentScore = nullptr; + _soundManager = nullptr; + _currentPalette = nullptr; + _currentPaletteLength = 0; + _lingo = nullptr; + + _mainArchive = nullptr; + _macBinary = nullptr; + + _movies = nullptr; + + _wm = nullptr; + + const Common::FSNode gameDataDir(ConfMan.get("path")); + SearchMan.addSubDirectoryMatching(gameDataDir, "data"); + SearchMan.addSubDirectoryMatching(gameDataDir, "install"); +} + +DirectorEngine::~DirectorEngine() { + delete _sharedCasts; + delete _sharedSound; + delete _sharedBMP; + delete _sharedSTXT; + delete _sharedDIB; + + delete _currentScore; + delete _mainArchive; + delete _macBinary; + delete _soundManager; + delete _lingo; +} + +Common::Error DirectorEngine::run() { + debug("Starting v%d Director game", getVersion()); + + //FIXME + _sharedMMM = "SHARDCST.MMM"; + + _currentPalette = nullptr; + + _macBinary = nullptr; + _soundManager = nullptr; + + _wm = new Graphics::MacWindowManager; + + _lingo = new Lingo(this); + _soundManager = new DirectorSound(); + + if (getGameID() == GID_TEST) { + _mainArchive = nullptr; + _currentScore = nullptr; + + _lingo->runTests(); + + return Common::kNoError; + } + + //FIXME + //_mainArchive = new RIFFArchive(); + //_mainArchive->openFile("bookshelf_example.mmm"); + + if (getPlatform() == Common::kPlatformWindows) + loadEXE(); + else + loadMac(); + + _currentScore = new Score(this); + debug(0, "Score name %s", _currentScore->getMacName().c_str()); + + _currentScore->loadArchive(); + _currentScore->startLoop(); + + return Common::kNoError; +} + +Common::HashMap<Common::String, Score *> DirectorEngine::loadMMMNames(Common::String folder) { + Common::FSNode directory(folder); + Common::FSList movies; + + Common::HashMap<Common::String, Score *> nameMap; + if (!directory.getChildren(movies, Common::FSNode::kListFilesOnly)) + return nameMap; + + if (!movies.empty()) { + for (Common::FSList::const_iterator i = movies.begin(); i != movies.end(); ++i) { + if (i->getName() == _sharedMMM) { + loadSharedCastsFrom(i->getPath()); + continue; + } + + RIFFArchive *arc = new RIFFArchive(); + arc->openFile(i->getPath()); + Score *sc = new Score(this); + nameMap[sc->getMacName()] = sc; + } + } + + return nameMap; +} + +void DirectorEngine::loadEXE() { + Common::SeekableReadStream *exeStream = SearchMan.createReadStreamForMember(getEXEName()); + if (!exeStream) + error("Failed to open EXE '%s'", getEXEName().c_str()); + + _lingo->processEvent(kEventStart, 0); + + exeStream->seek(-4, SEEK_END); + exeStream->seek(exeStream->readUint32LE()); + + switch (getVersion()) { + case 3: + loadEXEv3(exeStream); + break; + case 4: + loadEXEv4(exeStream); + break; + case 5: + loadEXEv5(exeStream); + break; + case 7: + loadEXEv7(exeStream); + break; + default: + error("Unhandled Windows EXE version %d", getVersion()); + } +} + +void DirectorEngine::loadEXEv3(Common::SeekableReadStream *stream) { + uint16 entryCount = stream->readUint16LE(); + if (entryCount != 1) + error("Unhandled multiple entry v3 EXE"); + + stream->skip(5); // unknown + + stream->readUint32LE(); // Main MMM size + Common::String mmmFileName = readPascalString(*stream); + Common::String directoryName = readPascalString(*stream); + + debug("Main MMM: '%s'", mmmFileName.c_str()); + debug("Directory Name: '%s'", directoryName.c_str()); + + _mainArchive = new RIFFArchive(); + + if (!_mainArchive->openFile(mmmFileName)) + error("Could not open '%s'", mmmFileName.c_str()); + + delete stream; +} + +void DirectorEngine::loadEXEv4(Common::SeekableReadStream *stream) { + if (stream->readUint32BE() != MKTAG('P', 'J', '9', '3')) + error("Invalid projector tag found in v4 EXE"); + + uint32 rifxOffset = stream->readUint32LE(); + /* uint32 fontMapOffset = */ stream->readUint32LE(); + /* uint32 resourceForkOffset1 = */ stream->readUint32LE(); + /* uint32 resourceForkOffset2 = */ stream->readUint32LE(); + stream->readUint32LE(); // graphics DLL offset + stream->readUint32LE(); // sound DLL offset + /* uint32 rifxOffsetAlt = */ stream->readUint32LE(); // equivalent to rifxOffset + + loadEXERIFX(stream, rifxOffset); +} + +void DirectorEngine::loadEXEv5(Common::SeekableReadStream *stream) { + if (stream->readUint32LE() != MKTAG('P', 'J', '9', '5')) + error("Invalid projector tag found in v5 EXE"); + + uint32 rifxOffset = stream->readUint32LE(); + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + /* uint16 screenWidth = */ stream->readUint16LE(); + /* uint16 screenHeight = */ stream->readUint16LE(); + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + /* uint32 fontMapOffset = */ stream->readUint32LE(); + + loadEXERIFX(stream, rifxOffset); +} + +void DirectorEngine::loadEXEv7(Common::SeekableReadStream *stream) { + if (stream->readUint32LE() != MKTAG('P', 'J', '0', '0')) + error("Invalid projector tag found in v7 EXE"); + + uint32 rifxOffset = stream->readUint32LE(); + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + stream->readUint32LE(); // unknown + stream->readUint32LE(); // some DLL offset + + loadEXERIFX(stream, rifxOffset); +} + +void DirectorEngine::loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset) { + _mainArchive = new RIFXArchive(); + + if (!_mainArchive->openStream(stream, offset)) + error("Failed to load RIFX from EXE"); +} + +void DirectorEngine::loadMac() { + if (getVersion() < 4) { + // The data is part of the resource fork of the executable + _mainArchive = new MacArchive(); + + if (!_mainArchive->openFile(getEXEName())) + error("Failed to open Mac binary '%s'", getEXEName().c_str()); + } else { + // The RIFX is located in the data fork of the executable + _macBinary = new Common::MacResManager(); + + if (!_macBinary->open(getEXEName()) || !_macBinary->hasDataFork()) + error("Failed to open Mac binary '%s'", getEXEName().c_str()); + + Common::SeekableReadStream *dataFork = _macBinary->getDataFork(); + _mainArchive = new RIFXArchive(); + + // First we need to detect PPC vs. 68k + + uint32 tag = dataFork->readUint32BE(); + uint32 startOffset; + + if (SWAP_BYTES_32(tag) == MKTAG('P', 'J', '9', '3') || tag == MKTAG('P', 'J', '9', '5') || tag == MKTAG('P', 'J', '0', '0')) { + // PPC: The RIFX shares the data fork with the binary + startOffset = dataFork->readUint32BE(); + } else { + // 68k: The RIFX is the only thing in the data fork + startOffset = 0; + } + + if (!_mainArchive->openStream(dataFork, startOffset)) + error("Failed to load RIFX from Mac binary"); + } +} + +Common::String DirectorEngine::readPascalString(Common::SeekableReadStream &stream) { + byte length = stream.readByte(); + Common::String x; + + while (length--) + x += (char)stream.readByte(); + + return x; +} + +void DirectorEngine::setPalette(byte *palette, uint16 count) { + _currentPalette = palette; + _currentPaletteLength = count; +} + +void DirectorEngine::loadSharedCastsFrom(Common::String filename) { + Archive *shardcst; + + if (getVersion() < 4) { + shardcst = new RIFFArchive(); + } else { + shardcst = new RIFXArchive(); + } + + shardcst->openFile(filename); + + Score *castScore = new Score(this); + Common::SeekableSubReadStreamEndian *castStream = shardcst->getResource(MKTAG('V','W','C','R'), 1024); + + castScore->loadCastData(*castStream); + *_sharedCasts = castScore->_casts; + + Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' ')); + + if (dib.size() != 0) { + Common::Array<uint16>::iterator iterator; + for (iterator = dib.begin(); iterator != dib.end(); ++iterator) { + debug(3, "Shared DIB %d", *iterator); + _sharedDIB->setVal(*iterator, shardcst->getResource(MKTAG('D','I','B',' '), *iterator)); + } + } + + Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T')); + + if (stxt.size() != 0) { + Common::Array<uint16>::iterator iterator; + for (iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { + debug(3, "Shared STXT %d", *iterator); + _sharedSTXT->setVal(*iterator, shardcst->getResource(MKTAG('S','T','X','T'), *iterator)); + } + } + + Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D')); + + if (bmp.size() != 0) { + Common::Array<uint16>::iterator iterator; + for (iterator = bmp.begin(); iterator != bmp.end(); ++iterator) { + _sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator)); + } + } + + Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' ')); + + if (stxt.size() != 0) { + Common::Array<uint16>::iterator iterator; + for (iterator = sound.begin(); iterator != sound.end(); ++iterator) { + _sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator)); + } + } +} + +} // End of namespace Director diff --git a/engines/director/director.h b/engines/director/director.h new file mode 100644 index 0000000000..97f8a7097d --- /dev/null +++ b/engines/director/director.h @@ -0,0 +1,128 @@ +/* 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 DIRECTOR_DIRECTOR_H +#define DIRECTOR_DIRECTOR_H + +#include "common/random.h" +#include "common/substream.h" + +#include "common/hashmap.h" +#include "engines/engine.h" + +namespace Common { +class MacResManager; +} + +namespace Graphics { +class MacWindowManager; +} + +namespace Director { + +enum DirectorGameID { + GID_GENERIC, + GID_TEST +}; + +class Archive; +struct DirectorGameDescription; +class DirectorSound; +class Lingo; +class Score; +struct Cast; + +enum { + kDebugLingoExec = 1 << 0, + kDebugLingoCompile = 1 << 1, + kDebugLoading = 1 << 2, + kDebugImages = 1 << 3 +}; + + +class DirectorEngine : public ::Engine { +public: + DirectorEngine(OSystem *syst, const DirectorGameDescription *gameDesc); + ~DirectorEngine(); + + // Detection related functions + + DirectorGameID getGameID() const; + uint16 getVersion() const; + Common::Platform getPlatform() const; + Common::Language getLanguage() const; + Common::String getEXEName() const; + DirectorSound *getSoundManager() const { return _soundManager; } + Archive *getMainArchive() const { return _mainArchive; } + Lingo *getLingo() const { return _lingo; } + Score *getCurrentScore() const { return _currentScore; } + void setPalette(byte *palette, uint16 count); + bool hasFeature(EngineFeature f) const; + const byte *getPalette() const { return _currentPalette; } + uint16 getPaletteColorCount() const { return _currentPaletteLength; } + void loadSharedCastsFrom(Common::String filename); + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedDIB() const { return _sharedDIB; } + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedBMP() const { return _sharedBMP; } + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *getSharedSTXT() const { return _sharedSTXT; } + Common::HashMap<int, Cast *> *getSharedCasts() const { return _sharedCasts; } + + Common::HashMap<Common::String, Score *> *_movies; + Score *_currentScore; + + Common::RandomSource _rnd; + Graphics::MacWindowManager *_wm; + +protected: + virtual Common::Error run(); + +private: + const DirectorGameDescription *_gameDescription; + + Common::HashMap<Common::String, Score *> loadMMMNames(Common::String folder); + void loadEXE(); + void loadEXEv3(Common::SeekableReadStream *stream); + void loadEXEv4(Common::SeekableReadStream *stream); + void loadEXEv5(Common::SeekableReadStream *stream); + void loadEXEv7(Common::SeekableReadStream *stream); + void loadEXERIFX(Common::SeekableReadStream *stream, uint32 offset); + void loadMac(); + + Common::String readPascalString(Common::SeekableReadStream &stream); + + Common::String _sharedMMM; + Common::HashMap<int, Cast *> *_sharedCasts; + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *_sharedDIB; + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *_sharedSTXT; + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *_sharedSound; + Common::HashMap<int, Common::SeekableSubReadStreamEndian *> *_sharedBMP; + + Archive *_mainArchive; + Common::MacResManager *_macBinary; + DirectorSound *_soundManager; + byte *_currentPalette; + uint16 _currentPaletteLength; + Lingo *_lingo; +}; + +} // End of namespace Director + +#endif diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp new file mode 100644 index 0000000000..3d5d8b6a4b --- /dev/null +++ b/engines/director/frame.cpp @@ -0,0 +1,784 @@ +/* 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/system.h" +#include "graphics/font.h" +#include "graphics/macgui/macwindowmanager.h" +#include "image/bmp.h" + +#include "director/director.h" +#include "director/frame.h" +#include "director/images.h" +#include "director/resource.h" +#include "director/score.h" +#include "director/sprite.h" + +namespace Director { + +Frame::Frame(DirectorEngine *vm) { + _vm = vm; + _transDuration = 0; + _transType = kTransNone; + _transArea = 0; + _transChunkSize = 0; + _tempo = 0; + + _sound1 = 0; + _sound2 = 0; + _soundType1 = 0; + _soundType2 = 0; + + _actionId = 0; + _skipFrameFlag = 0; + _blend = 0; + + _palette = NULL; + + _sprites.resize(CHANNEL_COUNT); + + for (uint16 i = 0; i < _sprites.size(); i++) { + Sprite *sp = new Sprite(); + _sprites[i] = sp; + } +} + +Frame::Frame(const Frame &frame) { + _vm = frame._vm; + _actionId = frame._actionId; + _transArea = frame._transArea; + _transDuration = frame._transDuration; + _transType = frame._transType; + _transChunkSize = frame._transChunkSize; + _tempo = frame._tempo; + _sound1 = frame._sound1; + _sound2 = frame._sound2; + _soundType1 = frame._soundType1; + _soundType2 = frame._soundType2; + _skipFrameFlag = frame._skipFrameFlag; + _blend = frame._blend; + _palette = new PaletteInfo(); + + debugC(1, kDebugLoading, "Frame. action: %d transType: %d transDuration: %d", _actionId, _transType, _transDuration); + + _sprites.resize(CHANNEL_COUNT); + + for (uint16 i = 0; i < CHANNEL_COUNT; i++) { + _sprites[i] = new Sprite(*frame._sprites[i]); + } +} + +Frame::~Frame() { + delete _palette; +} + +void Frame::readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) { + if (offset >= 32) { + if (size <= 16) + readSprite(stream, offset, size); + else { + //read > 1 sprites channel + while (size > 16) { + byte spritePosition = (offset - 32) / 16; + uint16 nextStart = (spritePosition + 1) * 16 + 32; + uint16 needSize = nextStart - offset; + readSprite(stream, offset, needSize); + offset += needSize; + size -= needSize; + } + readSprite(stream, offset, size); + } + } else { + readMainChannels(stream, offset, size); + } +} + +void Frame::readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) { + uint16 finishPosition = offset + size; + + while (offset < finishPosition) { + switch(offset) { + case kScriptIdPosition: + _actionId = stream.readByte(); + offset++; + break; + case kSoundType1Position: + _soundType1 = stream.readByte(); + offset++; + break; + case kTransFlagsPosition: { + uint8 transFlags = stream.readByte(); + if (transFlags & 0x80) + _transArea = 1; + else + _transArea = 0; + _transDuration = transFlags & 0x7f; + offset++; + } + break; + case kTransChunkSizePosition: + _transChunkSize = stream.readByte(); + offset++; + break; + case kTempoPosition: + _tempo = stream.readByte(); + offset++; + break; + case kTransTypePosition: + _transType = static_cast<TransitionType>(stream.readByte()); + offset++; + break; + case kSound1Position: + _sound1 = stream.readUint16(); + offset+=2; + break; + case kSkipFrameFlagsPosition: + _skipFrameFlag = stream.readByte(); + offset++; + break; + case kBlendPosition: + _blend = stream.readByte(); + offset++; + break; + case kSound2Position: + _sound2 = stream.readUint16(); + offset += 2; + break; + case kSound2TypePosition: + _soundType2 = stream.readByte(); + offset += 1; + break; + case kPaletePosition: + if (stream.readUint16()) + readPaletteInfo(stream); + offset += 16; + break; + default: + offset++; + stream.readByte(); + debug("Field Position %d, Finish Position %d", offset, finishPosition); + break; + } + } +} + +void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) { + _palette->firstColor = stream.readByte(); + _palette->lastColor = stream.readByte(); + _palette->flags = stream.readByte(); + _palette->speed = stream.readByte(); + _palette->frameCount = stream.readUint16(); + stream.skip(8); //unknown +} + +void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) { + uint16 spritePosition = (offset - 32) / 16; + uint16 spriteStart = spritePosition * 16 + 32; + + uint16 fieldPosition = offset - spriteStart; + uint16 finishPosition = fieldPosition + size; + + Sprite &sprite = *_sprites[spritePosition]; + + while (fieldPosition < finishPosition) { + switch (fieldPosition) { + case kSpritePositionUnk1: + /*byte x1 = */ stream.readByte(); + fieldPosition++; + break; + case kSpritePositionEnabled: + sprite._enabled = (stream.readByte() != 0); + fieldPosition++; + break; + case kSpritePositionUnk2: + /*byte x2 = */ stream.readUint16(); + fieldPosition += 2; + break; + case kSpritePositionFlags: + sprite._flags = stream.readUint16(); + sprite._ink = static_cast<InkType>(sprite._flags & 0x3f); + + if (sprite._flags & 0x40) + sprite._trails = 1; + else + sprite._trails = 0; + + fieldPosition += 2; + break; + case kSpritePositionCastId: + sprite._castId = stream.readUint16(); + fieldPosition += 2; + break; + case kSpritePositionY: + sprite._startPoint.y = stream.readUint16(); + fieldPosition += 2; + break; + case kSpritePositionX: + sprite._startPoint.x = stream.readUint16(); + fieldPosition += 2; + break; + case kSpritePositionWidth: + sprite._width = stream.readUint16(); + fieldPosition += 2; + break; + case kSpritePositionHeight: + sprite._height = stream.readUint16(); + fieldPosition += 2; + break; + default: + //end cycle, go to next sprite channel + readSprite(stream, spriteStart + 16, finishPosition - fieldPosition); + fieldPosition = finishPosition; + break; + } + } +} + +void Frame::prepareFrame(Score *score) { + renderSprites(*score->_surface, false); + renderSprites(*score->_trailSurface, true); + + if (_transType != 0) + //TODO Handle changing area case + playTransition(score); + + if (_sound1 != 0 || _sound2 != 0) { + playSoundChannel(); + } + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, score->_surface->getBounds().width(), score->_surface->getBounds().height()); +} + +void Frame::playSoundChannel() { + debug(0, "Sound2 %d", _sound2); + debug(0, "Sound1 %d", _sound1); +} + +void Frame::playTransition(Score *score) { + uint16 duration = _transDuration * 250; // _transDuration in 1/4 of sec + duration = (duration == 0 ? 250 : duration); // director support transition duration = 0, but animation play like value = 1, idk. + + if (_transChunkSize == 0) + _transChunkSize = 1; //equal 1 step + + uint16 stepDuration = duration / _transChunkSize; + uint16 steps = duration / stepDuration; + + switch (_transType) { + case kTransCoverDown: + { + uint16 stepSize = score->_movieRect.height() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setHeight(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverUp: + { + uint16 stepSize = score->_movieRect.height() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setHeight(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverRight: { + uint16 stepSize = score->_movieRect.width() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setWidth(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverLeft: { + uint16 stepSize = score->_movieRect.width() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setWidth(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverUpLeft: { + uint16 stepSize = score->_movieRect.width() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setWidth(stepSize * i); + r.setHeight(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, score->_movieRect.height() - stepSize * i, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverUpRight: { + uint16 stepSize = score->_movieRect.width() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setWidth(stepSize * i); + r.setHeight(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverDownLeft: { + uint16 stepSize = score->_movieRect.width() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setWidth(stepSize * i); + r.setHeight(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + case kTransCoverDownRight: { + uint16 stepSize = score->_movieRect.width() / steps; + Common::Rect r = score->_movieRect; + + for (uint16 i = 1; i < steps; i++) { + r.setWidth(stepSize * i); + r.setHeight(stepSize * i); + + g_system->delayMillis(stepDuration); + score->processEvents(); + + g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height()); + g_system->updateScreen(); + } + } + break; + default: + warning("Unhandled transition type %d %d %d", _transType, duration, _transChunkSize); + break; + + } +} + +void Frame::renderSprites(Graphics::ManagedSurface &surface, bool renderTrail) { + for (uint16 i = 0; i < CHANNEL_COUNT; i++) { + if (_sprites[i]->_enabled) { + if ((_sprites[i]->_trails == 0 && renderTrail) || (_sprites[i]->_trails == 1 && !renderTrail)) + continue; + + Cast *cast; + if (!_vm->_currentScore->_casts.contains(_sprites[i]->_castId)) { + if (!_vm->getSharedCasts()->contains(_sprites[i]->_castId)) { + warning("Cast id %d not found", _sprites[i]->_castId); + continue; + } else { + cast = _vm->getSharedCasts()->getVal(_sprites[i]->_castId); + } + } else { + cast = _vm->_currentScore->_casts[_sprites[i]->_castId]; + } + + if (cast->type == kCastText) { + renderText(surface, i); + continue; + } + + Image::ImageDecoder *img = getImageFrom(_sprites[i]->_castId); + + if (!img) { + warning("Image with id %d not found", _sprites[i]->_castId); + continue; + } + + if (!img->getSurface()) { + //TODO + //BMPDecoder doesnt cover all BITD resources (not all have first two bytes 'BM') + //Some BITD's first two bytes 0x6 0x0 + warning("Can not load image %d", _sprites[i]->_castId); + continue; + } + + uint32 regX = static_cast<BitmapCast *>(_sprites[i]->_cast)->regX; + uint32 regY = static_cast<BitmapCast *>(_sprites[i]->_cast)->regY; + uint32 rectLeft = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.left; + uint32 rectTop = static_cast<BitmapCast *>(_sprites[i]->_cast)->initialRect.top; + + int x = _sprites[i]->_startPoint.x - regX + rectLeft; + int y = _sprites[i]->_startPoint.y - regY + rectTop; + int height = _sprites[i]->_height; + int width = _sprites[i]->_width; + + Common::Rect drawRect = Common::Rect(x, y, x + width, y + height); + _drawRects.push_back(drawRect); + + switch (_sprites[i]->_ink) { + case kInkTypeCopy: + surface.blitFrom(*img->getSurface(), Common::Point(x, y)); + break; + case kInkTypeTransparent: + //FIXME: is it always white (last entry in pallette)? + surface.transBlitFrom(*img->getSurface(), Common::Point(x, y), _vm->getPaletteColorCount() - 1); + break; + case kInkTypeBackgndTrans: + drawBackgndTransSprite(surface, *img->getSurface(), drawRect); + break; + case kInkTypeMatte: + drawMatteSprite(surface, *img->getSurface(), drawRect); + break; + case kInkTypeGhost: + drawGhostSprite(surface, *img->getSurface(), drawRect); + break; + case kInkTypeReverse: + drawReverseSprite(surface, *img->getSurface(), drawRect); + break; + default: + warning("Unhandled ink type %d", _sprites[i]->_ink); + surface.blitFrom(*img->getSurface(), Common::Point(x, y)); + break; + } + } + } +} + +void Frame::renderButton(Graphics::ManagedSurface &surface, uint16 spriteId) { + renderText(surface, spriteId); + + uint16 castID = _sprites[spriteId]->_castId; + ButtonCast *button = static_cast<ButtonCast *>(_vm->_currentScore->_casts[castID]); + + uint32 rectLeft = button->initialRect.left; + uint32 rectTop = button->initialRect.top; + + int x = _sprites[spriteId]->_startPoint.x + rectLeft; + int y = _sprites[spriteId]->_startPoint.y + rectTop; + int height = _sprites[spriteId]->_height; + int width = _sprites[spriteId]->_width; + + switch (button->buttonType) { + case kTypeCheckBox: + //Magic numbers: checkbox square need to move left about 5px from text and 12px side size (d4) + surface.frameRect(Common::Rect(x - 17, y, x + 12, y + 12), 0); + break; + case kTypeButton: + surface.frameRect(Common::Rect(x, y, x + width, y + height), 0); + break; + case kTypeRadio: + warning("STUB: renderButton: kTypeRadio"); + break; + } +} + +Image::ImageDecoder *Frame::getImageFrom(uint16 spriteId) { + uint16 imgId = spriteId + 1024; + Image::ImageDecoder *img = NULL; + + if (_vm->_currentScore->getArchive()->hasResource(MKTAG('D', 'I', 'B', ' '), imgId)) { + img = new DIBDecoder(); + img->loadStream(*_vm->_currentScore->getArchive()->getResource(MKTAG('D', 'I', 'B', ' '), imgId)); + return img; + } + + if (_vm->getSharedDIB() != NULL && _vm->getSharedDIB()->contains(imgId)) { + img = new DIBDecoder(); + img->loadStream(*_vm->getSharedDIB()->getVal(imgId)); + return img; + } + + if (_vm->_currentScore->getArchive()->hasResource(MKTAG('B', 'I', 'T', 'D'), imgId)) { + Common::SeekableReadStream *pic = _vm->_currentScore->getArchive()->getResource(MKTAG('B', 'I', 'T', 'D'), imgId); + + if (_vm->getVersion() < 4) { + BitmapCast *bc = static_cast<BitmapCast *>(_vm->_currentScore->_casts[spriteId]); + int w = bc->initialRect.width(), h = bc->initialRect.height(); + + debugC(2, kDebugImages, "id: %d, w: %d, h: %d, flags: %x, some: %x, unk1: %d, unk2: %d", + imgId, w, h, bc->flags, bc->someFlaggyThing, bc->unk1, bc->unk2); + img = new BITDDecoder(w, h); + } else { + img = new Image::BitmapDecoder(); + } + + if (debugChannelSet(8, kDebugLoading)) { + Common::SeekableReadStream *s = pic; + byte buf[1024]; + int n = s->read(buf, 1024); + Common::hexdump(buf, n); + } + + img->loadStream(*pic); + return img; + } + + if (_vm->getSharedBMP() != NULL && _vm->getSharedBMP()->contains(imgId)) { + img = new Image::BitmapDecoder(); + img->loadStream(*_vm->getSharedBMP()->getVal(imgId)); + return img; + } + + warning("Image %d not found", spriteId); + return img; +} + + +void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) { + uint16 castID = _sprites[spriteID]->_castId; + + TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]); + Common::SeekableSubReadStreamEndian *textStream; + + if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) { + textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024); + } else { + textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024); + } + /*uint32 unk1 = */ textStream->readUint32(); + uint32 strLen = textStream->readUint32(); + /*uin32 dataLen = */ textStream->readUint32(); + Common::String text; + + for (uint32 i = 0; i < strLen; i++) { + byte ch = textStream->readByte(); + if (ch == 0x0d) { + ch = '\n'; + } + text += ch; + } + + uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left; + uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top; + + int x = _sprites[spriteID]->_startPoint.x + rectLeft; + int y = _sprites[spriteID]->_startPoint.y + rectTop; + int height = _sprites[spriteID]->_height; + int width = _sprites[spriteID]->_width; + + const char *fontName; + + if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) { + fontName = _vm->_currentScore->_fontMap[textCast->fontId].c_str(); + } else if ((fontName = _vm->_wm->getFontName(textCast->fontId, textCast->fontSize)) == NULL) { + warning("Unknown font id %d, falling back to default", textCast->fontId); + fontName = _vm->_wm->getFontName(0, 12); + } + + const Graphics::Font *font = _vm->_wm->getFont(fontName, Graphics::FontManager::kBigGUIFont); + + font->drawString(&surface, text, x, y, width, 0); + + if (textCast->borderSize != kSizeNone) { + uint16 size = textCast->borderSize; + + //Indent from borders, measured in d4 + x -= 1; + y -= 4; + + height += 4; + width += 1; + + while (size) { + surface.frameRect(Common::Rect(x, y, x + height, y + width), 0); + x--; + y--; + height += 2; + width += 2; + size--; + } + } + + if (textCast->gutterSize != kSizeNone) { + x -= 1; + y -= 4; + + height += 4; + width += 1; + uint16 size = textCast->gutterSize; + + surface.frameRect(Common::Rect(x, y, x + height, y + width), 0); + + while (size) { + surface.drawLine(x + width, y, x + width, y + height, 0); + surface.drawLine(x, y + height, x + width, y + height, 0); + x++; + y++; + size--; + } + } +} + +void Frame::drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { + uint8 skipColor = _vm->getPaletteColorCount() - 1; //FIXME is it always white (last entry in pallette) ? + + for (int ii = 0; ii < sprite.h; ii++) { + const byte *src = (const byte *)sprite.getBasePtr(0, ii); + byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii); + + for (int j = 0; j < drawRect.width(); j++) { + if (*src != skipColor) + *dst = *src; + + src++; + dst++; + } + } +} + +void Frame::drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { + uint8 skipColor = _vm->getPaletteColorCount() - 1; + for (int ii = 0; ii < sprite.h; ii++) { + const byte *src = (const byte *)sprite.getBasePtr(0, ii); + byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii); + + for (int j = 0; j < drawRect.width(); j++) { + if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0) && (*src != skipColor)) + *dst = (_vm->getPaletteColorCount() - 1) - *src; //Oposite color + + src++; + dst++; + } + } +} + +void Frame::drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { + uint8 skipColor = _vm->getPaletteColorCount() - 1; + for (int ii = 0; ii < sprite.h; ii++) { + const byte *src = (const byte *)sprite.getBasePtr(0, ii); + byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + ii); + + for (int j = 0; j < drawRect.width(); j++) { + if ((getSpriteIDFromPos(Common::Point(drawRect.left + j, drawRect.top + ii)) != 0)) + *dst = (_vm->getPaletteColorCount() - 1) - *src; + else if (*src != skipColor) + *dst = *src; + src++; + dst++; + } + } +} + +void Frame::drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect) { + // Like background trans, but all white pixels NOT ENCLOSED by coloured pixels are transparent + Graphics::Surface tmp; + tmp.copyFrom(sprite); + + // Searching white color in the corners + int whiteColor = -1; + + for (int corner = 0; corner < 4; corner++) { + int x = (corner & 0x1) ? tmp.w - 1 : 0; + int y = (corner & 0x2) ? tmp.h - 1 : 0; + + byte color = *(byte *)tmp.getBasePtr(x, y); + + if (_vm->getPalette()[color * 3 + 0] == 0xff && + _vm->getPalette()[color * 3 + 1] == 0xff && + _vm->getPalette()[color * 3 + 2] == 0xff) { + whiteColor = color; + break; + } + } + + if (whiteColor == -1) { + debugC(1, kDebugImages, "No white color for Matte image"); + + for (int yy = 0; yy < tmp.h; yy++) { + const byte *src = (const byte *)tmp.getBasePtr(0, yy); + byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + yy); + + for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++) + *dst = *src; + } + } else { + Graphics::FloodFill ff(&tmp, whiteColor, 0, true); + + for (int yy = 0; yy < tmp.h; yy++) { + ff.addSeed(0, yy); + ff.addSeed(tmp.w - 1, yy); + } + + for (int xx = 0; xx < tmp.w; xx++) { + ff.addSeed(xx, 0); + ff.addSeed(xx, tmp.h - 1); + } + ff.fillMask(); + + for (int yy = 0; yy < tmp.h; yy++) { + const byte *src = (const byte *)tmp.getBasePtr(0, yy); + const byte *mask = (const byte *)ff.getMask()->getBasePtr(0, yy); + byte *dst = (byte *)target.getBasePtr(drawRect.left, drawRect.top + yy); + + for (int xx = 0; xx < drawRect.width(); xx++, src++, dst++, mask++) + if (*mask == 0) + *dst = *src; + } + } + + tmp.free(); +} + +uint16 Frame::getSpriteIDFromPos(Common::Point pos) { + //Find first from top to bottom + for (uint16 i = _drawRects.size() - 1; i > 0; i--) { + if (_drawRects[i].contains(pos)) + return i; + } + + return 0; +} + +} //End of namespace Director diff --git a/engines/director/frame.h b/engines/director/frame.h new file mode 100644 index 0000000000..8c6f82f493 --- /dev/null +++ b/engines/director/frame.h @@ -0,0 +1,149 @@ +/* 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 DIRECTOR_FRAME_H +#define DIRECTOR_FRAME_H + +#include "graphics/managed_surface.h" + +namespace Image { + class ImageDecoder; +} + +namespace Director { + +class Sprite; + +#define CHANNEL_COUNT 24 + +enum TransitionType { + kTransNone, + kTransWipeRight, + kTransWipeLeft, + kTransWipeDown, + kTransWipeUp, + kTransCenterOutHorizontal, + kTransEdgesInHorizontal, + kTransCenterOutVertical, + kTransEdgesInVertical, + kTransCenterOutSquare, + kTransEdgesInSquare, + kTransPushLeft, + kTransPushRight, + kTransPushDown, + kTransPushUp, + kTransRevealUp, + kTransRevealUpRight, + kTransRevealRight, + kTransRevealDown, + kTransRevealDownRight, + kTransRevealDownLeft, + kTransRevealLeft, + kTransRevealUpLeft, + kTransDissolvePixelsFast, + kTransDissolveBoxyRects, + kTransDissolveBoxySquares, + kTransDissolvePatterns, + kTransRandomRows, + kTransRandomColumns, + kTransCoverDown, + kTransCoverDownLeft, + kTransCoverDownRight, + kTransCoverLeft, + kTransCoverRight, + kTransCoverUp, + kTransCoverUpLeft, + kTransCoverUpRight, + kTransTypeVenitianBlind, + kTransTypeCheckerboard, + kTransTypeStripsBottomBuildLeft, + kTransTypeStripsBottomBuildRight, + kTransTypeStripsLeftBuildDown, + kTransTypeStripsLeftBuildUp, + kTransTypeStripsRightBuildDown, + kTransTypeStripsRightBuildUp, + kTransTypeStripsTopBuildLeft, + kTransTypeStripsTopBuildRight, + kTransZoomOpen, + kTransZoomClose, + kTransVerticalBinds, + kTransDissolveBitsTrans, + kTransDissolvePixels, + kTransDissolveBits +}; + +struct PaletteInfo { + uint8 firstColor; + uint8 lastColor; + uint8 flags; + uint8 speed; + uint16 frameCount; +}; + + +class Frame { +public: + Frame(DirectorEngine *vm); + Frame(const Frame &frame); + ~Frame(); + void readChannel(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); + void prepareFrame(Score *score); + uint16 getSpriteIDFromPos(Common::Point pos); + +private: + void playTransition(Score *score); + void playSoundChannel(); + void renderSprites(Graphics::ManagedSurface &surface, bool renderTrail); + void renderText(Graphics::ManagedSurface &surface, uint16 spriteId); + void renderButton(Graphics::ManagedSurface &surface, uint16 spriteId); + void readPaletteInfo(Common::SeekableSubReadStreamEndian &stream); + void readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); + void readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size); + Image::ImageDecoder *getImageFrom(uint16 spriteID); + void drawBackgndTransSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); + void drawMatteSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); + void drawGhostSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); + void drawReverseSprite(Graphics::ManagedSurface &target, const Graphics::Surface &sprite, Common::Rect &drawRect); +public: + uint8 _actionId; + uint8 _transDuration; + uint8 _transArea; //1 - Whole Stage, 0 - Changing Area + uint8 _transChunkSize; + TransitionType _transType; + PaletteInfo *_palette; + uint8 _tempo; + + uint16 _sound1; + uint8 _soundType1; + uint16 _sound2; + uint8 _soundType2; + + uint8 _skipFrameFlag; + uint8 _blend; + Common::Array<Sprite *> _sprites; + Common::Array<Common::Rect > _drawRects; + DirectorEngine *_vm; +}; + +} //End of namespace Director + +#endif diff --git a/engines/director/images.cpp b/engines/director/images.cpp new file mode 100644 index 0000000000..cd8223ae8e --- /dev/null +++ b/engines/director/images.cpp @@ -0,0 +1,203 @@ +/* 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/substream.h" +#include "common/debug.h" +#include "common/textconsole.h" + +#include "director/director.h" +#include "director/images.h" + +namespace Director { + +DIBDecoder::DIBDecoder() { + _surface = 0; + _palette = 0; + _paletteColorCount = 0; + _codec = 0; +} + +DIBDecoder::~DIBDecoder() { + destroy(); +} + +void DIBDecoder::destroy() { + _surface = 0; + + delete[] _palette; + _palette = 0; + _paletteColorCount = 0; + + delete _codec; + _codec = 0; +} + +void DIBDecoder::loadPalette(Common::SeekableReadStream &stream) { + uint16 steps = stream.size() / 6; + uint16 index = (steps * 3) - 1; + _paletteColorCount = steps; + _palette = new byte[index + 1]; + + for (uint8 i = 0; i < steps; i++) { + _palette[index - 2] = stream.readByte(); + stream.readByte(); + + _palette[index - 1] = stream.readByte(); + stream.readByte(); + + _palette[index] = stream.readByte(); + stream.readByte(); + index -= 3; + } +} + +bool DIBDecoder::loadStream(Common::SeekableReadStream &stream) { + uint32 headerSize = stream.readUint32LE(); + if (headerSize != 40) + return false; + + uint32 width = stream.readUint32LE(); + uint32 height = stream.readUint32LE(); + stream.readUint16LE(); // planes + uint16 bitsPerPixel = stream.readUint16LE(); + uint32 compression = stream.readUint32BE(); + /* uint32 imageSize = */ stream.readUint32LE(); + /* uint32 pixelsPerMeterX = */ stream.readUint32LE(); + /* uint32 pixelsPerMeterY = */ stream.readUint32LE(); + _paletteColorCount = stream.readUint32LE(); + /* uint32 colorsImportant = */ stream.readUint32LE(); + + _paletteColorCount = (_paletteColorCount == 0) ? 255: _paletteColorCount; + + Common::SeekableSubReadStream subStream(&stream, 40, stream.size()); + + _codec = Image::createBitmapCodec(compression, width, height, bitsPerPixel); + + if (!_codec) + return false; + + _surface = _codec->decodeFrame(subStream); + + return true; +} + +/**************************** + * BITD + ****************************/ + +BITDDecoder::BITDDecoder(int w, int h) { + _surface = new Graphics::Surface(); + + // We make the surface pitch a multiple of 16. + int pitch = w; + if (w % 16) + pitch += 16 - (w % 16); + + // HACK: Create a padded surface by adjusting w after create() + _surface->create(pitch, h, Graphics::PixelFormat::createFormatCLUT8()); + _surface->w = w; + + _palette = new byte[256 * 3]; + + _palette[0] = _palette[1] = _palette[2] = 0; + _palette[255 * 3 + 0] = _palette[255 * 3 + 1] = _palette[255 * 3 + 2] = 0xff; + + _paletteColorCount = 2; +} + +BITDDecoder::~BITDDecoder() { + destroy(); +} + +void BITDDecoder::destroy() { + _surface = 0; + + delete[] _palette; + _palette = 0; + _paletteColorCount = 0; +} + +void BITDDecoder::loadPalette(Common::SeekableReadStream &stream) { + // no op +} + +bool BITDDecoder::loadStream(Common::SeekableReadStream &stream) { + int x = 0, y = 0; + + // If the stream has exactly the required number of bits for this image, + // we assume it is uncompressed. + if (stream.size() * 8 == _surface->pitch * _surface->h) { + debugC(3, kDebugImages, "Skipping compression"); + for (y = 0; y < _surface->h; y++) { + for (x = 0; x < _surface->pitch; ) { + byte color = stream.readByte(); + for (int c = 0; c < 8; c++) + *((byte *)_surface->getBasePtr(x++, y)) = (color & (1 << (7 - c))) ? 0 : 0xff; + } + } + + return true; + } + + while (y < _surface->h) { + int n = stream.readSByte(); + int count; + int b = 0; + int state = 0; + + if (stream.eos()) + break; + + if ((n >= 0) && (n <= 127)) { // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + count = n + 1; + state = 1; + } else if ((n >= -127) && (n <= -1)) { // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + b = stream.readByte(); + count = -n + 1; + state = 2; + } else { // Else if n is -128, noop. + count = 0; + } + + for (int i = 0; i < count && y < _surface->h; i++) { + byte color = 0; + if (state == 1) { + color = stream.readByte(); + } else if (state == 2) + color = b; + + for (int c = 0; c < 8; c++) { + *((byte *)_surface->getBasePtr(x, y)) = (color & (1 << (7 - c))) ? 0 : 0xff; + x++; + if (x == _surface->pitch) { + y++; + x = 0; + break; + } + } + } + } + + return true; +} + +} // End of namespace Director diff --git a/engines/director/images.h b/engines/director/images.h new file mode 100644 index 0000000000..54e824588f --- /dev/null +++ b/engines/director/images.h @@ -0,0 +1,86 @@ +/* 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 DIRECTOR_IMAGES_H +#define DIRECTOR_IMAGES_H + +#include "common/scummsys.h" +#include "common/str.h" +#include "image/image_decoder.h" +#include "image/codecs/bmp_raw.h" + +namespace Common { +class SeekableReadStream; +} + +namespace Graphics { +struct Surface; +} + +namespace Image { +class Codec; +} + +namespace Director { + +class DIBDecoder : public Image::ImageDecoder { +public: + DIBDecoder(); + virtual ~DIBDecoder(); + + // ImageDecoder API + void destroy(); + virtual bool loadStream(Common::SeekableReadStream &stream); + virtual const Graphics::Surface *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + void loadPalette(Common::SeekableReadStream &stream); + uint16 getPaletteColorCount() const { return _paletteColorCount; } + +private: + Image::Codec *_codec; + const Graphics::Surface *_surface; + byte *_palette; + uint8 _paletteColorCount; +}; + +class BITDDecoder : public Image::ImageDecoder { +public: + BITDDecoder(int w, int h); + virtual ~BITDDecoder(); + + // ImageDecoder API + void destroy(); + virtual bool loadStream(Common::SeekableReadStream &stream); + virtual const Graphics::Surface *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + void loadPalette(Common::SeekableReadStream &stream); + uint16 getPaletteColorCount() const { return _paletteColorCount; } + +private: + Graphics::Surface *_surface; + byte *_palette; + uint8 _paletteColorCount; +}; + +} // End of namespace Director + +#endif diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp new file mode 100644 index 0000000000..bad585cfe1 --- /dev/null +++ b/engines/director/lingo/lingo-builtins.cpp @@ -0,0 +1,823 @@ +/* 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 "director/lingo/lingo.h" + +namespace Director { + +static struct BuiltinProto { + const char *name; + void (*func)(int); + int minArgs; + int maxArgs; + bool parens; +} builtins[] = { + // Math + { "abs", Lingo::b_abs, 1, 1, true }, // D2 + { "atan", Lingo::b_atan, 1, 1, true }, // D4 + { "cos", Lingo::b_cos, 1, 1, true }, // D4 + { "exp", Lingo::b_exp, 1, 1, true }, // D4 + { "float", Lingo::b_float, 1, 1, true }, // D4 + { "integer", Lingo::b_integer, 1, 1, true }, + { "integerp", Lingo::b_integerp, 1, 1, true }, + { "log", Lingo::b_log, 1, 1, true }, // D4 + { "pi", Lingo::b_pi, 0, 0, true }, // D4 + { "power", Lingo::b_power, 2, 2, true }, // D4 + { "random", Lingo::b_random, 1, 1, true }, // D2 + { "sin", Lingo::b_sin, 1, 1, true }, + { "sqrt", Lingo::b_sqrt, 1, 1, true }, // D2 + { "tan", Lingo::b_tan, 1, 1, true }, // D4 + // String + { "chars", Lingo::b_chars, 3, 3, true }, // D2 + { "charToNum", Lingo::b_charToNum, 1, 1, true }, // D2 + { "length", Lingo::b_length, 1, 1, true }, // D2 + { "numToChar", Lingo::b_numToChar, 1, 1, true }, // D2 + { "offset", Lingo::b_offset, 2, 2, true }, // D2 + { "string", Lingo::b_string, 1, 1, true }, // D2 + { "stringp", Lingo::b_stringp, 1, 1, true }, // D2 + { "value", Lingo::b_value, 1, 1, true }, // D2 + // Files + { "closeDA", Lingo::b_closeDA, 0, 0, false }, // D2 + { "closeResFile", Lingo::b_closeResFile, 0, 1, false }, // D2 + { "closeXlib", Lingo::b_closeXlib, 0, 1, false }, // D2 + // open // D2 + { "openDA", Lingo::b_openDA, 1, 1, false }, // D2 + { "openResFile", Lingo::b_openResFile, 1, 1, false }, // D2 + { "openXlib", Lingo::b_openXlib, 1, 1, false }, // D2 + { "showResFile", Lingo::b_showResFile, 0, 1, false }, // D2 + { "showXlib", Lingo::b_showXlib, 0, 1, false }, // D2 + // Control + { "continue", Lingo::b_continue, 0, 0, false }, // D2 + { "dontPassEvent", Lingo::b_dontPassEvent, 0, 0, false }, // D2 + { "delay", Lingo::b_delay, 1, 1, false }, // D2 + { "do", Lingo::b_do, 1, 1, false }, // D2 + { "nothing", Lingo::b_nothing, 0, 0, false }, // D2 + { "pause", Lingo::b_pause, 0, 0, false }, // D2 + // play // D2 + { "playAccel", Lingo::b_playAccel, -1,0, false }, // D2 + // play done // D2 + { "quit", Lingo::b_quit, 0, 0, false }, // D2 + { "restart", Lingo::b_restart, 0, 0, false }, // D2 + { "shutDown", Lingo::b_shutDown, 0, 0, false }, // D2 + { "startTimer", Lingo::b_startTimer, 0, 0, false }, // D2 + // when keyDown // D2 + // when mouseDown // D2 + // when mouseUp // D2 + // when timeOut // D2 + // Misc + { "alert", Lingo::b_alert, 1, 1, false }, // D2 + { "cursor", Lingo::b_cursor, 1, 1, false }, // D2 + { "printFrom", Lingo::b_printFrom, -1,0, false }, // D2 + { "ilk", Lingo::b_ilk, 1, 2, true }, // D4 + // put // D2 + // set // D2 + { "objectp", Lingo::b_objectp, 1, 1, true }, + { "showGlobals", Lingo::b_showGlobals, 0, 0, false }, // D2 + { "showLocals", Lingo::b_showLocals, 0, 0, false }, // D2 + { "symbolp", Lingo::b_symbolp, 1, 1, true }, // D2 + // Score + { "constrainH", Lingo::b_constrainH, 2, 2, true }, // D2 + { "constrainV", Lingo::b_constrainV, 2, 2, true }, // D2 + { "editableText", Lingo::b_editableText, 0, 0, false }, // D2 + // go // D2 + { "installMenu", Lingo::b_installMenu, 1, 1, false }, // D2 + { "label", Lingo::b_label, 1, 1, true }, // D2 + { "marker", Lingo::b_marker, 1, 1, true }, // D2 + { "moveableSprite", Lingo::b_moveableSprite,0, 0, false }, // D2 + { "puppetPalette", Lingo::b_puppetPalette, -1,0, false }, // D2 + { "puppetSound", Lingo::b_puppetSound, -1,0, false }, // D2 + { "puppetSprite", Lingo::b_puppetSprite, -1,0, false }, // D2 + { "puppetTempo", Lingo::b_puppetTempo, 1, 1, false }, // D2 + { "puppetTransition",Lingo::b_puppetTransition,-1,0, false },// D2 + { "rollOver", Lingo::b_rollOver, 1, 1, true }, // D2 + { "spriteBox", Lingo::b_spriteBox, -1,0, false }, // D2 + { "updateStage", Lingo::b_updateStage, 0, 0, false }, // D2 + { "zoomBox", Lingo::b_zoomBox, -1,0, false }, // D2 + // Point + { "point", Lingo::b_point, 2, 2, true }, + // Sound + { "beep", Lingo::b_beep, 0, 1, false }, // D2 + { "mci", Lingo::b_mci, 1, 1, false }, + { "mciwait", Lingo::b_mciwait, 1, 1, false }, + // Constants + { "backspace", Lingo::b_backspace, 0, 0, false }, // D2 + { "empty", Lingo::b_empty, 0, 0, false }, // D2 + { "enter", Lingo::b_enter, 0, 0, false }, // D2 + { "false", Lingo::b_false, 0, 0, false }, // D2 + { "quote", Lingo::b_quote, 0, 0, false }, // D2 + { "return", Lingo::b_return, 0, 0, false }, // D2 + { "tab", Lingo::b_tab, 0, 0, false }, // D2 + { "true", Lingo::b_true, 0, 0, false }, // D2 + + { 0, 0, 0, 0, false } +}; + +void Lingo::initBuiltIns() { + for (BuiltinProto *blt = builtins; blt->name; blt++) { + Symbol *sym = new Symbol; + + sym->name = (char *)calloc(strlen(blt->name) + 1, 1); + Common::strlcpy(sym->name, blt->name, strlen(blt->name)); + sym->type = BLTIN; + sym->nargs = blt->minArgs; + sym->maxArgs = blt->maxArgs; + sym->parens = blt->parens; + sym->u.bltin = blt->func; + + _handlers[blt->name] = sym; + + _functions[(void *)sym->u.s] = new FuncDesc(blt->name, ""); + } +} + +void Lingo::printStubWithArglist(const char *funcname, int nargs) { + Common::String s(funcname); + + s += '('; + + for (int i = 0; i < nargs; i++) { + Datum d = _stack[_stack.size() - nargs + i]; + + d.toString(); + s += *d.u.s; + + if (i != nargs - 1) + s += ", "; + } + + s += ")"; + + warning("STUB: %s", s.c_str()); +} + +void Lingo::convertVOIDtoString(int arg, int nargs) { + if (_stack[_stack.size() - nargs + arg].type == VOID) { + if (_stack[_stack.size() - nargs + arg].u.s != NULL) + g_lingo->_stack[_stack.size() - nargs + arg].type = STRING; + else + warning("Incorrect convertVOIDtoString for arg %d of %d", arg, nargs); + } +} + +void Lingo::dropStack(int nargs) { + for (int i = 0; i < nargs; i++) + pop(); +} + +void Lingo::drop(int num) { + if (num > _stack.size() - 1) { + warning("Incorrect number of elements to drop from stack: %d > %d", num, _stack.size() - 1); + return; + } + _stack.remove_at(_stack.size() - 1 - num); +} + + +/////////////////// +// Math +/////////////////// +void Lingo::b_abs(int nargs) { + Datum d = g_lingo->pop(); + + if (d.type == INT) + d.u.i = ABS(d.u.i); + else if (d.type == FLOAT) + d.u.f = ABS(d.u.f); + + g_lingo->push(d); +} + +void Lingo::b_atan(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + d.u.f = atan(d.u.f); + g_lingo->push(d); +} + +void Lingo::b_cos(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + d.u.f = cos(d.u.f); + g_lingo->push(d); +} + +void Lingo::b_exp(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); // Lingo uses int, so we're enforcing it + d.toFloat(); + d.u.f = exp(d.u.f); + g_lingo->push(d); +} + +void Lingo::b_float(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + g_lingo->push(d); +} + +void Lingo::b_integer(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); + g_lingo->push(d); +} + +void Lingo::b_integerp(int nargs) { + Datum d = g_lingo->pop(); + int res = (d.type == INT) ? 1 : 0; + d.toInt(); + d.u.i = res; + g_lingo->push(d); +} + +void Lingo::b_log(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + d.u.f = log(d.u.f); + g_lingo->push(d); +} + +void Lingo::b_pi(int nargs) { + Datum d; + d.toFloat(); + d.u.f = M_PI; + g_lingo->push(d); +} + +void Lingo::b_power(int nargs) { + Datum d1 = g_lingo->pop(); + Datum d2 = g_lingo->pop(); + d1.toFloat(); + d2.toFloat(); + d1.u.f = pow(d2.u.f, d1.u.f); + g_lingo->push(d1); +} + +void Lingo::b_random(int nargs) { + Datum max = g_lingo->pop(); + Datum res; + + max.toInt(); + + res.u.i = g_lingo->_vm->_rnd.getRandomNumber(max.u.i); + res.type = INT; + + g_lingo->push(res); +} + +void Lingo::b_sin(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + d.u.f = sin(d.u.f); + g_lingo->push(d); +} + +void Lingo::b_sqrt(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + d.u.f = sqrt(d.u.f); + g_lingo->push(d); +} + +void Lingo::b_tan(int nargs) { + Datum d = g_lingo->pop(); + d.toFloat(); + d.u.f = tan(d.u.f); + g_lingo->push(d); +} + +/////////////////// +// String +/////////////////// +void Lingo::b_chars(int nargs) { + Datum to = g_lingo->pop(); + Datum from = g_lingo->pop(); + Datum s = g_lingo->pop(); + + if (s.type != STRING) + error("Incorrect type for 'chars' function: %s", s.type2str()); + + to.toInt(); + from.toInt(); + + int len = strlen(s.u.s->c_str()); + int f = MAX(0, MIN(len, from.u.i - 1)); + int t = MAX(0, MIN(len, to.u.i)); + + Common::String *res = new Common::String(&(s.u.s->c_str()[f]), &(s.u.s->c_str()[t])); + + delete s.u.s; + + s.u.s = res; + s.type = STRING; + g_lingo->push(s); +} + +void Lingo::b_charToNum(int nargs) { + Datum d = g_lingo->pop(); + + if (d.type != STRING) + error("Incorrect type for 'charToNum' function: %s", d.type2str()); + + byte chr = d.u.s->c_str()[0]; + delete d.u.s; + + d.u.i = chr; + d.type = INT; + g_lingo->push(d); +} + +void Lingo::b_length(int nargs) { + Datum d = g_lingo->pop(); + + if (d.type != STRING) + error("Incorrect type for 'length' function: %s", d.type2str()); + + int len = strlen(d.u.s->c_str()); + delete d.u.s; + + d.u.i = len; + d.type = INT; + g_lingo->push(d); +} + +void Lingo::b_numToChar(int nargs) { + Datum d = g_lingo->pop(); + + d.toInt(); + + g_lingo->push(Datum((char)d.u.i)); +} + +void Lingo::b_offset(int nargs) { + Datum target = g_lingo->pop(); + Datum source = g_lingo->pop(); + + target.toString(); + source.toString(); + + warning("STUB: b_offset()"); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_string(int nargs) { + Datum d = g_lingo->pop(); + d.toString(); + g_lingo->push(d); +} + +void Lingo::b_stringp(int nargs) { + Datum d = g_lingo->pop(); + int res = (d.type == STRING) ? 1 : 0; + d.toInt(); + d.u.i = res; + g_lingo->push(d); +} + +void Lingo::b_value(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); + warning("STUB: b_value()"); + g_lingo->push(d); +} + + +/////////////////// +// Files +/////////////////// +void Lingo::b_closeDA(int nargs) { + warning("STUB: b_closeDA"); +} + +void Lingo::b_closeResFile(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_closeResFile(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_closeXlib(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_closeXlib(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_openDA(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_openDA(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_openResFile(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_openResFile(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_openXlib(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_openXlib(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_showResFile(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_showResFile(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_showXlib(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_showXlib(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +/////////////////// +// Control +/////////////////// +void Lingo::b_dontPassEvent(int nargs) { + warning("STUB: b_dontPassEvent"); +} + +void Lingo::b_continue(int nargs) { + warning("STUB: b_continue"); +} + +void Lingo::b_nothing(int nargs) { + warning("STUB: b_nothing"); +} + +void Lingo::b_delay(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); + warning("STUB: b_delay(%d)", d.u.i); +} + +void Lingo::b_do(int nargs) { + Datum d = g_lingo->pop(); + d.toString(); + warning("STUB: b_do(%s)", d.u.s->c_str()); +} + +void Lingo::b_pause(int nargs) { + warning("STUB: b_pause"); +} + +void Lingo::b_playAccel(int nargs) { + g_lingo->printStubWithArglist("b_playAccel", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_printFrom(int nargs) { + g_lingo->printStubWithArglist("b_printFrom", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_quit(int nargs) { + warning("STUB: b_quit"); +} + +void Lingo::b_restart(int nargs) { + warning("STUB: b_restart"); +} + +void Lingo::b_shutDown(int nargs) { + warning("STUB: b_shutDown"); +} + +void Lingo::b_startTimer(int nargs) { + warning("STUB: b_startTimer"); +} + + +/////////////////// +// Misc +/////////////////// +void Lingo::b_ilk(int nargs) { + Datum d = g_lingo->pop(); + d.u.i = d.type; + d.type = SYMBOL; + g_lingo->push(d); +} + +void Lingo::b_alert(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + warning("STUB: b_alert(%s)", d.u.s->c_str()); + + delete d.u.s; +} + +void Lingo::b_cursor(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); + warning("STUB: b_cursor(%d)", d.u.i); +} + +void Lingo::b_objectp(int nargs) { + Datum d = g_lingo->pop(); + int res = (d.type == OBJECT) ? 1 : 0; + d.toInt(); + d.u.i = res; + g_lingo->push(d); +} + +void Lingo::b_showGlobals(int nargs) { + warning("STUB: b_showGlobals"); +} + +void Lingo::b_showLocals(int nargs) { + warning("STUB: b_showLocals"); +} + +void Lingo::b_symbolp(int nargs) { + Datum d = g_lingo->pop(); + int res = (d.type == SYMBOL) ? 1 : 0; + d.toInt(); + d.u.i = res; + g_lingo->push(d); +} + + +/////////////////// +// Score +/////////////////// +void Lingo::b_constrainH(int nargs) { + Datum num = g_lingo->pop(); + Datum sprite = g_lingo->pop(); + + num.toInt(); + sprite.toInt(); + + warning("STUB: b_constrainH(%d, %d)", sprite.u.i, num.u.i); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_constrainV(int nargs) { + Datum num = g_lingo->pop(); + Datum sprite = g_lingo->pop(); + + num.toInt(); + sprite.toInt(); + + warning("STUB: b_constrainV(%d, %d)", sprite.u.i, num.u.i); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_editableText(int nargs) { + warning("STUB: b_editableText"); +} + +void Lingo::b_installMenu(int nargs) { + Datum d = g_lingo->pop(); + warning("STUB: b_installMenu(%d)", d.u.i); +} + +void Lingo::b_label(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); + warning("STUB: b_label(%d)", d.u.i); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_marker(int nargs) { + Datum d = g_lingo->pop(); + d.toInt(); + warning("STUB: b_marker(%d)", d.u.i); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_moveableSprite(int nargs) { + Datum d = g_lingo->pop(); + warning("STUB: b_moveableSprite(%d)", d.u.i); +} + +void Lingo::b_puppetPalette(int nargs) { + g_lingo->convertVOIDtoString(0, nargs); + + g_lingo->printStubWithArglist("b_puppetPalette", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_puppetSound(int nargs) { + g_lingo->convertVOIDtoString(0, nargs); + + g_lingo->printStubWithArglist("b_puppetSound", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_puppetSprite(int nargs) { + g_lingo->printStubWithArglist("b_puppetSprite", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_puppetTempo(int nargs) { + Datum d = g_lingo->pop(); + warning("STUB: b_puppetTempo(%d)", d.u.i); +} + +void Lingo::b_puppetTransition(int nargs) { + g_lingo->printStubWithArglist("b_puppetTransition", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_rollOver(int nargs) { + Datum d = g_lingo->pop(); + warning("STUB: b_puppetTempo(%d)", d.u.i); + + g_lingo->push(Datum(0)); +} + +void Lingo::b_spriteBox(int nargs) { + g_lingo->printStubWithArglist("b_spriteBox", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_zoomBox(int nargs) { + g_lingo->printStubWithArglist("b_zoomBox", nargs); + + g_lingo->dropStack(nargs); +} + +void Lingo::b_updateStage(int nargs) { + warning("STUB: b_updateStage"); +} + + + +/////////////////// +// Point +/////////////////// +void Lingo::b_point(int nargs) { + Datum y = g_lingo->pop(); + Datum x = g_lingo->pop(); + Datum d; + + x.toFloat(); + y.toFloat(); + + d.u.arr = new FloatArray; + + d.u.arr->push_back(x.u.f); + d.u.arr->push_back(y.u.f); + d.type = POINT; + + g_lingo->push(d); +} + + +/////////////////// +// Sound +/////////////////// +void Lingo::b_beep(int nargs) { + Datum d = g_lingo->pop(); + warning("STUB: b_beep(%d)", d.u.i); +} + +void Lingo::b_mci(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + g_lingo->func_mci(*d.u.s); +} + +void Lingo::b_mciwait(int nargs) { + Datum d = g_lingo->pop(); + + d.toString(); + + g_lingo->func_mciwait(*d.u.s); +} + +/////////////////// +// Constants +/////////////////// +void Lingo::b_backspace(int nargs) { + g_lingo->push(Datum(new Common::String("\b"))); +} + +void Lingo::b_empty(int nargs) { + g_lingo->push(Datum(new Common::String(""))); +} + +void Lingo::b_enter(int nargs) { + g_lingo->push(Datum(new Common::String("\n"))); +} + +void Lingo::b_false(int nargs) { + g_lingo->push(Datum(0)); +} + +void Lingo::b_quote(int nargs) { + g_lingo->push(Datum(new Common::String("\""))); +} + +void Lingo::b_return(int nargs) { + g_lingo->push(Datum(new Common::String("\r"))); +} + +void Lingo::b_tab(int nargs) { + g_lingo->push(Datum(new Common::String("\t"))); +} + +void Lingo::b_true(int nargs) { + g_lingo->push(Datum(1)); +} + +/////////////////// +// Factory +/////////////////// +void Lingo::b_factory(int nargs) { + // This is intentionally empty +} + +void Lingo::factoryCall(Common::String &name, int nargs) { + Common::String s("factoryCall: "); + + s += name; + + convertVOIDtoString(0, nargs); + + printStubWithArglist(s.c_str(), nargs); + + Datum method = _stack[_stack.size() - nargs + 0]; + + drop(nargs - 1); + + s = name + "-" + *method.u.s; + + debugC(3, kDebugLingoExec, "Stack size before call: %d, nargs: %d", _stack.size(), nargs); + call(s, nargs); + debugC(3, kDebugLingoExec, "Stack size after call: %d", _stack.size()); + + if (!method.u.s->compareToIgnoreCase("mNew")) { + Datum d; + + d.type = OBJECT; + d.u.s = new Common::String(name); + + g_lingo->push(d); + } +} + +} // End of namespace Director diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp new file mode 100644 index 0000000000..9e3350a1df --- /dev/null +++ b/engines/director/lingo/lingo-code.cpp @@ -0,0 +1,972 @@ +/* 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. + * + */ + +// Heavily inspired by hoc +// Copyright (C) AT&T 1995 +// All Rights Reserved +// +// Permission to use, copy, modify, and distribute this software and +// its documentation for any purpose and without fee is hereby +// granted, provided that the above copyright notice appear in all +// copies and that both that the copyright notice and this +// permission notice and warranty disclaimer appear in supporting +// documentation, and that the name of AT&T or any of its entities +// not be used in advertising or publicity pertaining to +// distribution of the software without specific, written prior +// permission. +// +// AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +// IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +// THIS SOFTWARE. + +#include "director/lingo/lingo.h" +#include "director/lingo/lingo-gr.h" + +namespace Director { + +static struct FuncDescr { + const inst func; + const char *name; + const char *args; +} funcDescr[] = { + { 0, "STOP", "" }, + { Lingo::c_xpop, "c_xpop", "" }, + { Lingo::c_printtop, "c_printtop", "" }, + { Lingo::c_constpush, "c_constpush", "i" }, + { Lingo::c_voidpush, "c_voidpush", "" }, + { Lingo::c_fconstpush, "c_fconstpush", "f" }, + { Lingo::c_stringpush, "c_stringpush", "s" }, + { Lingo::c_varpush, "c_varpush", "s" }, + { Lingo::c_assign, "c_assign", "" }, + { Lingo::c_eval, "c_eval", "s" }, + { Lingo::c_theentitypush,"c_theentitypush","ii" }, // entity, field + { Lingo::c_theentityassign,"c_theentityassign","ii" }, + { Lingo::c_swap, "c_swap", "" }, + { Lingo::c_add, "c_add", "" }, + { Lingo::c_sub, "c_sub", "" }, + { Lingo::c_mul, "c_mul", "" }, + { Lingo::c_div, "c_div", "" }, + { Lingo::c_mod, "c_mod", "" }, + { Lingo::c_negate, "c_negate", "" }, + { Lingo::c_ampersand, "c_ampersand", "" }, + { Lingo::c_concat, "c_concat", "" }, + { Lingo::c_contains, "c_contains", "" }, + { Lingo::c_starts, "c_starts", "" }, + { Lingo::c_intersects, "c_intersects", "" }, + { Lingo::c_within, "c_within", "" }, + { Lingo::c_and, "c_and", "" }, + { Lingo::c_or, "c_or", "" }, + { Lingo::c_not, "c_not", "" }, + { Lingo::c_eq, "c_eq", "" }, + { Lingo::c_neq, "c_neq", "" }, + { Lingo::c_gt, "c_gt", "" }, + { Lingo::c_lt, "c_lt", "" }, + { Lingo::c_ge, "c_ge", "" }, + { Lingo::c_le, "c_le", "" }, + { Lingo::c_repeatwhilecode,"c_repeatwhilecode","oo" }, + { Lingo::c_repeatwithcode,"c_repeatwithcode","ooooos" }, + { Lingo::c_exitRepeat, "c_exitRepeat", "" }, + { Lingo::c_ifcode, "c_ifcode", "oooi" }, + { Lingo::c_whencode, "c_whencode", "os" }, + { Lingo::c_goto, "c_goto", "" }, + { Lingo::c_gotoloop, "c_gotoloop", "" }, + { Lingo::c_gotonext, "c_gotonext", "" }, + { Lingo::c_gotoprevious,"c_gotoprevious","" }, + { Lingo::c_play, "c_play", "" }, + { Lingo::c_playdone, "c_playdone", "" }, + { Lingo::c_call, "c_call", "si" }, + { Lingo::c_procret, "c_procret", "" }, + { Lingo::c_global, "c_global", "s" }, + { Lingo::c_instance, "c_instance", "s" }, + { Lingo::c_open, "c_open", "" }, + { 0, 0, 0 } +}; + +void Lingo::initFuncs() { + Symbol sym; + for (FuncDescr *fnc = funcDescr; fnc->name; fnc++) { + sym.u.func = fnc->func; + _functions[(void *)sym.u.s] = new FuncDesc(fnc->name, fnc->args); + } +} + +void Lingo::push(Datum d) { + _stack.push_back(d); +} + +void Lingo::pushVoid() { + Datum d; + d.u.s = NULL; + d.type = VOID; + push(d); +} + +Datum Lingo::pop(void) { + if (_stack.size() == 0) + error("stack underflow"); + + Datum ret = _stack.back(); + _stack.pop_back(); + + return ret; +} + +void Lingo::c_xpop() { + g_lingo->pop(); +} + +void Lingo::c_printtop(void) { + Datum d = g_lingo->pop(); + + switch (d.type) { + case VOID: + warning("Void, came from %s", d.u.s ? d.u.s->c_str() : "<>"); + break; + case INT: + warning("%d", d.u.i); + break; + case FLOAT: + warning(g_lingo->_floatPrecisionFormat.c_str(), d.u.f); + break; + case VAR: + if (!d.u.sym) { + warning("Inconsistent stack: var, val: %d", d.u.i); + } else { + if (d.u.sym->name) + warning("var: %s", d.u.sym->name); + else + warning("Nameless var. val: %d", d.u.sym->u.i); + } + break; + case STRING: + warning("%s", d.u.s->c_str()); + break; + case POINT: + warning("point(%d, %d)", (int)((*d.u.arr)[0]), (int)((*d.u.arr)[1])); + break; + case SYMBOL: + warning("%s", d.type2str(true)); + break; + case OBJECT: + warning("#%s", d.u.s->c_str()); + break; + default: + warning("--unknown--"); + } +} + +void Lingo::c_constpush() { + Datum d; + inst i = (*g_lingo->_currentScript)[g_lingo->_pc++]; + d.u.i = READ_UINT32(&i); + d.type = INT; + g_lingo->push(d); +} + +void Lingo::c_voidpush() { + Datum d; + d.u.s = NULL; + d.type = VOID; + g_lingo->push(d); +} + +void Lingo::c_fconstpush() { + Datum d; + inst i = (*g_lingo->_currentScript)[g_lingo->_pc]; + d.u.f = *((double *)&i); + d.type = FLOAT; + + g_lingo->_pc += g_lingo->calcCodeAlignment(sizeof(double)); + + g_lingo->push(d); +} + +void Lingo::c_stringpush() { + char *s = (char *)&(*g_lingo->_currentScript)[g_lingo->_pc]; + g_lingo->_pc += g_lingo->calcStringAlignment(s); + + g_lingo->push(Datum(new Common::String(s))); +} + +void Lingo::c_varpush() { + char *name = (char *)&(*g_lingo->_currentScript)[g_lingo->_pc]; + Datum d; + + d.u.sym = g_lingo->lookupVar(name); + if (d.u.sym->type == CASTREF) { + d.type = INT; + int val = d.u.sym->u.i; + + delete d.u.sym; + + d.u.i = val; + } else { + d.type = VAR; + } + + g_lingo->_pc += g_lingo->calcStringAlignment(name); + + g_lingo->push(d); +} + +void Lingo::c_assign() { + Datum d1, d2; + d1 = g_lingo->pop(); + d2 = g_lingo->pop(); + + if (d1.type != VAR) { + warning("assignment to non-variable"); + return; + } + + if (d1.u.sym->type != INT && d1.u.sym->type != VOID && + d1.u.sym->type != FLOAT && d1.u.sym->type != STRING) { + warning("assignment to non-variable '%s'", d1.u.sym->name); + return; + } + + if ((d1.u.sym->type == STRING || d1.u.sym->type == VOID) && d1.u.sym->u.s) // Free memory if needed + delete d1.u.sym->u.s; + + if (d1.u.sym->type == POINT || d1.u.sym->type == RECT || d1.u.sym->type == ARRAY) + delete d1.u.sym->u.arr; + + if (d2.type == INT) { + d1.u.sym->u.i = d2.u.i; + } else if (d2.type == FLOAT) { + d1.u.sym->u.f = d2.u.f; + } else if (d2.type == STRING) { + d1.u.sym->u.s = new Common::String(*d2.u.s); + delete d2.u.s; + } else if (d2.type == POINT) { + d1.u.sym->u.arr = new FloatArray(*d2.u.arr); + delete d2.u.arr; + } else if (d2.type == SYMBOL) { + d1.u.sym->u.i = d2.u.i; + } else if (d2.type == OBJECT) { + d1.u.sym->u.s = d2.u.s; + } else { + warning("c_assign: unhandled type: %s", d2.type2str()); + d1.u.sym->u.s = d2.u.s; + } + + d1.u.sym->type = d2.type; + + g_lingo->push(d1); +} + +bool Lingo::verify(Symbol *s) { + if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT) { + warning("attempt to evaluate non-variable '%s'", s->name); + + return false; + } + + if (s->type == VOID) + warning("Variable used before assigning a value '%s'", s->name); + + return true; +} + +void Lingo::c_eval() { + g_lingo->c_varpush(); + + Datum d; + d = g_lingo->pop(); + + if (d.type != VAR) { // It could be cast ref + g_lingo->push(d); + return; + } + + if (!g_lingo->verify(d.u.sym)) + return; + + d.type = d.u.sym->type; + + if (d.u.sym->type == INT) + d.u.i = d.u.sym->u.i; + else if (d.u.sym->type == FLOAT) + d.u.f = d.u.sym->u.f; + else if (d.u.sym->type == STRING) + d.u.s = new Common::String(*d.u.sym->u.s); + else if (d.u.sym->type == POINT) + d.u.arr = d.u.sym->u.arr; + else if (d.u.sym->type == SYMBOL) + d.u.i = d.u.sym->u.i; + else if (d.u.sym->type == VOID) + d.u.s = new Common::String(d.u.sym->name); + else + warning("c_eval: unhandled type: %s", d.type2str()); + + g_lingo->push(d); +} + +void Lingo::c_theentitypush() { + inst e = (*g_lingo->_currentScript)[g_lingo->_pc++]; + inst f = (*g_lingo->_currentScript)[g_lingo->_pc++]; + Datum id = g_lingo->pop(); + + int entity = READ_UINT32(&e); + int field = READ_UINT32(&f); + + Datum d = g_lingo->getTheEntity(entity, id, field); + g_lingo->push(d); +} + +void Lingo::c_theentityassign() { + inst e = (*g_lingo->_currentScript)[g_lingo->_pc++]; + inst f = (*g_lingo->_currentScript)[g_lingo->_pc++]; + Datum id = g_lingo->pop(); + + int entity = READ_UINT32(&e); + int field = READ_UINT32(&f); + + Datum d = g_lingo->pop(); + g_lingo->setTheEntity(entity, id, field, d); + + g_lingo->push(d); // Dummy value +} + +void Lingo::c_swap() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + g_lingo->push(d2); + g_lingo->push(d1); +} + +void Lingo::c_add() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.f += d2.u.f; + } else { + d1.u.i += d2.u.i; + } + g_lingo->push(d1); +} + +void Lingo::c_sub() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.f -= d2.u.f; + } else { + d1.u.i -= d2.u.i; + } + g_lingo->push(d1); +} + +void Lingo::c_mul() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.f *= d2.u.f; + } else { + d1.u.i *= d2.u.i; + } + g_lingo->push(d1); +} + +void Lingo::c_div() { + Datum d2 = g_lingo->pop(); + + if ((d2.type == INT && d2.u.i == 0) || + (d2.type == FLOAT && d2.u.f == 0.0)) + error("division by zero"); + + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.f /= d2.u.f; + } else { + d1.u.i /= d2.u.i; + } + g_lingo->push(d1); +} + +void Lingo::c_mod() { + Datum d2 = g_lingo->pop(); + d2.toInt(); + + if (d2.u.i == 0) + error("division by zero"); + + Datum d1 = g_lingo->pop(); + d1.toInt(); + + d1.u.i %= d2.u.i; + + g_lingo->push(d1); +} + +void Lingo::c_negate() { + Datum d = g_lingo->pop(); + + if (d.type == INT) + d.u.i = -d.u.i; + else if (d.type == FLOAT) + d.u.f = -d.u.f; + + g_lingo->push(d); +} + +void Lingo::c_ampersand() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toString(); + d2.toString(); + + *d1.u.s += *d2.u.s; + + delete d2.u.s; + + g_lingo->push(d1); +} + +void Lingo::c_concat() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toString(); + d2.toString(); + + *d1.u.s += " "; + *d1.u.s += *d2.u.s; + + delete d2.u.s; + + g_lingo->push(d1); +} + +void Lingo::c_contains() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toString(); + d2.toString(); + + Common::String *s1 = g_lingo->toLowercaseMac(d1.u.s); + Common::String *s2 = g_lingo->toLowercaseMac(d2.u.s); + + int res = s1->contains(*s2) ? 1 : 0; + + delete d1.u.s; + delete d2.u.s; + delete s1; + delete s2; + + d1.type = INT; + d1.u.i = res; + + g_lingo->push(d1); +} + +void Lingo::c_starts() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toString(); + d2.toString(); + + Common::String *s1 = g_lingo->toLowercaseMac(d1.u.s); + Common::String *s2 = g_lingo->toLowercaseMac(d2.u.s); + + int res = s1->hasPrefix(*s2) ? 1 : 0; + + delete d1.u.s; + delete d2.u.s; + delete s1; + delete s2; + + d1.type = INT; + d1.u.i = res; + + g_lingo->push(d1); +} + +void Lingo::c_intersects() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + warning("STUB: c_intersects: %d", d2.u.i); + + g_lingo->push(d1); +} + +void Lingo::c_within() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + warning("STUB: c_within: %d", d2.u.i); + + g_lingo->push(d1); +} + +void Lingo::c_and() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toInt(); + d2.toInt(); + + d1.u.i = (d1.u.i && d2.u.i) ? 1 : 0; + + g_lingo->push(d1); +} + +void Lingo::c_or() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toInt(); + d2.toInt(); + + d1.u.i = (d1.u.i || d2.u.i) ? 1 : 0; + + g_lingo->push(d1); +} + +void Lingo::c_not() { + Datum d = g_lingo->pop(); + + d.toInt(); + + d.u.i = ~d.u.i ? 1 : 0; + + g_lingo->push(d); +} + +void Lingo::c_eq() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.i = (d1.u.f == d2.u.f) ? 1 : 0; + d1.type = INT; + } else { + d1.u.i = (d1.u.i == d2.u.i) ? 1 : 0; + } + g_lingo->push(d1); +} + +void Lingo::c_neq() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.i = (d1.u.f != d2.u.f) ? 1 : 0; + d1.type = INT; + } else { + d1.u.i = (d1.u.i != d2.u.i) ? 1 : 0; + } + g_lingo->push(d1); +} + +void Lingo::c_gt() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.i = (d1.u.f > d2.u.f) ? 1 : 0; + d1.type = INT; + } else { + d1.u.i = (d1.u.i > d2.u.i) ? 1 : 0; + } + g_lingo->push(d1); +} + +void Lingo::c_lt() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.i = (d1.u.f < d2.u.f) ? 1 : 0; + d1.type = INT; + } else { + d1.u.i = (d1.u.i < d2.u.i) ? 1 : 0; + } + g_lingo->push(d1); +} + +void Lingo::c_ge() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.i = (d1.u.f >= d2.u.f) ? 1 : 0; + d1.type = INT; + } else { + d1.u.i = (d1.u.i >= d2.u.i) ? 1 : 0; + } + g_lingo->push(d1); +} + +void Lingo::c_le() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + if (g_lingo->alignTypes(d1, d2) == FLOAT) { + d1.u.i = (d1.u.f <= d2.u.f) ? 1 : 0; + d1.type = INT; + } else { + d1.u.i = (d1.u.i <= d2.u.i) ? 1 : 0; + } + g_lingo->push(d1); +} + +void Lingo::c_repeatwhilecode(void) { + Datum d; + int savepc = g_lingo->_pc; + + int body = READ_UINT32(&(*g_lingo->_currentScript)[savepc]); + int end = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 1]); + + g_lingo->execute(savepc + 2); /* condition */ + d = g_lingo->pop(); + d.toInt(); + + while (d.u.i) { + g_lingo->execute(body); /* body */ + if (g_lingo->_returning) + break; + + if (g_lingo->_exitRepeat) { + g_lingo->_exitRepeat = false; + break; + } + + g_lingo->execute(savepc + 2); /* condition */ + d = g_lingo->pop(); + d.toInt(); + } + + if (!g_lingo->_returning) + g_lingo->_pc = end; /* next stmt */ +} + +void Lingo::c_repeatwithcode(void) { + Datum d; + int savepc = g_lingo->_pc; + + int init = READ_UINT32(&(*g_lingo->_currentScript)[savepc]); + int finish = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 1]); + int body = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 2]); + int inc = (int32)READ_UINT32(&(*g_lingo->_currentScript)[savepc + 3]); + int end = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 4]); + Common::String countername((char *)&(*g_lingo->_currentScript)[savepc + 5]); + Symbol *counter = g_lingo->lookupVar(countername.c_str()); + + if (counter->type == CASTREF) { + error("Cast ref used as index: %s", countername.c_str()); + } + + g_lingo->execute(init); /* condition */ + d = g_lingo->pop(); + d.toInt(); + counter->u.i = d.u.i; + counter->type = INT; + + while (true) { + g_lingo->execute(body); /* body */ + if (g_lingo->_returning) + break; + + if (g_lingo->_exitRepeat) { + g_lingo->_exitRepeat = false; + break; + } + + counter->u.i += inc; + g_lingo->execute(finish); /* condition */ + d = g_lingo->pop(); + d.toInt(); + + if (counter->u.i == d.u.i + inc) + break; + } + + if (!g_lingo->_returning) + g_lingo->_pc = end; /* next stmt */ +} + +void Lingo::c_exitRepeat(void) { + g_lingo->_exitRepeat = true; +} + +void Lingo::c_ifcode() { + Datum d; + int savepc = g_lingo->_pc; /* then part */ + + int then = READ_UINT32(&(*g_lingo->_currentScript)[savepc]); + int elsep = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 1]); + int end = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 2]); + int skipEnd = READ_UINT32(&(*g_lingo->_currentScript)[savepc + 3]); + + debugC(8, kDebugLingoExec, "executing cond (have to %s end)", skipEnd ? "skip" : "execute"); + g_lingo->execute(savepc + 4); /* condition */ + + d = g_lingo->pop(); + + if (d.toInt()) { + debugC(8, kDebugLingoExec, "executing then"); + g_lingo->execute(then); + } else if (elsep) { /* else part? */ + debugC(8, kDebugLingoExec, "executing else"); + g_lingo->execute(elsep); + } + + if (!g_lingo->_returning && !skipEnd) { + g_lingo->_pc = end; /* next stmt */ + debugC(8, kDebugLingoExec, "executing end"); + } else { + debugC(8, kDebugLingoExec, "Skipped end"); + } +} + +void Lingo::c_whencode() { + Datum d; + int start = g_lingo->_pc; + int end = READ_UINT32(&(*g_lingo->_currentScript)[start]); + Common::String eventname((char *)&(*g_lingo->_currentScript)[start]); + + start += g_lingo->calcStringAlignment(eventname.c_str()); + + warning("STUB: c_whencode([%5d][%5d], %s)", start, end, eventname.c_str()); + + g_lingo->_pc = end; +} + +//************************ +// Built-in functions +//************************ +void Lingo::c_goto() { + Datum mode = g_lingo->pop(); + Datum frame, movie; + + if (mode.u.i == 2 || mode.u.i == 3) + movie = g_lingo->pop(); + + if (mode.u.i == 1 || mode.u.i == 3) + frame = g_lingo->pop(); + + g_lingo->func_goto(frame, movie); +} + +void Lingo::c_gotoloop() { + g_lingo->func_gotoloop(); +} + +void Lingo::c_gotonext() { + g_lingo->func_gotonext(); +} + +void Lingo::c_gotoprevious() { + g_lingo->func_gotoprevious(); +} + +void Lingo::c_play() { + Datum mode = g_lingo->pop(); + Datum frame, movie; + + if (mode.u.i == 2 || mode.u.i == 3) + movie = g_lingo->pop(); + + if (mode.u.i == 1 || mode.u.i == 3) + frame = g_lingo->pop(); + + if (frame.type == VOID) { + frame.u.s = new Common::String("<void>"); + frame.type = STRING; + } + frame.toString(); + + if (movie.type == VOID) { + movie.u.s = new Common::String("<void>"); + movie.type = STRING; + } + movie.toString(); + + warning("STUB: c_play(%s, %s)", frame.u.s->c_str(), movie.u.s->c_str()); +} + +void Lingo::c_playdone() { + warning("STUB: c_playdone()"); +} + +void Lingo::c_call() { + Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]); + g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); + + int nargs = READ_UINT32(&(*g_lingo->_currentScript)[g_lingo->_pc++]); + + g_lingo->call(name, nargs); +} + +void Lingo::call(Common::String &name, int nargs) { + bool drop = false; + + Symbol *sym; + + if (!g_lingo->_handlers.contains(name)) { + Symbol *s = g_lingo->lookupVar(name.c_str(), false); + if (s && s->type == OBJECT) { + debugC(3, kDebugLingoExec, "Dereferencing object reference: %s to %s", name.c_str(), s->u.s->c_str()); + name = *s->u.s; + } + } + + if (!g_lingo->_handlers.contains(name)) { + warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs); + drop = true; + } else { + sym = g_lingo->_handlers[name]; + + if (sym->type == BLTIN && sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) { + if (sym->nargs == sym->maxArgs) + warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs); + else + warning("Incorrect number of arguments to handler '%s', expecting %d or %d. Dropping %d stack items", name.c_str(), sym->nargs, sym->maxArgs, nargs); + + drop = true; + } + } + + if (drop) { + for (int i = 0; i < nargs; i++) + g_lingo->pop(); + + // Push dummy value + g_lingo->pushVoid(); + + return; + } + + if (sym->nargs != -1 && sym->nargs < nargs) { + warning("Incorrect number of arguments for function %s. Dropping extra %d", name.c_str(), nargs - sym->nargs); + for (int i = 0; i < nargs - sym->nargs; i++) + g_lingo->pop(); + } + + if (sym->type == BLTIN) { + if (sym->u.bltin == b_factory) + g_lingo->factoryCall(name, nargs); + else + (*sym->u.bltin)(nargs); + + return; + } + + for (int i = nargs; i < sym->nargs; i++) { + Datum d; + + d.u.s = NULL; + d.type = VOID; + g_lingo->push(d); + } + + debugC(5, kDebugLingoExec, "Pushing frame %d", g_lingo->_callstack.size() + 1); + CFrame *fp = new CFrame; + + fp->sp = sym; + fp->retpc = g_lingo->_pc; + fp->retscript = g_lingo->_currentScript; + fp->localvars = g_lingo->_localvars; + + // Create new set of local variables + g_lingo->_localvars = new SymbolHash; + + g_lingo->_callstack.push_back(fp); + + g_lingo->_currentScript = sym->u.defn; + g_lingo->execute(0); + + g_lingo->_returning = false; +} + +void Lingo::c_procret() { + if (!g_lingo->_callstack.size()) { + warning("Call stack underflow"); + g_lingo->_returning = true; + return; + } + + debugC(5, kDebugLingoExec, "Popping frame %d", g_lingo->_callstack.size() + 1); + + CFrame *fp = g_lingo->_callstack.back(); + g_lingo->_callstack.pop_back(); + + g_lingo->_currentScript = fp->retscript; + g_lingo->_pc = fp->retpc; + + g_lingo->cleanLocalVars(); + + // Restore local variables + g_lingo->_localvars = fp->localvars; + + delete fp; + + g_lingo->_returning = true; +} + +void Lingo::c_global() { + Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]); + + Symbol *s = g_lingo->lookupVar(name.c_str(), false); + if (s && !s->global) { + warning("Local variable %s declared as global", name.c_str()); + } + + s = g_lingo->lookupVar(name.c_str(), true, true); + s->global = true; + + g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); +} + +void Lingo::c_instance() { + Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]); + + warning("STUB: c_instance(%s)", name.c_str()); + + g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); +} + +void Lingo::c_open() { + Datum d2 = g_lingo->pop(); + Datum d1 = g_lingo->pop(); + + d1.toString(); + d2.toString(); + + warning("STUB: c_open(%s, %s)", d1.u.s->c_str(), d2.u.s->c_str()); +} + +} diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp new file mode 100644 index 0000000000..c145184a19 --- /dev/null +++ b/engines/director/lingo/lingo-codegen.cpp @@ -0,0 +1,355 @@ +/* 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. + * + */ + +// Heavily inspired by hoc +// Copyright (C) AT&T 1995 +// All Rights Reserved +// +// Permission to use, copy, modify, and distribute this software and +// its documentation for any purpose and without fee is hereby +// granted, provided that the above copyright notice appear in all +// copies and that both that the copyright notice and this +// permission notice and warranty disclaimer appear in supporting +// documentation, and that the name of AT&T or any of its entities +// not be used in advertising or publicity pertaining to +// distribution of the software without specific, written prior +// permission. +// +// AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +// IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +// THIS SOFTWARE. + +#include "director/lingo/lingo.h" +#include "common/file.h" +#include "audio/decoders/wave.h" + +#include "director/lingo/lingo-gr.h" + +namespace Director { + +void Lingo::execute(int pc) { + for(_pc = pc; (*_currentScript)[_pc] != STOP && !_returning;) { + Common::String instr = decodeInstruction(_pc); + + if (debugChannelSet(5, kDebugLingoExec)) + printStack("Stack before: "); + + debugC(1, kDebugLingoExec, "[%3d]: %s", _pc, instr.c_str()); + + _pc++; + (*((*_currentScript)[_pc - 1]))(); + + if (debugChannelSet(5, kDebugLingoExec)) + printStack("Stack after: "); + } +} + +void Lingo::printStack(const char *s) { + Common::String stack(s); + + for (uint i = 0; i < _stack.size(); i++) { + Datum d = _stack[i]; + d.toString(); + stack += Common::String::format("<%s> ", d.u.s->c_str()); + } + debugC(5, kDebugLingoExec, "%s", stack.c_str()); +} + +Common::String Lingo::decodeInstruction(int pc, int *newPc) { + Symbol sym; + Common::String res; + + sym.u.func = (*_currentScript)[pc++]; + if (_functions.contains((void *)sym.u.s)) { + res = _functions[(void *)sym.u.s]->name; + const char *pars = _functions[(void *)sym.u.s]->proto; + inst i; + + while (*pars) { + switch (*pars++) { + case 'i': + { + i = (*_currentScript)[pc++]; + int v = READ_UINT32(&i); + + res += Common::String::format(" %d", v); + break; + } + case 'o': + { + i = (*_currentScript)[pc++]; + int v = READ_UINT32(&i); + + res += Common::String::format(" [%5d]", v); + break; + } + case 's': + { + char *s = (char *)&(*_currentScript)[pc]; + pc += calcStringAlignment(s); + + res += Common::String::format(" \"%s\"", s); + break; + } + default: + warning("decodeInstruction: Unknown parameter type: %c", pars[-1]); + } + + if (*pars) + res += ','; + } + } else { + res = "<unknown>"; + } + + if (newPc) + *newPc = pc; + + return res; +} + +Symbol *Lingo::lookupVar(const char *name, bool create, bool putInGlobalList) { + Symbol *sym; + + // Looking for the cast member constants + if (_vm->getVersion() < 4) { // TODO: There could be a flag 'Allow Outdated Lingo' in Movie Info in D4 + if (strlen(name) == 3) { + if (tolower(name[0]) >= 'a' && tolower(name[0]) <= 'h' && + name[1] >= '1' && name[1] <= '8' && + name[2] >= '1' && name[2] <= '8') { + + if (!create) + error("Cast reference used in wrong context: %s", name); + + int val = (tolower(name[0]) - 'a') * 64 + (name[1] - '1') * 8 + (name[2] - '1') + 1; + sym = new Symbol; + + sym->type = CASTREF; + sym->u.i = val; + + return sym; + } + } + } + + if (!_localvars->contains(name)) { // Create variable if it was not defined + if (!create) + return NULL; + + sym = new Symbol; + sym->name = (char *)calloc(strlen(name) + 1, 1); + Common::strlcpy(sym->name, name, strlen(name) + 1); + sym->type = VOID; + sym->u.i = 0; + + (*_localvars)[name] = sym; + + if (putInGlobalList) { + sym->global = true; + _globalvars[name] = sym; + } + } else { + sym = (*_localvars)[name]; + + if (sym->global) + sym = _globalvars[name]; + } + + return sym; +} + +void Lingo::cleanLocalVars() { + // Clean up current scope local variables and clean up memory + for (SymbolHash::const_iterator h = _localvars->begin(); h != _localvars->end(); ++h) { + if (!h->_value->global) + delete h->_value; + } + delete g_lingo->_localvars; +} + +void Lingo::define(Common::String &name, int start, int nargs, Common::String *prefix) { + Symbol *sym; + + if (prefix) + name = *prefix + "-" + name; + + debugC(3, kDebugLingoCompile, "define(\"%s\", %d, %d, %d)", name.c_str(), start, _currentScript->size() - 1, nargs); + + if (!_handlers.contains(name)) { // Create variable if it was not defined + sym = new Symbol; + + sym->name = (char *)calloc(name.size() + 1, 1); + Common::strlcpy(sym->name, name.c_str(), name.size() + 1); + sym->type = HANDLER; + + _handlers[name] = sym; + } else { + sym = g_lingo->_handlers[name]; + + warning("Redefining handler '%s'", name.c_str()); + delete sym->u.defn; + } + + sym->u.defn = new ScriptData(&(*_currentScript)[start], _currentScript->size() - start + 1); + sym->nargs = nargs; +} + +int Lingo::codeString(const char *str) { + int numInsts = calcStringAlignment(str); + + // Where we copy the string over + int pos = _currentScript->size(); + + // Allocate needed space in script + for (int i = 0; i < numInsts; i++) + _currentScript->push_back(0); + + byte *dst = (byte *)&_currentScript->front() + pos * sizeof(inst); + + memcpy(dst, str, strlen(str) + 1); + + return _currentScript->size(); +} + +int Lingo::codeFloat(double f) { + int numInsts = calcCodeAlignment(sizeof(double)); + + // Where we copy the string over + int pos = _currentScript->size(); + + // Allocate needed space in script + for (int i = 0; i < numInsts; i++) + _currentScript->push_back(0); + + double *dst = (double *)((byte *)&_currentScript->front() + pos * sizeof(inst)); + + *dst = f; + + return _currentScript->size(); +} + +int Lingo::codeConst(int val) { + int res = g_lingo->code1(g_lingo->c_constpush); + inst i = 0; + WRITE_UINT32(&i, val); + g_lingo->code1(i); + + return res; +} + +void Lingo::codeArg(Common::String *s) { + _argstack.push_back(s); +} + +void Lingo::codeArgStore() { + while (true) { + if (_argstack.empty()) { + break; + } + + Common::String *arg = _argstack.back(); + _argstack.pop_back(); + + code1(c_varpush); + codeString(arg->c_str()); + code1(c_assign); + code1(c_xpop); + + delete arg; + } +} + +int Lingo::codeFunc(Common::String *s, int numpar) { + int ret = g_lingo->code1(g_lingo->c_call); + + if (s->equalsIgnoreCase("me")) { + if (!g_lingo->_currentFactory.empty()) { + g_lingo->codeString(g_lingo->_currentFactory.c_str()); + debugC(2, kDebugLingoCompile, "Replaced 'me' with %s", g_lingo->_currentFactory.c_str()); + } else { + warning("'me' out of factory method"); + g_lingo->codeString(s->c_str()); + } + } else { + g_lingo->codeString(s->c_str()); + } + + inst num = 0; + WRITE_UINT32(&num, numpar); + g_lingo->code1(num); + + return ret; +} + +void Lingo::codeLabel(int label) { + _labelstack.push_back(label); +} + +void Lingo::processIf(int elselabel, int endlabel) { + inst ielse1, iend; + int else1 = elselabel; + + WRITE_UINT32(&iend, endlabel); + + while (true) { + if (_labelstack.empty()) { + warning("Label stack underflow"); + break; + } + + int label = _labelstack.back(); + _labelstack.pop_back(); + + // This is beginning of our if() + if (!label) + break; + + WRITE_UINT32(&ielse1, else1); + (*_currentScript)[label + 2] = ielse1; /* elsepart */ + (*_currentScript)[label + 3] = iend; /* end, if cond fails */ + + else1 = label; + } +} + +void Lingo::codeFactory(Common::String &name) { + _currentFactory = name; + + Symbol *sym = new Symbol; + + sym->name = (char *)calloc(name.size() + 1, 1); + Common::strlcpy(sym->name, name.c_str(), name.size()); + sym->type = BLTIN; + sym->nargs = -1; + sym->maxArgs = 0; + sym->parens = true; + sym->u.bltin = g_lingo->b_factory; + + _handlers[name] = sym; +} + +} diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp new file mode 100644 index 0000000000..e22044c1e9 --- /dev/null +++ b/engines/director/lingo/lingo-funcs.cpp @@ -0,0 +1,213 @@ +/* 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 "director/lingo/lingo.h" +#include "common/file.h" +#include "audio/decoders/wave.h" +#include "common/util.h" +#include "director/lingo/lingo-gr.h" +#include "director/sound.h" + +namespace Director { + +enum MCITokenType { + kMCITokenNone, + + kMCITokenOpen, + kMCITokenWait, + kMCITokenPlay, + + kMCITokenType, + kMCITokenAlias, + kMCITokenBuffer, + kMCITokenFrom, + kMCITokenTo, + kMCITokenRepeat +}; + +struct MCIToken { + MCITokenType command; // Command this flag belongs to + MCITokenType flag; + const char *token; + int pos; // Position of parameter to store. 0 is always filename. Negative parameters mean boolean +} MCITokens[] = { + { kMCITokenNone, kMCITokenOpen, "open", 0 }, + { kMCITokenOpen, kMCITokenType, "type", 1 }, + { kMCITokenOpen, kMCITokenAlias, "alias", 2 }, + { kMCITokenOpen, kMCITokenBuffer, "buffer", 3 }, + + { kMCITokenNone, kMCITokenPlay, "play", 0 }, + { kMCITokenPlay, kMCITokenFrom, "from", 1 }, + { kMCITokenPlay, kMCITokenTo, "to", 2 }, + { kMCITokenPlay, kMCITokenRepeat, "repeat", -3 }, // This is boolean parameter + + { kMCITokenNone, kMCITokenWait, "wait", 0 }, + + { kMCITokenNone, kMCITokenNone, 0, 0 } +}; + +void Lingo::func_mci(Common::String &s) { + Common::String params[5]; + MCITokenType command = kMCITokenNone; + + s.trim(); + s.toLowercase(); + + MCITokenType state = kMCITokenNone; + Common::String token; + const char *ptr = s.c_str(); + int respos = -1; + + while (*ptr) { + while (*ptr && *ptr == ' ') + ptr++; + + token.clear(); + + while (*ptr && *ptr != ' ') + token += *ptr++; + + switch (state) { + case kMCITokenNone: + { + MCIToken *f = MCITokens; + + while (f->token) { + if (command == f->command && token == f->token) + break; + + f++; + } + + if (command == kMCITokenNone) { // We caught command + command = f->flag; // Switching to processing this command parameters + } else if (f->flag == kMCITokenNone) { // Unmatched token, storing as filename + if (!params[0].empty()) + warning("Duplicate filename in MCI command: %s -> %s", params[0].c_str(), token.c_str()); + params[0] = token; + } else { // This is normal parameter, storing next token to designated position + if (f->pos > 0) { // This is normal parameter + state = f->flag; + respos = f->pos; + } else { // This is boolean + params[-f->pos] = "true"; + state = kMCITokenNone; + } + } + break; + } + default: + params[respos] = token; + state = kMCITokenNone; + break; + } + } + + switch (command) { + case kMCITokenOpen: + { + warning("MCI open file: %s, type: %s, alias: %s buffer: %s", params[0].c_str(), params[1].c_str(), params[2].c_str(), params[3].c_str()); + + Common::File *file = new Common::File(); + + if (!file->open(params[0])) { + warning("Failed to open %s", params[0].c_str()); + delete file; + return; + } + + if (params[1] == "waveaudio") { + Audio::AudioStream *sound = Audio::makeWAVStream(file, DisposeAfterUse::YES); + _audioAliases[params[2]] = sound; + } else { + warning("Unhandled audio type %s", params[2].c_str()); + } + } + break; + case kMCITokenPlay: + { + warning("MCI play file: %s, from: %s, to: %s, repeat: %s", params[0].c_str(), params[1].c_str(), params[2].c_str(), params[3].c_str()); + + if (!_audioAliases.contains(params[0])) { + warning("Unknown alias %s", params[0].c_str()); + return; + } + + uint32 from = strtol(params[1].c_str(), 0, 10); + uint32 to = strtol(params[2].c_str(), 0, 10); + + _vm->getSoundManager()->playMCI(*_audioAliases[params[0]], from, to); + } + break; + default: + warning("Unhandled MCI command: %s", s.c_str()); + } +} + +void Lingo::func_mciwait(Common::String &s) { + warning("STUB: MCI wait file: %s", s.c_str()); +} + +void Lingo::func_goto(Datum &frame, Datum &movie) { + if (movie.type != VOID) { + movie.toString(); + + if (!_vm->_movies || !_vm->_movies->contains(*movie.u.s)) { + warning("Movie %s does not exist", movie.u.s->c_str()); + return; + } + + _vm->_currentScore = _vm->_movies->getVal(*movie.u.s); + _vm->_currentScore->loadArchive(); + } + + if (!_vm->_currentScore) { + warning("func_goto: No score is loaded"); + return; + } + + if (frame.type == VOID) + return; + + if (frame.type == STRING) { + _vm->_currentScore->setStartToLabel(*frame.u.s); + return; + } + + frame.toInt(); + + _vm->_currentScore->setCurrentFrame(frame.u.i); +} + +void Lingo::func_gotoloop() { + _vm->_currentScore->gotoloop(); +} + +void Lingo::func_gotonext() { + _vm->_currentScore->gotonext(); +} + +void Lingo::func_gotoprevious() { + _vm->_currentScore->gotoprevious(); +} + +} diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp new file mode 100644 index 0000000000..7bb13adde0 --- /dev/null +++ b/engines/director/lingo/lingo-gr.cpp @@ -0,0 +1,2808 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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, 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. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + UNARY = 258, + CASTREF = 259, + VOID = 260, + VAR = 261, + POINT = 262, + RECT = 263, + ARRAY = 264, + SYMBOL = 265, + OBJECT = 266, + INT = 267, + THEENTITY = 268, + THEENTITYWITHID = 269, + FLOAT = 270, + BLTIN = 271, + BLTINNOARGS = 272, + BLTINNOARGSORONE = 273, + BLTINONEARG = 274, + BLTINARGLIST = 275, + ID = 276, + STRING = 277, + HANDLER = 278, + tDOWN = 279, + tELSE = 280, + tNLELSIF = 281, + tEND = 282, + tEXIT = 283, + tFRAME = 284, + tGLOBAL = 285, + tGO = 286, + tIF = 287, + tINTO = 288, + tLOOP = 289, + tMACRO = 290, + tMOVIE = 291, + tNEXT = 292, + tOF = 293, + tPREVIOUS = 294, + tPUT = 295, + tREPEAT = 296, + tSET = 297, + tTHEN = 298, + tTO = 299, + tWHEN = 300, + tWITH = 301, + tWHILE = 302, + tNLELSE = 303, + tFACTORY = 304, + tMETHOD = 305, + tOPEN = 306, + tPLAY = 307, + tDONE = 308, + tPLAYACCEL = 309, + tINSTANCE = 310, + tGE = 311, + tLE = 312, + tGT = 313, + tLT = 314, + tEQ = 315, + tNEQ = 316, + tAND = 317, + tOR = 318, + tNOT = 319, + tMOD = 320, + tCONCAT = 321, + tCONTAINS = 322, + tSTARTS = 323, + tSPRITE = 324, + tINTERSECTS = 325, + tWITHIN = 326 + }; +#endif +/* Tokens. */ +#define UNARY 258 +#define CASTREF 259 +#define VOID 260 +#define VAR 261 +#define POINT 262 +#define RECT 263 +#define ARRAY 264 +#define SYMBOL 265 +#define OBJECT 266 +#define INT 267 +#define THEENTITY 268 +#define THEENTITYWITHID 269 +#define FLOAT 270 +#define BLTIN 271 +#define BLTINNOARGS 272 +#define BLTINNOARGSORONE 273 +#define BLTINONEARG 274 +#define BLTINARGLIST 275 +#define ID 276 +#define STRING 277 +#define HANDLER 278 +#define tDOWN 279 +#define tELSE 280 +#define tNLELSIF 281 +#define tEND 282 +#define tEXIT 283 +#define tFRAME 284 +#define tGLOBAL 285 +#define tGO 286 +#define tIF 287 +#define tINTO 288 +#define tLOOP 289 +#define tMACRO 290 +#define tMOVIE 291 +#define tNEXT 292 +#define tOF 293 +#define tPREVIOUS 294 +#define tPUT 295 +#define tREPEAT 296 +#define tSET 297 +#define tTHEN 298 +#define tTO 299 +#define tWHEN 300 +#define tWITH 301 +#define tWHILE 302 +#define tNLELSE 303 +#define tFACTORY 304 +#define tMETHOD 305 +#define tOPEN 306 +#define tPLAY 307 +#define tDONE 308 +#define tPLAYACCEL 309 +#define tINSTANCE 310 +#define tGE 311 +#define tLE 312 +#define tGT 313 +#define tLT 314 +#define tEQ 315 +#define tNEQ 316 +#define tAND 317 +#define tOR 318 +#define tNOT 319 +#define tMOD 320 +#define tCONCAT 321 +#define tCONTAINS 322 +#define tSTARTS 323 +#define tSPRITE 324 +#define tINTERSECTS 325 +#define tWITHIN 326 + + + + +/* Copy the first part of user declarations. */ +#line 49 "engines/director/lingo/lingo-gr.y" + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/hash-str.h" + +#include "director/lingo/lingo.h" +#include "director/lingo/lingo-gr.h" + +extern int yylex(); +extern int yyparse(); + +using namespace Director; +void yyerror(char *s) { + g_lingo->_hadError = true; + warning("%s at line %d col %d", s, g_lingo->_linenumber, g_lingo->_colnumber); +} + + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 69 "engines/director/lingo/lingo-gr.y" +{ + Common::String *s; + int i; + double f; + int e[2]; // Entity + field + int code; + int narg; /* number of arguments */ + Common::Array<double> *arr; +} +/* Line 193 of yacc.c. */ +#line 268 "engines/director/lingo/lingo-gr.cpp" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ +#line 281 "engines/director/lingo/lingo-gr.cpp" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 92 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 995 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 85 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 37 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 130 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 269 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 326 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 79, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 78, 73, 2, + 80, 81, 76, 74, 84, 75, 2, 77, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 83, 72, 82, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 7, 9, 12, 14, 15, 17, 19, + 21, 23, 25, 30, 35, 40, 46, 51, 56, 62, + 64, 66, 68, 70, 79, 91, 104, 108, 117, 129, + 141, 148, 159, 170, 171, 175, 178, 180, 183, 185, + 192, 194, 200, 202, 206, 210, 213, 217, 219, 221, + 222, 223, 224, 227, 230, 234, 236, 238, 240, 242, + 247, 249, 251, 254, 256, 260, 264, 268, 272, 276, + 280, 284, 288, 292, 296, 300, 304, 307, 311, 315, + 319, 323, 326, 329, 333, 338, 343, 346, 348, 350, + 353, 355, 358, 361, 364, 367, 369, 372, 377, 380, + 382, 386, 388, 392, 395, 398, 401, 404, 408, 411, + 414, 416, 420, 423, 426, 429, 433, 436, 437, 446, + 449, 450, 459, 460, 462, 466, 471, 472, 476, 477, + 479 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 86, 0, -1, 86, 87, 88, -1, 88, -1, 1, + 87, -1, 79, -1, -1, 115, -1, 108, -1, 120, + -1, 89, -1, 91, -1, 40, 107, 33, 21, -1, + 42, 21, 72, 107, -1, 42, 13, 72, 107, -1, + 42, 14, 107, 72, 107, -1, 42, 21, 44, 107, + -1, 42, 13, 44, 107, -1, 42, 14, 107, 44, + 107, -1, 107, -1, 108, -1, 90, -1, 92, -1, + 99, 80, 98, 81, 105, 104, 27, 41, -1, 100, + 72, 107, 104, 44, 107, 104, 105, 104, 27, 41, + -1, 100, 72, 107, 104, 24, 44, 107, 104, 105, + 104, 27, 41, -1, 106, 107, 104, -1, 101, 98, + 43, 87, 105, 104, 27, 32, -1, 101, 98, 43, + 87, 105, 104, 48, 105, 104, 27, 32, -1, 101, + 98, 43, 87, 105, 104, 103, 94, 104, 27, 32, + -1, 101, 98, 43, 103, 90, 104, -1, 101, 98, + 43, 103, 90, 104, 48, 103, 90, 104, -1, 101, + 98, 43, 103, 90, 104, 95, 104, 93, 104, -1, + -1, 48, 103, 90, -1, 94, 97, -1, 97, -1, + 95, 96, -1, 96, -1, 102, 98, 43, 103, 91, + 104, -1, 95, -1, 102, 98, 43, 105, 104, -1, + 107, -1, 107, 72, 107, -1, 80, 98, 81, -1, + 41, 47, -1, 41, 46, 21, -1, 32, -1, 26, + -1, -1, -1, -1, 105, 87, -1, 105, 91, -1, + 45, 21, 43, -1, 12, -1, 15, -1, 22, -1, + 17, -1, 21, 80, 121, 81, -1, 21, -1, 13, + -1, 14, 107, -1, 89, -1, 107, 74, 107, -1, + 107, 75, 107, -1, 107, 76, 107, -1, 107, 77, + 107, -1, 107, 65, 107, -1, 107, 82, 107, -1, + 107, 83, 107, -1, 107, 61, 107, -1, 107, 56, + 107, -1, 107, 57, 107, -1, 107, 62, 107, -1, + 107, 63, 107, -1, 64, 107, -1, 107, 73, 107, + -1, 107, 66, 107, -1, 107, 67, 107, -1, 107, + 68, 107, -1, 74, 107, -1, 75, 107, -1, 80, + 107, 81, -1, 69, 107, 70, 107, -1, 69, 107, + 71, 107, -1, 40, 107, -1, 111, -1, 114, -1, + 28, 41, -1, 28, -1, 30, 109, -1, 55, 110, + -1, 19, 107, -1, 18, 107, -1, 18, -1, 20, + 121, -1, 51, 107, 46, 107, -1, 51, 107, -1, + 21, -1, 109, 84, 21, -1, 21, -1, 110, 84, + 21, -1, 31, 34, -1, 31, 37, -1, 31, 39, + -1, 31, 112, -1, 31, 112, 113, -1, 31, 113, + -1, 29, 107, -1, 107, -1, 38, 36, 107, -1, + 36, 107, -1, 52, 53, -1, 52, 112, -1, 52, + 112, 113, -1, 52, 113, -1, -1, 35, 21, 116, + 103, 118, 87, 119, 105, -1, 49, 21, -1, -1, + 50, 21, 117, 103, 118, 87, 119, 105, -1, -1, + 21, -1, 118, 84, 21, -1, 118, 87, 84, 21, + -1, -1, 21, 103, 121, -1, -1, 107, -1, 121, + 84, 107, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 105, 105, 106, 107, 110, 115, 116, 117, 118, + 119, 120, 123, 129, 135, 143, 151, 157, 165, 174, + 175, 177, 178, 183, 194, 210, 222, 230, 237, 246, + 255, 265, 275, 286, 287, 290, 291, 294, 295, 298, + 306, 307, 315, 316, 317, 319, 321, 327, 333, 340, + 342, 344, 345, 346, 349, 355, 356, 359, 362, 365, + 368, 372, 379, 385, 386, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 410, 411, 412, 413, + 414, 416, 417, 418, 421, 424, 427, 428, 429, 432, + 433, 436, 437, 448, 449, 450, 451, 454, 457, 462, + 463, 466, 467, 470, 471, 474, 477, 507, 507, 513, + 516, 516, 521, 522, 523, 524, 526, 530, 538, 539, + 540 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "UNARY", "CASTREF", "VOID", "VAR", + "POINT", "RECT", "ARRAY", "SYMBOL", "OBJECT", "INT", "THEENTITY", + "THEENTITYWITHID", "FLOAT", "BLTIN", "BLTINNOARGS", "BLTINNOARGSORONE", + "BLTINONEARG", "BLTINARGLIST", "ID", "STRING", "HANDLER", "tDOWN", + "tELSE", "tNLELSIF", "tEND", "tEXIT", "tFRAME", "tGLOBAL", "tGO", "tIF", + "tINTO", "tLOOP", "tMACRO", "tMOVIE", "tNEXT", "tOF", "tPREVIOUS", + "tPUT", "tREPEAT", "tSET", "tTHEN", "tTO", "tWHEN", "tWITH", "tWHILE", + "tNLELSE", "tFACTORY", "tMETHOD", "tOPEN", "tPLAY", "tDONE", + "tPLAYACCEL", "tINSTANCE", "tGE", "tLE", "tGT", "tLT", "tEQ", "tNEQ", + "tAND", "tOR", "tNOT", "tMOD", "tCONCAT", "tCONTAINS", "tSTARTS", + "tSPRITE", "tINTERSECTS", "tWITHIN", "'='", "'&'", "'+'", "'-'", "'*'", + "'/'", "'%'", "'\\n'", "'('", "')'", "'>'", "'<'", "','", "$accept", + "program", "nl", "programline", "asgn", "stmtoneliner", "stmt", "ifstmt", + "elsestmtoneliner", "elseifstmt", "elseifstmtoneliner", + "elseifstmtoneliner1", "elseifstmt1", "cond", "repeatwhile", + "repeatwith", "if", "elseif", "begin", "end", "stmtlist", "when", "expr", + "func", "globallist", "instancelist", "gotofunc", "gotoframe", + "gotomovie", "playfunc", "defn", "@1", "@2", "argdef", "argstore", + "macro", "arglist", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 61, 38, 43, 45, 42, 47, 37, 10, + 40, 41, 62, 60, 44 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 85, 86, 86, 86, 87, 88, 88, 88, 88, + 88, 88, 89, 89, 89, 89, 89, 89, 89, 90, + 90, 91, 91, 91, 91, 91, 91, 92, 92, 92, + 92, 92, 92, 93, 93, 94, 94, 95, 95, 96, + 97, 97, 98, 98, 98, 99, 100, 101, 102, 103, + 104, 105, 105, 105, 106, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, + 109, 110, 110, 111, 111, 111, 111, 111, 111, 112, + 112, 113, 113, 114, 114, 114, 114, 116, 115, 115, + 117, 115, 118, 118, 118, 118, 119, 120, 121, 121, + 121 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 3, 1, 2, 1, 0, 1, 1, 1, + 1, 1, 4, 4, 4, 5, 4, 4, 5, 1, + 1, 1, 1, 8, 11, 12, 3, 8, 11, 11, + 6, 10, 10, 0, 3, 2, 1, 2, 1, 6, + 1, 5, 1, 3, 3, 2, 3, 1, 1, 0, + 0, 0, 2, 2, 3, 1, 1, 1, 1, 4, + 1, 1, 2, 1, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, + 3, 2, 2, 3, 4, 4, 2, 1, 1, 2, + 1, 2, 2, 2, 2, 1, 2, 4, 2, 1, + 3, 1, 3, 2, 2, 2, 2, 3, 2, 2, + 1, 3, 2, 2, 2, 3, 2, 0, 8, 2, + 0, 8, 0, 1, 3, 4, 0, 3, 0, 1, + 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 55, 61, 0, 56, 58, 95, 0, 128, + 49, 57, 90, 0, 0, 47, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 63, 21, 11, 22, 0, 0, 0, + 0, 19, 8, 87, 88, 7, 9, 5, 4, 60, + 0, 63, 62, 94, 93, 129, 96, 128, 128, 89, + 99, 91, 0, 103, 0, 104, 0, 105, 110, 106, + 108, 117, 86, 0, 45, 0, 0, 0, 0, 119, + 120, 98, 113, 114, 116, 101, 92, 76, 0, 81, + 82, 0, 1, 6, 0, 0, 0, 0, 42, 50, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, + 0, 109, 112, 0, 107, 49, 0, 46, 0, 0, + 0, 0, 0, 54, 49, 0, 115, 0, 0, 0, + 83, 2, 0, 50, 0, 0, 49, 0, 26, 72, + 73, 71, 74, 75, 68, 78, 79, 80, 77, 64, + 65, 66, 67, 69, 70, 130, 59, 100, 111, 122, + 12, 17, 14, 0, 0, 16, 13, 122, 97, 102, + 84, 85, 51, 0, 44, 51, 0, 43, 123, 0, + 18, 15, 0, 50, 0, 0, 50, 50, 20, 0, + 126, 126, 52, 53, 0, 0, 50, 49, 30, 124, + 0, 51, 51, 0, 50, 51, 0, 51, 0, 48, + 49, 50, 38, 0, 125, 118, 121, 23, 51, 50, + 27, 50, 50, 40, 36, 0, 0, 37, 33, 0, + 50, 0, 0, 35, 0, 0, 50, 49, 50, 49, + 0, 0, 0, 0, 49, 31, 0, 32, 0, 0, + 24, 28, 29, 50, 34, 50, 25, 41, 39 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 31, 202, 32, 51, 34, 203, 36, 248, 232, + 233, 222, 234, 97, 37, 38, 39, 223, 258, 148, + 193, 40, 41, 198, 61, 86, 43, 69, 70, 44, + 45, 125, 134, 189, 211, 46, 56 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -206 +static const yytype_int16 yypact[] = +{ + 263, -61, -206, -206, 671, -206, -206, 671, 671, 671, + 912, -206, -17, 9, 593, -206, 14, 671, 8, 6, + 20, 24, 29, 671, 634, 31, 671, 671, 671, 671, + 671, 3, -206, 4, -206, -206, -206, -21, -8, 707, + 671, 889, -206, -206, -206, -206, -206, -206, -206, -20, + 671, -206, 889, 889, 889, 889, 1, 671, 671, -206, + -206, 7, 671, -206, 671, -206, 37, -206, 889, 13, + -206, -206, 723, 54, -206, -38, 671, -34, 41, -206, + -206, 774, -206, 13, -206, -206, 10, -43, 797, -43, + -43, 843, -206, 332, 707, 671, 707, 43, 866, 889, + 671, 671, 671, 671, 671, 671, 671, 671, 671, 671, + 671, 671, 671, 671, 671, 671, 723, 671, -59, 1, + 67, 889, 889, 671, -206, -206, 69, -206, 671, 671, + 751, 671, 671, -206, -206, 671, -206, 71, 671, 671, + -206, -206, 18, 889, 19, 820, -61, 671, -206, 44, + 44, 44, -43, -43, -43, 889, 44, 44, 166, 224, + 224, -43, -43, 889, 889, 889, -206, -206, 889, 81, + -206, 889, 889, 671, 671, 889, 889, 81, 889, -206, + 889, 889, -206, -7, -206, -206, 529, 889, -206, -58, + 889, 889, -58, 396, 60, 671, 396, -206, -206, 84, + 27, 27, -206, -206, 85, 671, 889, -16, -12, -206, + 87, -206, -206, 73, 889, -206, 90, -206, 97, -206, + -206, 97, -206, 707, -206, 396, 396, -206, -206, 396, + -206, 396, 97, 97, -206, 707, 529, -206, 76, 86, + 396, 101, 104, -206, 105, 93, -206, -206, -206, -206, + 111, 114, 126, 127, -18, -206, 529, -206, 465, 120, + -206, -206, -206, 396, -206, -206, -206, -206, -206 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -206, -206, 11, 70, 2, -179, 0, -206, -206, -206, + -44, -205, -67, -63, -206, -206, -206, -203, -9, -13, + -141, -206, 39, 5, -206, -206, -206, 142, -11, -206, + -206, -206, -206, -4, -32, -206, 23 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -61 +static const yytype_int16 yytable[] = +{ + 35, 58, 33, 92, -10, 42, 128, 197, -51, -51, + 131, 216, 48, 84, 219, 235, 237, 194, 47, 75, + 76, 47, 166, 106, 59, 117, 199, 77, 237, 235, + 60, 142, 217, 144, 129, 71, 220, 195, 132, 114, + 115, 78, 93, 52, 196, 79, 53, 54, 55, 64, + 80, 66, 85, 68, 73, 74, 72, 246, 124, 94, + 57, -51, 81, 68, 95, 87, 88, 89, 90, 91, + 225, 226, 136, 123, 229, 127, 231, 264, 98, 99, + 118, 119, 47, -10, 133, 117, 146, 240, 167, 116, + 170, 120, 179, 35, 137, 33, 55, 55, 42, 182, + 184, 121, 188, 122, 205, 209, 103, 104, 224, 105, + 106, 210, 213, 263, 227, 130, 169, 109, 110, 111, + 112, 113, 230, 219, 247, 177, 114, 115, 251, 249, + 183, 252, 253, 98, 143, 145, 254, 186, 259, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 260, 165, 185, 261, 262, + 239, 266, 168, 141, 221, 243, 83, 171, 172, 212, + 175, 176, 245, 192, 178, 0, 0, 180, 181, 0, + 204, 0, 0, 207, 208, 0, 187, 0, 0, 0, + 0, 0, 0, 215, 0, 0, 0, 0, 218, 0, + 200, 228, 0, 201, 0, 0, 0, 0, 238, 0, + 0, 236, 190, 191, 0, 0, 241, 0, 242, 244, + 0, 0, 0, 0, 0, 0, 0, 250, 103, 104, + 0, 105, 106, 255, 206, 257, 0, 0, 256, 0, + 110, 111, 112, 113, 214, 0, 0, 0, 114, 115, + 267, 0, 268, 0, 0, 0, 0, 0, 265, 0, + 0, 0, 98, -6, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 98, 2, 3, 4, 5, 0, + 6, 7, 8, 9, 10, 11, 103, 104, 0, 105, + 106, 12, 0, 13, 14, 15, 0, 0, 16, 0, + 112, 113, 0, 17, 18, 19, 114, 115, 20, 0, + 0, 0, 21, 22, 23, 24, 0, 0, 25, 0, + 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, + 0, 0, 27, 0, 0, 0, 0, 28, 29, 0, + 0, 0, -6, 30, 2, 3, 4, 5, 0, 6, + 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, + 12, 0, 13, 14, 15, 0, 0, 16, 0, 0, + 0, 0, 17, 18, 19, 0, 0, 20, 0, 0, + 0, 21, 22, 23, 24, 0, 0, 25, 0, 0, + 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, + 0, 27, 0, 0, 0, 0, 28, 29, 2, 3, + 4, 5, 30, 6, 7, 8, 9, 49, 11, 0, + 0, 0, 0, 0, 12, 0, 13, 14, 15, 0, + 0, 0, 0, 0, 0, 0, 17, 18, 19, 0, + 0, 20, 0, 0, 0, 0, 0, 23, 24, 0, + 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 0, 27, 0, 0, 0, 0, + 28, 29, 0, 0, 0, 47, 30, 2, 3, 4, + 5, 0, 6, 7, 8, 9, 49, 11, 0, 0, + 0, 0, 0, 12, 0, 13, 14, 15, 0, 0, + 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, + 20, 0, 0, 0, 0, 0, 23, 24, 0, 0, + 25, 0, 0, 0, 0, 0, 0, 0, 0, 26, + 0, 0, 0, 0, 27, 0, 0, 0, 0, 28, + 29, 2, 3, 4, 5, 30, 6, 7, 8, 9, + 49, 11, 0, 0, 0, 0, 0, 12, 0, 13, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 24, 0, 0, 25, 0, 0, 0, 0, 0, + 0, 0, 0, 26, 0, 0, 0, 0, 27, 0, + 0, 0, 0, 28, 29, 2, 3, 4, 5, 30, + 6, 0, 0, 0, 49, 11, 0, 0, 0, 0, + 0, 0, 62, 0, 0, 0, 0, 63, 0, 64, + 65, 66, 67, 50, 0, 19, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, + 0, 6, 0, 0, 0, 49, 11, 26, 0, 0, + 0, 0, 27, 62, 0, 0, 0, 28, 29, 0, + 64, 0, 66, 30, 50, 0, 19, 0, 0, 0, + 0, 0, 0, 2, 3, 4, 5, 82, 6, 0, + 0, 0, 49, 11, 0, 0, 0, 0, 26, 0, + 0, 0, 0, 27, 0, 0, 0, 0, 28, 29, + 0, 50, 0, 19, 30, 0, 0, 0, 0, 2, + 3, 4, 5, 0, 6, 0, 0, 0, 49, 11, + 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, + 27, 0, 0, 0, 0, 28, 29, 50, 0, 19, + 0, 30, 0, 0, 0, 0, 126, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 26, 0, 0, 0, 0, 27, 0, 0, 100, + 101, 28, 29, 0, 102, 103, 104, 96, 105, 106, + 107, 108, 0, 0, 0, 173, 109, 110, 111, 112, + 113, 0, 0, 0, 0, 114, 115, 100, 101, 0, + 0, 0, 102, 103, 104, 0, 105, 106, 107, 108, + 135, 0, 0, 174, 109, 110, 111, 112, 113, 0, + 100, 101, 0, 114, 115, 102, 103, 104, 0, 105, + 106, 107, 108, 0, 0, 0, 0, 109, 110, 111, + 112, 113, 0, 100, 101, 0, 114, 115, 102, 103, + 104, 0, 105, 106, 107, 108, 0, 138, 139, 0, + 109, 110, 111, 112, 113, 0, 100, 101, 0, 114, + 115, 102, 103, 104, 0, 105, 106, 107, 108, 0, + 0, 0, 147, 109, 110, 111, 112, 113, 0, 100, + 101, 140, 114, 115, 102, 103, 104, 0, 105, 106, + 107, 108, 0, 0, 0, 0, 109, 110, 111, 112, + 113, 0, 100, 101, 140, 114, 115, 102, 103, 104, + 0, 105, 106, 107, 108, 0, 0, 0, 147, 109, + 110, 111, 112, 113, 0, 100, 101, 0, 114, 115, + 102, 103, 104, 0, 105, 106, 107, 108, 0, 0, + 0, 0, 109, 110, 111, 112, 113, 0, -60, -60, + 0, 114, 115, -60, -60, -60, 0, -60, -60, -60, + -60, 0, 0, 0, 0, -60, 0, 0, -60, -60, + 0, 0, 57, 0, -60, -60 +}; + +static const yytype_int16 yycheck[] = +{ + 0, 10, 0, 0, 0, 0, 44, 186, 26, 27, + 44, 27, 1, 24, 26, 218, 221, 24, 79, 13, + 14, 79, 81, 66, 41, 84, 84, 21, 233, 232, + 21, 94, 48, 96, 72, 21, 48, 44, 72, 82, + 83, 21, 31, 4, 185, 21, 7, 8, 9, 36, + 21, 38, 21, 14, 46, 47, 17, 236, 69, 80, + 80, 79, 23, 24, 72, 26, 27, 28, 29, 30, + 211, 212, 83, 36, 215, 21, 217, 256, 39, 40, + 57, 58, 79, 79, 43, 84, 43, 228, 21, 50, + 21, 84, 21, 93, 84, 93, 57, 58, 93, 81, + 81, 62, 21, 64, 44, 21, 62, 63, 21, 65, + 66, 84, 27, 254, 41, 76, 125, 73, 74, 75, + 76, 77, 32, 26, 48, 134, 82, 83, 27, 43, + 143, 27, 27, 94, 95, 96, 43, 146, 27, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 41, 117, 146, 32, 32, + 223, 41, 123, 93, 208, 232, 24, 128, 129, 201, + 131, 132, 235, 177, 135, -1, -1, 138, 139, -1, + 193, -1, -1, 196, 197, -1, 147, -1, -1, -1, + -1, -1, -1, 206, -1, -1, -1, -1, 207, -1, + 189, 214, -1, 192, -1, -1, -1, -1, 221, -1, + -1, 220, 173, 174, -1, -1, 229, -1, 231, 232, + -1, -1, -1, -1, -1, -1, -1, 240, 62, 63, + -1, 65, 66, 246, 195, 248, -1, -1, 247, -1, + 74, 75, 76, 77, 205, -1, -1, -1, 82, 83, + 263, -1, 265, -1, -1, -1, -1, -1, 258, -1, + -1, -1, 223, 0, 1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 235, 12, 13, 14, 15, -1, + 17, 18, 19, 20, 21, 22, 62, 63, -1, 65, + 66, 28, -1, 30, 31, 32, -1, -1, 35, -1, + 76, 77, -1, 40, 41, 42, 82, 83, 45, -1, + -1, -1, 49, 50, 51, 52, -1, -1, 55, -1, + -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, + -1, -1, 69, -1, -1, -1, -1, 74, 75, -1, + -1, -1, 79, 80, 12, 13, 14, 15, -1, 17, + 18, 19, 20, 21, 22, -1, -1, -1, -1, -1, + 28, -1, 30, 31, 32, -1, -1, 35, -1, -1, + -1, -1, 40, 41, 42, -1, -1, 45, -1, -1, + -1, 49, 50, 51, 52, -1, -1, 55, -1, -1, + -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, + -1, 69, -1, -1, -1, -1, 74, 75, 12, 13, + 14, 15, 80, 17, 18, 19, 20, 21, 22, -1, + -1, -1, -1, -1, 28, -1, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, 42, -1, + -1, 45, -1, -1, -1, -1, -1, 51, 52, -1, + -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, + 64, -1, -1, -1, -1, 69, -1, -1, -1, -1, + 74, 75, -1, -1, -1, 79, 80, 12, 13, 14, + 15, -1, 17, 18, 19, 20, 21, 22, -1, -1, + -1, -1, -1, 28, -1, 30, 31, 32, -1, -1, + -1, -1, -1, -1, -1, 40, 41, 42, -1, -1, + 45, -1, -1, -1, -1, -1, 51, 52, -1, -1, + 55, -1, -1, -1, -1, -1, -1, -1, -1, 64, + -1, -1, -1, -1, 69, -1, -1, -1, -1, 74, + 75, 12, 13, 14, 15, 80, 17, 18, 19, 20, + 21, 22, -1, -1, -1, -1, -1, 28, -1, 30, + 31, -1, -1, -1, -1, -1, -1, -1, -1, 40, + -1, 42, -1, -1, -1, -1, -1, -1, -1, -1, + 51, 52, -1, -1, 55, -1, -1, -1, -1, -1, + -1, -1, -1, 64, -1, -1, -1, -1, 69, -1, + -1, -1, -1, 74, 75, 12, 13, 14, 15, 80, + 17, -1, -1, -1, 21, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, -1, 34, -1, 36, + 37, 38, 39, 40, -1, 42, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 12, 13, 14, 15, + -1, 17, -1, -1, -1, 21, 22, 64, -1, -1, + -1, -1, 69, 29, -1, -1, -1, 74, 75, -1, + 36, -1, 38, 80, 40, -1, 42, -1, -1, -1, + -1, -1, -1, 12, 13, 14, 15, 53, 17, -1, + -1, -1, 21, 22, -1, -1, -1, -1, 64, -1, + -1, -1, -1, 69, -1, -1, -1, -1, 74, 75, + -1, 40, -1, 42, 80, -1, -1, -1, -1, 12, + 13, 14, 15, -1, 17, -1, -1, -1, 21, 22, + -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, + 69, -1, -1, -1, -1, 74, 75, 40, -1, 42, + -1, 80, -1, -1, -1, -1, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 64, -1, -1, -1, -1, 69, -1, -1, 56, + 57, 74, 75, -1, 61, 62, 63, 80, 65, 66, + 67, 68, -1, -1, -1, 44, 73, 74, 75, 76, + 77, -1, -1, -1, -1, 82, 83, 56, 57, -1, + -1, -1, 61, 62, 63, -1, 65, 66, 67, 68, + 46, -1, -1, 72, 73, 74, 75, 76, 77, -1, + 56, 57, -1, 82, 83, 61, 62, 63, -1, 65, + 66, 67, 68, -1, -1, -1, -1, 73, 74, 75, + 76, 77, -1, 56, 57, -1, 82, 83, 61, 62, + 63, -1, 65, 66, 67, 68, -1, 70, 71, -1, + 73, 74, 75, 76, 77, -1, 56, 57, -1, 82, + 83, 61, 62, 63, -1, 65, 66, 67, 68, -1, + -1, -1, 72, 73, 74, 75, 76, 77, -1, 56, + 57, 81, 82, 83, 61, 62, 63, -1, 65, 66, + 67, 68, -1, -1, -1, -1, 73, 74, 75, 76, + 77, -1, 56, 57, 81, 82, 83, 61, 62, 63, + -1, 65, 66, 67, 68, -1, -1, -1, 72, 73, + 74, 75, 76, 77, -1, 56, 57, -1, 82, 83, + 61, 62, 63, -1, 65, 66, 67, 68, -1, -1, + -1, -1, 73, 74, 75, 76, 77, -1, 56, 57, + -1, 82, 83, 61, 62, 63, -1, 65, 66, 67, + 68, -1, -1, -1, -1, 73, -1, -1, 76, 77, + -1, -1, 80, -1, 82, 83 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 1, 12, 13, 14, 15, 17, 18, 19, 20, + 21, 22, 28, 30, 31, 32, 35, 40, 41, 42, + 45, 49, 50, 51, 52, 55, 64, 69, 74, 75, + 80, 86, 88, 89, 90, 91, 92, 99, 100, 101, + 106, 107, 108, 111, 114, 115, 120, 79, 87, 21, + 40, 89, 107, 107, 107, 107, 121, 80, 103, 41, + 21, 109, 29, 34, 36, 37, 38, 39, 107, 112, + 113, 21, 107, 46, 47, 13, 14, 21, 21, 21, + 21, 107, 53, 112, 113, 21, 110, 107, 107, 107, + 107, 107, 0, 87, 80, 72, 80, 98, 107, 107, + 56, 57, 61, 62, 63, 65, 66, 67, 68, 73, + 74, 75, 76, 77, 82, 83, 107, 84, 121, 121, + 84, 107, 107, 36, 113, 116, 33, 21, 44, 72, + 107, 44, 72, 43, 117, 46, 113, 84, 70, 71, + 81, 88, 98, 107, 98, 107, 43, 72, 104, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 81, 21, 107, 103, + 21, 107, 107, 44, 72, 107, 107, 103, 107, 21, + 107, 107, 81, 104, 81, 87, 103, 107, 21, 118, + 107, 107, 118, 105, 24, 44, 105, 90, 108, 84, + 87, 87, 87, 91, 104, 44, 107, 104, 104, 21, + 84, 119, 119, 27, 107, 104, 27, 48, 103, 26, + 48, 95, 96, 102, 21, 105, 105, 41, 104, 105, + 32, 105, 94, 95, 97, 102, 103, 96, 104, 98, + 105, 104, 104, 97, 104, 98, 90, 48, 93, 43, + 104, 27, 27, 27, 43, 104, 103, 104, 103, 27, + 41, 32, 32, 105, 90, 91, 41, 104, 104 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: +#line 107 "engines/director/lingo/lingo-gr.y" + { yyerrok; ;} + break; + + case 5: +#line 110 "engines/director/lingo/lingo-gr.y" + { + g_lingo->_linenumber++; + g_lingo->_colnumber = 1; + ;} + break; + + case 10: +#line 119 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_xpop); ;} + break; + + case 12: +#line 123 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_varpush); + g_lingo->codeString((yyvsp[(4) - (4)].s)->c_str()); + g_lingo->code1(g_lingo->c_assign); + (yyval.code) = (yyvsp[(2) - (4)].code); + delete (yyvsp[(4) - (4)].s); ;} + break; + + case 13: +#line 129 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_varpush); + g_lingo->codeString((yyvsp[(2) - (4)].s)->c_str()); + g_lingo->code1(g_lingo->c_assign); + (yyval.code) = (yyvsp[(4) - (4)].code); + delete (yyvsp[(2) - (4)].s); ;} + break; + + case 14: +#line 135 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(0); // Put dummy id + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, (yyvsp[(2) - (4)].e)[0]); + WRITE_UINT32(&f, (yyvsp[(2) - (4)].e)[1]); + g_lingo->code2(e, f); + (yyval.code) = (yyvsp[(4) - (4)].code); ;} + break; + + case 15: +#line 143 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_swap); + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, (yyvsp[(2) - (5)].e)[0]); + WRITE_UINT32(&f, (yyvsp[(2) - (5)].e)[1]); + g_lingo->code2(e, f); + (yyval.code) = (yyvsp[(5) - (5)].code); ;} + break; + + case 16: +#line 151 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_varpush); + g_lingo->codeString((yyvsp[(2) - (4)].s)->c_str()); + g_lingo->code1(g_lingo->c_assign); + (yyval.code) = (yyvsp[(4) - (4)].code); + delete (yyvsp[(2) - (4)].s); ;} + break; + + case 17: +#line 157 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(0); // Put dummy id + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, (yyvsp[(2) - (4)].e)[0]); + WRITE_UINT32(&f, (yyvsp[(2) - (4)].e)[1]); + g_lingo->code2(e, f); + (yyval.code) = (yyvsp[(4) - (4)].code); ;} + break; + + case 18: +#line 165 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_swap); + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, (yyvsp[(2) - (5)].e)[0]); + WRITE_UINT32(&f, (yyvsp[(2) - (5)].e)[1]); + g_lingo->code2(e, f); + (yyval.code) = (yyvsp[(5) - (5)].code); ;} + break; + + case 19: +#line 174 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_xpop); ;} + break; + + case 23: +#line 183 "engines/director/lingo/lingo-gr.y" + { + inst body = 0, end = 0; + WRITE_UINT32(&body, (yyvsp[(5) - (8)].code)); + WRITE_UINT32(&end, (yyvsp[(6) - (8)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (8)].code) + 1] = body; /* body of loop */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (8)].code) + 2] = end; ;} + break; + + case 24: +#line 194 "engines/director/lingo/lingo-gr.y" + { + inst init = 0, finish = 0, body = 0, end = 0, inc = 0; + WRITE_UINT32(&init, (yyvsp[(3) - (11)].code)); + WRITE_UINT32(&finish, (yyvsp[(6) - (11)].code)); + WRITE_UINT32(&body, (yyvsp[(8) - (11)].code)); + WRITE_UINT32(&end, (yyvsp[(9) - (11)].code)); + WRITE_UINT32(&inc, 1); + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 1] = init; /* initial count value */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 2] = finish;/* final count value */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 3] = body; /* body of loop */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 4] = inc; /* increment */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 5] = end; ;} + break; + + case 25: +#line 210 "engines/director/lingo/lingo-gr.y" + { + inst init = 0, finish = 0, body = 0, end = 0, inc = 0; + WRITE_UINT32(&init, (yyvsp[(3) - (12)].code)); + WRITE_UINT32(&finish, (yyvsp[(7) - (12)].code)); + WRITE_UINT32(&body, (yyvsp[(9) - (12)].code)); + WRITE_UINT32(&end, (yyvsp[(10) - (12)].code)); + WRITE_UINT32(&inc, -1); + (*g_lingo->_currentScript)[(yyvsp[(1) - (12)].code) + 1] = init; /* initial count value */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (12)].code) + 2] = finish;/* final count value */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (12)].code) + 3] = body; /* body of loop */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (12)].code) + 4] = inc; /* increment */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (12)].code) + 5] = end; ;} + break; + + case 26: +#line 222 "engines/director/lingo/lingo-gr.y" + { + inst end = 0; + WRITE_UINT32(&end, (yyvsp[(3) - (3)].code)); + g_lingo->code1(STOP); + (*g_lingo->_currentScript)[(yyvsp[(1) - (3)].code) + 1] = end; + ;} + break; + + case 27: +#line 230 "engines/director/lingo/lingo-gr.y" + { + inst then = 0, end = 0; + WRITE_UINT32(&then, (yyvsp[(5) - (8)].code)); + WRITE_UINT32(&end, (yyvsp[(6) - (8)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (8)].code) + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (8)].code) + 3] = end; /* end, if cond fails */ + g_lingo->processIf(0, 0); ;} + break; + + case 28: +#line 237 "engines/director/lingo/lingo-gr.y" + { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, (yyvsp[(5) - (11)].code)); + WRITE_UINT32(&else1, (yyvsp[(8) - (11)].code)); + WRITE_UINT32(&end, (yyvsp[(9) - (11)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 3] = end; /* end, if cond fails */ + g_lingo->processIf(0, 0); ;} + break; + + case 29: +#line 246 "engines/director/lingo/lingo-gr.y" + { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, (yyvsp[(5) - (11)].code)); + WRITE_UINT32(&else1, (yyvsp[(7) - (11)].code)); + WRITE_UINT32(&end, (yyvsp[(9) - (11)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (11)].code) + 3] = end; /* end, if cond fails */ + g_lingo->processIf(0, (yyvsp[(9) - (11)].code)); ;} + break; + + case 30: +#line 255 "engines/director/lingo/lingo-gr.y" + { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, (yyvsp[(4) - (6)].code)); + WRITE_UINT32(&else1, 0); + WRITE_UINT32(&end, (yyvsp[(6) - (6)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 3] = end; /* end, if cond fails */ + + g_lingo->processIf(0, 0); ;} + break; + + case 31: +#line 265 "engines/director/lingo/lingo-gr.y" + { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, (yyvsp[(4) - (10)].code)); + WRITE_UINT32(&else1, (yyvsp[(8) - (10)].code)); + WRITE_UINT32(&end, (yyvsp[(10) - (10)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */ + + g_lingo->processIf(0, 0); ;} + break; + + case 32: +#line 275 "engines/director/lingo/lingo-gr.y" + { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, (yyvsp[(4) - (10)].code)); + WRITE_UINT32(&else1, (yyvsp[(6) - (10)].code)); + WRITE_UINT32(&end, (yyvsp[(10) - (10)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[(yyvsp[(1) - (10)].code) + 3] = end; /* end, if cond fails */ + + g_lingo->processIf(0, (yyvsp[(10) - (10)].code)); ;} + break; + + case 33: +#line 286 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = 0; ;} + break; + + case 34: +#line 287 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = (yyvsp[(2) - (3)].code); ;} + break; + + case 39: +#line 298 "engines/director/lingo/lingo-gr.y" + { + inst then = 0; + WRITE_UINT32(&then, (yyvsp[(4) - (6)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (6)].code) + 1] = then; /* thenpart */ + + g_lingo->codeLabel((yyvsp[(1) - (6)].code)); ;} + break; + + case 41: +#line 307 "engines/director/lingo/lingo-gr.y" + { + inst then = 0; + WRITE_UINT32(&then, (yyvsp[(4) - (5)].code)); + (*g_lingo->_currentScript)[(yyvsp[(1) - (5)].code) + 1] = then; /* thenpart */ + + g_lingo->codeLabel((yyvsp[(1) - (5)].code)); ;} + break; + + case 42: +#line 315 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(STOP); ;} + break; + + case 43: +#line 316 "engines/director/lingo/lingo-gr.y" + { g_lingo->code2(g_lingo->c_eq, STOP); ;} + break; + + case 45: +#line 319 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = g_lingo->code3(g_lingo->c_repeatwhilecode, STOP, STOP); ;} + break; + + case 46: +#line 321 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code3(g_lingo->c_repeatwithcode, STOP, STOP); + g_lingo->code3(STOP, STOP, STOP); + g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); + delete (yyvsp[(3) - (3)].s); ;} + break; + + case 47: +#line 327 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_ifcode); + g_lingo->code3(STOP, STOP, STOP); + g_lingo->code1(0); // Do not skip end + g_lingo->codeLabel(0); ;} + break; + + case 48: +#line 333 "engines/director/lingo/lingo-gr.y" + { + inst skipEnd; + WRITE_UINT32(&skipEnd, 1); // We have to skip end to avoid multiple executions + (yyval.code) = g_lingo->code1(g_lingo->c_ifcode); + g_lingo->code3(STOP, STOP, STOP); + g_lingo->code1(skipEnd); ;} + break; + + case 49: +#line 340 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = g_lingo->_currentScript->size(); ;} + break; + + case 50: +#line 342 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(STOP); (yyval.code) = g_lingo->_currentScript->size(); ;} + break; + + case 51: +#line 344 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = g_lingo->_currentScript->size(); ;} + break; + + case 54: +#line 349 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_whencode); + g_lingo->code1(STOP); + g_lingo->codeString((yyvsp[(2) - (3)].s)->c_str()); + delete (yyvsp[(2) - (3)].s); ;} + break; + + case 55: +#line 355 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = g_lingo->codeConst((yyvsp[(1) - (1)].i)); ;} + break; + + case 56: +#line 356 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_fconstpush); + g_lingo->codeFloat((yyvsp[(1) - (1)].f)); ;} + break; + + case 57: +#line 359 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_stringpush); + g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); ;} + break; + + case 58: +#line 362 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->_handlers[*(yyvsp[(1) - (1)].s)]->u.func); + delete (yyvsp[(1) - (1)].s); ;} + break; + + case 59: +#line 365 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg)); + delete (yyvsp[(1) - (4)].s); ;} + break; + + case 60: +#line 368 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_eval); + g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); + delete (yyvsp[(1) - (1)].s); ;} + break; + + case 61: +#line 372 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->codeConst(0); // Put dummy id + g_lingo->code1(g_lingo->c_theentitypush); + inst e = 0, f = 0; + WRITE_UINT32(&e, (yyvsp[(1) - (1)].e)[0]); + WRITE_UINT32(&f, (yyvsp[(1) - (1)].e)[1]); + g_lingo->code2(e, f); ;} + break; + + case 62: +#line 379 "engines/director/lingo/lingo-gr.y" + { + (yyval.code) = g_lingo->code1(g_lingo->c_theentitypush); + inst e = 0, f = 0; + WRITE_UINT32(&e, (yyvsp[(1) - (2)].e)[0]); + WRITE_UINT32(&f, (yyvsp[(1) - (2)].e)[1]); + g_lingo->code2(e, f); ;} + break; + + case 64: +#line 386 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_add); ;} + break; + + case 65: +#line 387 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_sub); ;} + break; + + case 66: +#line 388 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_mul); ;} + break; + + case 67: +#line 389 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_div); ;} + break; + + case 68: +#line 390 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_mod); ;} + break; + + case 69: +#line 391 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_gt); ;} + break; + + case 70: +#line 392 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_lt); ;} + break; + + case 71: +#line 393 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_neq); ;} + break; + + case 72: +#line 394 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_ge); ;} + break; + + case 73: +#line 395 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_le); ;} + break; + + case 74: +#line 396 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_and); ;} + break; + + case 75: +#line 397 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_or); ;} + break; + + case 76: +#line 398 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_not); ;} + break; + + case 77: +#line 399 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_ampersand); ;} + break; + + case 78: +#line 400 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_concat); ;} + break; + + case 79: +#line 401 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_contains); ;} + break; + + case 80: +#line 402 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_starts); ;} + break; + + case 81: +#line 403 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = (yyvsp[(2) - (2)].code); ;} + break; + + case 82: +#line 404 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = (yyvsp[(2) - (2)].code); g_lingo->code1(g_lingo->c_negate); ;} + break; + + case 83: +#line 405 "engines/director/lingo/lingo-gr.y" + { (yyval.code) = (yyvsp[(2) - (3)].code); ;} + break; + + case 84: +#line 406 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_intersects); ;} + break; + + case 85: +#line 407 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_within); ;} + break; + + case 86: +#line 410 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_printtop); ;} + break; + + case 89: +#line 413 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_exitRepeat); ;} + break; + + case 90: +#line 414 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeConst(0); // Push fake value on stack + g_lingo->code1(g_lingo->c_procret); ;} + break; + + case 93: +#line 418 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->_handlers[*(yyvsp[(1) - (2)].s)]->u.func); + delete (yyvsp[(1) - (2)].s); ;} + break; + + case 94: +#line 421 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->_handlers[*(yyvsp[(1) - (2)].s)]->u.func); + delete (yyvsp[(1) - (2)].s); ;} + break; + + case 95: +#line 424 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code2(g_lingo->c_voidpush, g_lingo->_handlers[*(yyvsp[(1) - (1)].s)]->u.func); + delete (yyvsp[(1) - (1)].s); ;} + break; + + case 96: +#line 427 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeFunc((yyvsp[(1) - (2)].s), (yyvsp[(2) - (2)].narg)); ;} + break; + + case 97: +#line 428 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_open); ;} + break; + + case 98: +#line 429 "engines/director/lingo/lingo-gr.y" + { g_lingo->code2(g_lingo->c_voidpush, g_lingo->c_open); ;} + break; + + case 99: +#line 432 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;} + break; + + case 100: +#line 433 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;} + break; + + case 101: +#line 436 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;} + break; + + case 102: +#line 437 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;} + break; + + case 103: +#line 448 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_gotoloop); ;} + break; + + case 104: +#line 449 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_gotonext); ;} + break; + + case 105: +#line 450 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_gotoprevious); ;} + break; + + case 106: +#line 451 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(1); + g_lingo->code1(g_lingo->c_goto); ;} + break; + + case 107: +#line 454 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(3); + g_lingo->code1(g_lingo->c_goto); ;} + break; + + case 108: +#line 457 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(2); + g_lingo->code1(g_lingo->c_goto); ;} + break; + + case 113: +#line 470 "engines/director/lingo/lingo-gr.y" + { g_lingo->code1(g_lingo->c_playdone); ;} + break; + + case 114: +#line 471 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(1); + g_lingo->code1(g_lingo->c_play); ;} + break; + + case 115: +#line 474 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(3); + g_lingo->code1(g_lingo->c_play); ;} + break; + + case 116: +#line 477 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(2); + g_lingo->code1(g_lingo->c_play); ;} + break; + + case 117: +#line 507 "engines/director/lingo/lingo-gr.y" + { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); ;} + break; + + case 118: +#line 508 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeConst(0); // Push fake value on stack + g_lingo->code1(g_lingo->c_procret); + g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg)); + g_lingo->_indef = false; ;} + break; + + case 119: +#line 513 "engines/director/lingo/lingo-gr.y" + { + g_lingo->codeFactory(*(yyvsp[(2) - (2)].s)); + ;} + break; + + case 120: +#line 516 "engines/director/lingo/lingo-gr.y" + { g_lingo->_indef = true; ;} + break; + + case 121: +#line 517 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_procret); + g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg) + 1, &g_lingo->_currentFactory); + g_lingo->_indef = false; ;} + break; + + case 122: +#line 521 "engines/director/lingo/lingo-gr.y" + { (yyval.narg) = 0; ;} + break; + + case 123: +#line 522 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeArg((yyvsp[(1) - (1)].s)); (yyval.narg) = 1; ;} + break; + + case 124: +#line 523 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeArg((yyvsp[(3) - (3)].s)); (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} + break; + + case 125: +#line 524 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeArg((yyvsp[(4) - (4)].s)); (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;} + break; + + case 126: +#line 526 "engines/director/lingo/lingo-gr.y" + { g_lingo->codeArgStore(); ;} + break; + + case 127: +#line 530 "engines/director/lingo/lingo-gr.y" + { + g_lingo->code1(g_lingo->c_call); + g_lingo->codeString((yyvsp[(1) - (3)].s)->c_str()); + inst numpar = 0; + WRITE_UINT32(&numpar, (yyvsp[(3) - (3)].narg)); + g_lingo->code1(numpar); ;} + break; + + case 128: +#line 538 "engines/director/lingo/lingo-gr.y" + { (yyval.narg) = 0; ;} + break; + + case 129: +#line 539 "engines/director/lingo/lingo-gr.y" + { (yyval.narg) = 1; ;} + break; + + case 130: +#line 540 "engines/director/lingo/lingo-gr.y" + { (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;} + break; + + +/* Line 1267 of yacc.c. */ +#line 2593 "engines/director/lingo/lingo-gr.cpp" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 543 "engines/director/lingo/lingo-gr.y" + + diff --git a/engines/director/lingo/lingo-gr.h b/engines/director/lingo/lingo-gr.h new file mode 100644 index 0000000000..46097085fe --- /dev/null +++ b/engines/director/lingo/lingo-gr.h @@ -0,0 +1,208 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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, 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. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + UNARY = 258, + CASTREF = 259, + VOID = 260, + VAR = 261, + POINT = 262, + RECT = 263, + ARRAY = 264, + SYMBOL = 265, + OBJECT = 266, + INT = 267, + THEENTITY = 268, + THEENTITYWITHID = 269, + FLOAT = 270, + BLTIN = 271, + BLTINNOARGS = 272, + BLTINNOARGSORONE = 273, + BLTINONEARG = 274, + BLTINARGLIST = 275, + ID = 276, + STRING = 277, + HANDLER = 278, + tDOWN = 279, + tELSE = 280, + tNLELSIF = 281, + tEND = 282, + tEXIT = 283, + tFRAME = 284, + tGLOBAL = 285, + tGO = 286, + tIF = 287, + tINTO = 288, + tLOOP = 289, + tMACRO = 290, + tMOVIE = 291, + tNEXT = 292, + tOF = 293, + tPREVIOUS = 294, + tPUT = 295, + tREPEAT = 296, + tSET = 297, + tTHEN = 298, + tTO = 299, + tWHEN = 300, + tWITH = 301, + tWHILE = 302, + tNLELSE = 303, + tFACTORY = 304, + tMETHOD = 305, + tOPEN = 306, + tPLAY = 307, + tDONE = 308, + tPLAYACCEL = 309, + tINSTANCE = 310, + tGE = 311, + tLE = 312, + tGT = 313, + tLT = 314, + tEQ = 315, + tNEQ = 316, + tAND = 317, + tOR = 318, + tNOT = 319, + tMOD = 320, + tCONCAT = 321, + tCONTAINS = 322, + tSTARTS = 323, + tSPRITE = 324, + tINTERSECTS = 325, + tWITHIN = 326 + }; +#endif +/* Tokens. */ +#define UNARY 258 +#define CASTREF 259 +#define VOID 260 +#define VAR 261 +#define POINT 262 +#define RECT 263 +#define ARRAY 264 +#define SYMBOL 265 +#define OBJECT 266 +#define INT 267 +#define THEENTITY 268 +#define THEENTITYWITHID 269 +#define FLOAT 270 +#define BLTIN 271 +#define BLTINNOARGS 272 +#define BLTINNOARGSORONE 273 +#define BLTINONEARG 274 +#define BLTINARGLIST 275 +#define ID 276 +#define STRING 277 +#define HANDLER 278 +#define tDOWN 279 +#define tELSE 280 +#define tNLELSIF 281 +#define tEND 282 +#define tEXIT 283 +#define tFRAME 284 +#define tGLOBAL 285 +#define tGO 286 +#define tIF 287 +#define tINTO 288 +#define tLOOP 289 +#define tMACRO 290 +#define tMOVIE 291 +#define tNEXT 292 +#define tOF 293 +#define tPREVIOUS 294 +#define tPUT 295 +#define tREPEAT 296 +#define tSET 297 +#define tTHEN 298 +#define tTO 299 +#define tWHEN 300 +#define tWITH 301 +#define tWHILE 302 +#define tNLELSE 303 +#define tFACTORY 304 +#define tMETHOD 305 +#define tOPEN 306 +#define tPLAY 307 +#define tDONE 308 +#define tPLAYACCEL 309 +#define tINSTANCE 310 +#define tGE 311 +#define tLE 312 +#define tGT 313 +#define tLT 314 +#define tEQ 315 +#define tNEQ 316 +#define tAND 317 +#define tOR 318 +#define tNOT 319 +#define tMOD 320 +#define tCONCAT 321 +#define tCONTAINS 322 +#define tSTARTS 323 +#define tSPRITE 324 +#define tINTERSECTS 325 +#define tWITHIN 326 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 69 "engines/director/lingo/lingo-gr.y" +{ + Common::String *s; + int i; + double f; + int e[2]; // Entity + field + int code; + int narg; /* number of arguments */ + Common::Array<double> *arr; +} +/* Line 1529 of yacc.c. */ +#line 201 "engines/director/lingo/lingo-gr.hpp" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +extern YYSTYPE yylval; + diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y new file mode 100644 index 0000000000..a4bc6195d9 --- /dev/null +++ b/engines/director/lingo/lingo-gr.y @@ -0,0 +1,543 @@ +/* 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. + * + */ + +// Heavily inspired by hoc +// Copyright (C) AT&T 1995 +// All Rights Reserved +// +// Permission to use, copy, modify, and distribute this software and +// its documentation for any purpose and without fee is hereby +// granted, provided that the above copyright notice appear in all +// copies and that both that the copyright notice and this +// permission notice and warranty disclaimer appear in supporting +// documentation, and that the name of AT&T or any of its entities +// not be used in advertising or publicity pertaining to +// distribution of the software without specific, written prior +// permission. +// +// AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +// IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +// THIS SOFTWARE. + + +%debug + +%{ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/hash-str.h" + +#include "director/lingo/lingo.h" +#include "director/lingo/lingo-gr.h" + +extern int yylex(); +extern int yyparse(); + +using namespace Director; +void yyerror(char *s) { + g_lingo->_hadError = true; + warning("%s at line %d col %d", s, g_lingo->_linenumber, g_lingo->_colnumber); +} + + +%} + +%union { + Common::String *s; + int i; + double f; + int e[2]; // Entity + field + int code; + int narg; /* number of arguments */ + Common::Array<double> *arr; +} + +%token UNARY +%token CASTREF VOID VAR POINT RECT ARRAY SYMBOL OBJECT +%token<i> INT +%token<e> THEENTITY THEENTITYWITHID +%token<f> FLOAT +%token<s> BLTIN BLTINNOARGS BLTINNOARGSORONE BLTINONEARG BLTINARGLIST +%token<s> ID STRING HANDLER +%token tDOWN tELSE tNLELSIF tEND tEXIT tFRAME tGLOBAL tGO tIF tINTO tLOOP tMACRO +%token tMOVIE tNEXT tOF tPREVIOUS tPUT tREPEAT tSET tTHEN tTO tWHEN +%token tWITH tWHILE tNLELSE tFACTORY tMETHOD tOPEN tPLAY tDONE tPLAYACCEL tINSTANCE +%token tGE tLE tGT tLT tEQ tNEQ tAND tOR tNOT tMOD +%token tCONCAT tCONTAINS tSTARTS +%token tSPRITE tINTERSECTS tWITHIN + +%type<code> asgn begin elseif elsestmtoneliner end expr if when repeatwhile repeatwith stmtlist +%type<narg> argdef arglist + +%right '=' +%left tLT tLE tGT tGE tNEQ tCONTAINS tSTARTS +%left '&' +%left '+' '-' +%left '*' '/' '%' tAND tOR tMOD +%right UNARY + +%% + +program: program nl programline + | programline + | error nl { yyerrok; } + ; + +nl: '\n' { + g_lingo->_linenumber++; + g_lingo->_colnumber = 1; + } + +programline: /* empty */ + | defn + | func + | macro + | asgn { g_lingo->code1(g_lingo->c_xpop); } + | stmt + ; + +asgn: tPUT expr tINTO ID { + g_lingo->code1(g_lingo->c_varpush); + g_lingo->codeString($4->c_str()); + g_lingo->code1(g_lingo->c_assign); + $$ = $2; + delete $4; } + | tSET ID '=' expr { + g_lingo->code1(g_lingo->c_varpush); + g_lingo->codeString($2->c_str()); + g_lingo->code1(g_lingo->c_assign); + $$ = $4; + delete $2; } + | tSET THEENTITY '=' expr { + g_lingo->codeConst(0); // Put dummy id + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, $2[0]); + WRITE_UINT32(&f, $2[1]); + g_lingo->code2(e, f); + $$ = $4; } + | tSET THEENTITYWITHID expr '=' expr { + g_lingo->code1(g_lingo->c_swap); + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, $2[0]); + WRITE_UINT32(&f, $2[1]); + g_lingo->code2(e, f); + $$ = $5; } + | tSET ID tTO expr { + g_lingo->code1(g_lingo->c_varpush); + g_lingo->codeString($2->c_str()); + g_lingo->code1(g_lingo->c_assign); + $$ = $4; + delete $2; } + | tSET THEENTITY tTO expr { + g_lingo->codeConst(0); // Put dummy id + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, $2[0]); + WRITE_UINT32(&f, $2[1]); + g_lingo->code2(e, f); + $$ = $4; } + | tSET THEENTITYWITHID expr tTO expr { + g_lingo->code1(g_lingo->c_swap); + g_lingo->code1(g_lingo->c_theentityassign); + inst e = 0, f = 0; + WRITE_UINT32(&e, $2[0]); + WRITE_UINT32(&f, $2[1]); + g_lingo->code2(e, f); + $$ = $5; } + ; +stmtoneliner: expr { g_lingo->code1(g_lingo->c_xpop); } + | func + ; +stmt: stmtoneliner + | ifstmt + // repeat while (expression = TRUE) + // statements + // end repeat + // + | repeatwhile '(' cond ')' stmtlist end tEND tREPEAT { + inst body = 0, end = 0; + WRITE_UINT32(&body, $5); + WRITE_UINT32(&end, $6); + (*g_lingo->_currentScript)[$1 + 1] = body; /* body of loop */ + (*g_lingo->_currentScript)[$1 + 2] = end; } /* end, if cond fails */ + ; + // repeat with index = start to end + // statements + // end repeat + // + | repeatwith '=' expr end tTO expr end stmtlist end tEND tREPEAT { + inst init = 0, finish = 0, body = 0, end = 0, inc = 0; + WRITE_UINT32(&init, $3); + WRITE_UINT32(&finish, $6); + WRITE_UINT32(&body, $8); + WRITE_UINT32(&end, $9); + WRITE_UINT32(&inc, 1); + (*g_lingo->_currentScript)[$1 + 1] = init; /* initial count value */ + (*g_lingo->_currentScript)[$1 + 2] = finish;/* final count value */ + (*g_lingo->_currentScript)[$1 + 3] = body; /* body of loop */ + (*g_lingo->_currentScript)[$1 + 4] = inc; /* increment */ + (*g_lingo->_currentScript)[$1 + 5] = end; } /* end, if cond fails */ + // repeat with index = high down to low + // statements + // end repeat + // + | repeatwith '=' expr end tDOWN tTO expr end stmtlist end tEND tREPEAT { + inst init = 0, finish = 0, body = 0, end = 0, inc = 0; + WRITE_UINT32(&init, $3); + WRITE_UINT32(&finish, $7); + WRITE_UINT32(&body, $9); + WRITE_UINT32(&end, $10); + WRITE_UINT32(&inc, -1); + (*g_lingo->_currentScript)[$1 + 1] = init; /* initial count value */ + (*g_lingo->_currentScript)[$1 + 2] = finish;/* final count value */ + (*g_lingo->_currentScript)[$1 + 3] = body; /* body of loop */ + (*g_lingo->_currentScript)[$1 + 4] = inc; /* increment */ + (*g_lingo->_currentScript)[$1 + 5] = end; } /* end, if cond fails */ + | when expr end { + inst end = 0; + WRITE_UINT32(&end, $3); + g_lingo->code1(STOP); + (*g_lingo->_currentScript)[$1 + 1] = end; + } + ; + +ifstmt: if cond tTHEN nl stmtlist end tEND tIF { + inst then = 0, end = 0; + WRITE_UINT32(&then, $5); + WRITE_UINT32(&end, $6); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */ + g_lingo->processIf(0, 0); } + | if cond tTHEN nl stmtlist end tNLELSE stmtlist end tEND tIF { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, $5); + WRITE_UINT32(&else1, $8); + WRITE_UINT32(&end, $9); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */ + g_lingo->processIf(0, 0); } + | if cond tTHEN nl stmtlist end begin elseifstmt end tEND tIF { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, $5); + WRITE_UINT32(&else1, $7); + WRITE_UINT32(&end, $9); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */ + g_lingo->processIf(0, $9); } + | if cond tTHEN begin stmtoneliner end { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, $4); + WRITE_UINT32(&else1, 0); + WRITE_UINT32(&end, $6); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */ + + g_lingo->processIf(0, 0); } + | if cond tTHEN begin stmtoneliner end tNLELSE begin stmtoneliner end { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, $4); + WRITE_UINT32(&else1, $8); + WRITE_UINT32(&end, $10); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */ + + g_lingo->processIf(0, 0); } + | if cond tTHEN begin stmtoneliner end elseifstmtoneliner end elsestmtoneliner end { + inst then = 0, else1 = 0, end = 0; + WRITE_UINT32(&then, $4); + WRITE_UINT32(&else1, $6); + WRITE_UINT32(&end, $10); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + (*g_lingo->_currentScript)[$1 + 2] = else1; /* elsepart */ + (*g_lingo->_currentScript)[$1 + 3] = end; /* end, if cond fails */ + + g_lingo->processIf(0, $10); } + ; +elsestmtoneliner: /* nothing */ { $$ = 0; } + | tNLELSE begin stmtoneliner { $$ = $2; } + ; + +elseifstmt: elseifstmt elseifstmt1 + | elseifstmt1 + ; + +elseifstmtoneliner: elseifstmtoneliner elseifstmtoneliner1 + | elseifstmtoneliner1 + ; + +elseifstmtoneliner1: elseif cond tTHEN begin stmt end { + inst then = 0; + WRITE_UINT32(&then, $4); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + + g_lingo->codeLabel($1); } + ; + +elseifstmt1: elseifstmtoneliner + | elseif cond tTHEN stmtlist end { + inst then = 0; + WRITE_UINT32(&then, $4); + (*g_lingo->_currentScript)[$1 + 1] = then; /* thenpart */ + + g_lingo->codeLabel($1); } + ; + +cond: expr { g_lingo->code1(STOP); } + | expr '=' expr { g_lingo->code2(g_lingo->c_eq, STOP); } + | '(' cond ')' + ; +repeatwhile: tREPEAT tWHILE { $$ = g_lingo->code3(g_lingo->c_repeatwhilecode, STOP, STOP); } + ; +repeatwith: tREPEAT tWITH ID { + $$ = g_lingo->code3(g_lingo->c_repeatwithcode, STOP, STOP); + g_lingo->code3(STOP, STOP, STOP); + g_lingo->codeString($3->c_str()); + delete $3; } + ; +if: tIF { + $$ = g_lingo->code1(g_lingo->c_ifcode); + g_lingo->code3(STOP, STOP, STOP); + g_lingo->code1(0); // Do not skip end + g_lingo->codeLabel(0); } // Mark beginning of the if() statement + ; +elseif: tNLELSIF { + inst skipEnd; + WRITE_UINT32(&skipEnd, 1); // We have to skip end to avoid multiple executions + $$ = g_lingo->code1(g_lingo->c_ifcode); + g_lingo->code3(STOP, STOP, STOP); + g_lingo->code1(skipEnd); } + ; +begin: /* nothing */ { $$ = g_lingo->_currentScript->size(); } + ; +end: /* nothing */ { g_lingo->code1(STOP); $$ = g_lingo->_currentScript->size(); } + ; +stmtlist: /* nothing */ { $$ = g_lingo->_currentScript->size(); } + | stmtlist nl + | stmtlist stmt + ; + +when: tWHEN ID tTHEN { + $$ = g_lingo->code1(g_lingo->c_whencode); + g_lingo->code1(STOP); + g_lingo->codeString($2->c_str()); + delete $2; } + +expr: INT { $$ = g_lingo->codeConst($1); } + | FLOAT { + $$ = g_lingo->code1(g_lingo->c_fconstpush); + g_lingo->codeFloat($1); } + | STRING { + $$ = g_lingo->code1(g_lingo->c_stringpush); + g_lingo->codeString($1->c_str()); } + | BLTINNOARGS { + $$ = g_lingo->code1(g_lingo->_handlers[*$1]->u.func); + delete $1; } + | ID '(' arglist ')' { + $$ = g_lingo->codeFunc($1, $3); + delete $1; } + | ID { + $$ = g_lingo->code1(g_lingo->c_eval); + g_lingo->codeString($1->c_str()); + delete $1; } + | THEENTITY { + $$ = g_lingo->codeConst(0); // Put dummy id + g_lingo->code1(g_lingo->c_theentitypush); + inst e = 0, f = 0; + WRITE_UINT32(&e, $1[0]); + WRITE_UINT32(&f, $1[1]); + g_lingo->code2(e, f); } + | THEENTITYWITHID expr { + $$ = g_lingo->code1(g_lingo->c_theentitypush); + inst e = 0, f = 0; + WRITE_UINT32(&e, $1[0]); + WRITE_UINT32(&f, $1[1]); + g_lingo->code2(e, f); } + | asgn + | expr '+' expr { g_lingo->code1(g_lingo->c_add); } + | expr '-' expr { g_lingo->code1(g_lingo->c_sub); } + | expr '*' expr { g_lingo->code1(g_lingo->c_mul); } + | expr '/' expr { g_lingo->code1(g_lingo->c_div); } + | expr tMOD expr { g_lingo->code1(g_lingo->c_mod); } + | expr '>' expr { g_lingo->code1(g_lingo->c_gt); } + | expr '<' expr { g_lingo->code1(g_lingo->c_lt); } + | expr tNEQ expr { g_lingo->code1(g_lingo->c_neq); } + | expr tGE expr { g_lingo->code1(g_lingo->c_ge); } + | expr tLE expr { g_lingo->code1(g_lingo->c_le); } + | expr tAND expr { g_lingo->code1(g_lingo->c_and); } + | expr tOR expr { g_lingo->code1(g_lingo->c_or); } + | tNOT expr %prec UNARY { g_lingo->code1(g_lingo->c_not); } + | expr '&' expr { g_lingo->code1(g_lingo->c_ampersand); } + | expr tCONCAT expr { g_lingo->code1(g_lingo->c_concat); } + | expr tCONTAINS expr { g_lingo->code1(g_lingo->c_contains); } + | expr tSTARTS expr { g_lingo->code1(g_lingo->c_starts); } + | '+' expr %prec UNARY { $$ = $2; } + | '-' expr %prec UNARY { $$ = $2; g_lingo->code1(g_lingo->c_negate); } + | '(' expr ')' { $$ = $2; } + | tSPRITE expr tINTERSECTS expr { g_lingo->code1(g_lingo->c_intersects); } + | tSPRITE expr tWITHIN expr { g_lingo->code1(g_lingo->c_within); } + ; + +func: tPUT expr { g_lingo->code1(g_lingo->c_printtop); } + | gotofunc + | playfunc + | tEXIT tREPEAT { g_lingo->code1(g_lingo->c_exitRepeat); } + | tEXIT { g_lingo->codeConst(0); // Push fake value on stack + g_lingo->code1(g_lingo->c_procret); } + | tGLOBAL globallist + | tINSTANCE instancelist + | BLTINONEARG expr { + g_lingo->code1(g_lingo->_handlers[*$1]->u.func); + delete $1; } + | BLTINNOARGSORONE expr { + g_lingo->code1(g_lingo->_handlers[*$1]->u.func); + delete $1; } + | BLTINNOARGSORONE { + g_lingo->code2(g_lingo->c_voidpush, g_lingo->_handlers[*$1]->u.func); + delete $1; } + | BLTINARGLIST arglist { g_lingo->codeFunc($1, $2); } + | tOPEN expr tWITH expr { g_lingo->code1(g_lingo->c_open); } + | tOPEN expr { g_lingo->code2(g_lingo->c_voidpush, g_lingo->c_open); } + ; + +globallist: ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($1->c_str()); delete $1; } + | globallist ',' ID { g_lingo->code1(g_lingo->c_global); g_lingo->codeString($3->c_str()); delete $3; } + ; + +instancelist: ID { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString($1->c_str()); delete $1; } + | instancelist ',' ID { g_lingo->code1(g_lingo->c_instance); g_lingo->codeString($3->c_str()); delete $3; } + ; + +// go {to} {frame} whichFrame {of movie whichMovie} +// go {to} {frame "Open23" of} movie whichMovie +// go loop +// go next +// go previous +// go to {frame} whichFrame {of movie whichMovie} +// go to {frame whichFrame of} movie whichMovie + +gotofunc: tGO tLOOP { g_lingo->code1(g_lingo->c_gotoloop); } + | tGO tNEXT { g_lingo->code1(g_lingo->c_gotonext); } + | tGO tPREVIOUS { g_lingo->code1(g_lingo->c_gotoprevious); } + | tGO gotoframe { + g_lingo->codeConst(1); + g_lingo->code1(g_lingo->c_goto); } + | tGO gotoframe gotomovie { + g_lingo->codeConst(3); + g_lingo->code1(g_lingo->c_goto); } + | tGO gotomovie { + g_lingo->codeConst(2); + g_lingo->code1(g_lingo->c_goto); } + ; + +gotoframe: tFRAME expr + | expr + ; + +gotomovie: tOF tMOVIE expr + | tMOVIE expr + ; + +playfunc: tPLAY tDONE { g_lingo->code1(g_lingo->c_playdone); } + | tPLAY gotoframe { + g_lingo->codeConst(1); + g_lingo->code1(g_lingo->c_play); } + | tPLAY gotoframe gotomovie { + g_lingo->codeConst(3); + g_lingo->code1(g_lingo->c_play); } + | tPLAY gotomovie { + g_lingo->codeConst(2); + g_lingo->code1(g_lingo->c_play); } + ; + +// macro +// +// Special Note The macro keyword is retained in Director 3.0 to maintain compatibility +// with scripts developed under Version 2.0. When writing new scripts, or editing old +// scripts, you should use handlers instead of macros. (Handlers are defined with the on keyword.) +// +// Syntax: +// +// -- [comment] +// macro macroName [argument1] [, argument2] +// [, argument3] +// [statement1] +// [statement2] +// +// Keyword. Defines a macro. A macro is a multiple-line script defined +// in the Text window. Macros can accept arguments (inputs) and +// optionally return a result. Macros can call other macros and can be +// called from any other script or factory. +// +// The first line of a castmember in the Text window that contains a macro must be +// a comment (--). You can define more than one macro in a given text castmember. +// The macro definition ends where the next macro (or factory) begins. +// +// See also: +// on keyword +defn: tMACRO ID { g_lingo->_indef = true; g_lingo->_currentFactory.clear(); } + begin argdef nl argstore stmtlist { + g_lingo->codeConst(0); // Push fake value on stack + g_lingo->code1(g_lingo->c_procret); + g_lingo->define(*$2, $4, $5); + g_lingo->_indef = false; } + | tFACTORY ID { + g_lingo->codeFactory(*$2); + } + | tMETHOD ID { g_lingo->_indef = true; } + begin argdef nl argstore stmtlist { + g_lingo->code1(g_lingo->c_procret); + g_lingo->define(*$2, $4, $5 + 1, &g_lingo->_currentFactory); + g_lingo->_indef = false; } ; +argdef: /* nothing */ { $$ = 0; } + | ID { g_lingo->codeArg($1); $$ = 1; } + | argdef ',' ID { g_lingo->codeArg($3); $$ = $1 + 1; } + | argdef nl ',' ID { g_lingo->codeArg($4); $$ = $1 + 1; } + ; +argstore: /* nothing */ { g_lingo->codeArgStore(); } + ; + + +macro: ID begin arglist { + g_lingo->code1(g_lingo->c_call); + g_lingo->codeString($1->c_str()); + inst numpar = 0; + WRITE_UINT32(&numpar, $3); + g_lingo->code1(numpar); } + ; + +arglist: /* nothing */ { $$ = 0; } + | expr { $$ = 1; } + | arglist ',' expr { $$ = $1 + 1; } + ; + +%% diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp new file mode 100644 index 0000000000..ebdb169a65 --- /dev/null +++ b/engines/director/lingo/lingo-lex.cpp @@ -0,0 +1,2390 @@ +#line 2 "engines/director/lingo/lingo-lex.cpp" + +#line 4 "engines/director/lingo/lingo-lex.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 59 +#define YY_END_OF_BUFFER 60 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[206] = + { 0, + 0, 0, 60, 58, 3, 56, 56, 58, 58, 55, + 55, 55, 54, 55, 55, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 2, 2, 3, 56, 0, 0, 0, 0, + 0, 57, 51, 1, 53, 54, 50, 48, 49, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 18, + 8, 52, 52, 52, 52, 52, 52, 52, 29, 52, + 31, 52, 52, 52, 52, 52, 52, 52, 52, 42, + 52, 52, 2, 2, 0, 1, 53, 4, 52, 52, + 52, 52, 12, 52, 52, 52, 52, 0, 52, 52, + + 52, 52, 52, 25, 52, 52, 28, 52, 52, 52, + 34, 52, 36, 52, 52, 52, 52, 52, 52, 0, + 52, 6, 7, 11, 14, 52, 52, 52, 0, 52, + 52, 21, 22, 52, 52, 52, 27, 30, 32, 52, + 52, 52, 52, 0, 41, 46, 52, 44, 10, 52, + 52, 15, 52, 17, 52, 52, 23, 52, 26, 52, + 52, 52, 52, 40, 40, 47, 52, 0, 52, 52, + 16, 52, 52, 24, 52, 35, 43, 37, 0, 40, + 45, 0, 52, 13, 52, 52, 52, 0, 40, 9, + 5, 19, 52, 33, 0, 40, 52, 0, 0, 20, + + 39, 0, 0, 38, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 1, 6, 1, 1, 7, 8, 1, 7, + 7, 7, 7, 7, 9, 10, 7, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 7, 1, 12, + 13, 14, 1, 1, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 24, + 1, 1, 1, 7, 39, 1, 40, 41, 42, 43, + + 44, 45, 46, 47, 48, 24, 24, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 24, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[63] = + { 0, + 1, 2, 3, 3, 2, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5 + } ; + +static yyconst flex_int16_t yy_base[211] = + { 0, + 0, 61, 156, 521, 65, 69, 73, 77, 148, 521, + 104, 99, 54, 70, 91, 58, 0, 58, 59, 69, + 74, 70, 70, 71, 88, 105, 105, 110, 82, 118, + 117, 130, 177, 181, 185, 521, 189, 193, 197, 106, + 94, 521, 521, 0, 82, 132, 521, 521, 521, 0, + 84, 119, 169, 116, 120, 174, 186, 191, 180, 171, + 0, 177, 183, 196, 182, 201, 181, 188, 0, 204, + 0, 209, 206, 194, 201, 207, 212, 231, 228, 0, + 233, 222, 271, 280, 230, 0, 80, 0, 230, 234, + 238, 247, 0, 235, 236, 244, 264, 293, 255, 271, + + 267, 266, 278, 0, 279, 271, 0, 279, 269, 273, + 0, 290, 0, 287, 282, 309, 289, 292, 296, 300, + 307, 0, 0, 0, 0, 296, 310, 318, 310, 324, + 311, 0, 0, 317, 318, 330, 0, 0, 0, 328, + 337, 322, 323, 363, 0, 0, 334, 334, 202, 336, + 330, 0, 338, 521, 340, 340, 0, 355, 0, 347, + 348, 364, 354, 212, 387, 0, 361, 388, 367, 359, + 0, 383, 382, 0, 369, 0, 0, 0, 402, 404, + 0, 393, 383, 0, 401, 405, 384, 403, 427, 521, + 0, 0, 395, 0, 256, 429, 401, 441, 448, 0, + + 453, 404, 459, 460, 521, 500, 502, 507, 511, 515 + } ; + +static yyconst flex_int16_t yy_def[211] = + { 0, + 205, 1, 205, 205, 205, 205, 205, 205, 206, 205, + 205, 205, 205, 205, 205, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 205, 205, 205, 205, 205, 205, 205, 205, + 206, 205, 205, 208, 205, 205, 205, 205, 205, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 205, 205, 205, 208, 205, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 205, 207, 207, + + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 205, + 207, 207, 207, 207, 207, 207, 207, 207, 205, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 209, 207, 207, 207, 207, 205, 207, + 207, 207, 207, 205, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 209, 209, 207, 207, 205, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 205, 209, + 207, 205, 207, 207, 207, 207, 207, 205, 209, 205, + 207, 207, 207, 207, 205, 209, 207, 210, 205, 207, + + 210, 205, 205, 210, 0, 205, 205, 205, 205, 205 + } ; + +static yyconst flex_int16_t yy_nxt[584] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 4, + 13, 14, 10, 15, 16, 17, 18, 19, 20, 21, + 22, 17, 23, 17, 24, 25, 26, 27, 28, 17, + 29, 30, 31, 17, 17, 32, 17, 17, 17, 16, + 17, 18, 19, 20, 21, 22, 17, 23, 24, 25, + 26, 27, 28, 17, 29, 30, 31, 17, 17, 32, + 17, 17, 33, 45, 46, 34, 35, 36, 36, 37, + 38, 39, 39, 38, 38, 39, 39, 38, 37, 36, + 36, 37, 47, 48, 51, 52, 53, 40, 57, 61, + 87, 40, 87, 54, 59, 55, 62, 60, 63, 42, + + 75, 88, 64, 49, 58, 56, 65, 44, 51, 52, + 53, 43, 40, 57, 61, 66, 40, 54, 59, 55, + 62, 60, 63, 67, 69, 75, 88, 64, 58, 56, + 85, 65, 68, 70, 72, 71, 76, 93, 79, 66, + 73, 45, 46, 74, 80, 89, 77, 92, 67, 69, + 78, 81, 82, 42, 85, 205, 68, 70, 72, 71, + 205, 76, 93, 79, 73, 205, 205, 74, 80, 89, + 77, 92, 98, 205, 78, 98, 81, 82, 83, 36, + 36, 84, 84, 36, 36, 84, 35, 36, 36, 37, + 37, 36, 36, 37, 38, 90, 94, 38, 38, 39, + + 39, 38, 95, 168, 91, 96, 168, 97, 99, 100, + 101, 40, 102, 179, 103, 40, 179, 106, 104, 90, + 107, 94, 108, 109, 110, 205, 111, 95, 91, 112, + 96, 97, 99, 100, 101, 105, 40, 102, 103, 113, + 40, 106, 114, 104, 107, 115, 116, 108, 109, 110, + 111, 117, 122, 112, 119, 118, 205, 198, 205, 105, + 198, 120, 121, 113, 123, 124, 114, 125, 126, 127, + 115, 116, 83, 36, 36, 84, 117, 122, 119, 128, + 118, 84, 36, 36, 84, 120, 121, 130, 123, 131, + 124, 125, 126, 127, 98, 133, 134, 98, 132, 135, + + 205, 136, 205, 137, 128, 138, 139, 140, 141, 142, + 144, 130, 143, 144, 131, 146, 147, 148, 149, 133, + 134, 150, 132, 151, 135, 129, 136, 137, 152, 138, + 139, 140, 153, 141, 142, 145, 143, 154, 155, 146, + 147, 156, 148, 149, 157, 158, 150, 151, 159, 129, + 160, 161, 166, 152, 162, 163, 167, 153, 169, 145, + 170, 154, 171, 155, 144, 156, 172, 144, 157, 158, + 205, 173, 174, 159, 175, 160, 161, 166, 162, 163, + 176, 167, 177, 169, 170, 178, 171, 181, 179, 168, + 172, 179, 168, 183, 165, 173, 184, 174, 175, 185, + + 186, 205, 187, 179, 176, 179, 179, 177, 179, 178, + 182, 181, 190, 205, 191, 194, 180, 183, 165, 192, + 184, 193, 195, 203, 185, 186, 187, 197, 179, 188, + 199, 179, 200, 199, 189, 182, 205, 190, 191, 194, + 180, 205, 198, 205, 192, 198, 193, 195, 203, 199, + 205, 197, 199, 188, 205, 205, 200, 205, 189, 196, + 204, 204, 205, 204, 204, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 202, 205, 205, 205, 205, + 205, 205, 205, 196, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 202, + + 41, 41, 205, 41, 41, 50, 50, 86, 86, 205, + 86, 86, 164, 205, 205, 164, 201, 205, 205, 201, + 3, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205 + } ; + +static yyconst flex_int16_t yy_chk[584] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 13, 13, 2, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 14, 14, 16, 18, 19, 6, 21, 23, + 87, 7, 45, 20, 22, 20, 23, 22, 24, 41, + + 29, 51, 25, 15, 21, 20, 25, 12, 16, 18, + 19, 11, 6, 21, 23, 25, 7, 20, 22, 20, + 23, 22, 24, 26, 27, 29, 51, 25, 21, 20, + 40, 25, 26, 27, 28, 27, 30, 55, 31, 25, + 28, 46, 46, 28, 31, 52, 30, 54, 26, 27, + 30, 32, 32, 9, 40, 3, 26, 27, 28, 27, + 0, 30, 55, 31, 28, 0, 0, 28, 31, 52, + 30, 54, 60, 0, 30, 60, 32, 32, 33, 33, + 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, + 37, 37, 37, 37, 38, 53, 56, 38, 39, 39, + + 39, 39, 57, 149, 53, 58, 149, 59, 62, 62, + 63, 38, 64, 164, 65, 39, 164, 67, 66, 53, + 68, 56, 70, 72, 73, 0, 74, 57, 53, 75, + 58, 59, 62, 62, 63, 66, 38, 64, 65, 76, + 39, 67, 77, 66, 68, 78, 79, 70, 72, 73, + 74, 81, 90, 75, 82, 81, 0, 195, 0, 66, + 195, 85, 89, 76, 91, 92, 77, 94, 95, 96, + 78, 79, 83, 83, 83, 83, 81, 90, 82, 97, + 81, 84, 84, 84, 84, 85, 89, 99, 91, 100, + 92, 94, 95, 96, 98, 101, 102, 98, 100, 103, + + 0, 105, 0, 106, 97, 108, 109, 110, 112, 114, + 116, 99, 115, 116, 100, 117, 118, 119, 120, 101, + 102, 121, 100, 126, 103, 98, 105, 106, 127, 108, + 109, 110, 128, 112, 114, 116, 115, 129, 130, 117, + 118, 131, 119, 120, 134, 135, 121, 126, 136, 98, + 140, 141, 147, 127, 142, 143, 148, 128, 150, 116, + 151, 129, 153, 130, 144, 131, 155, 144, 134, 135, + 0, 156, 158, 136, 160, 140, 141, 147, 142, 143, + 161, 148, 162, 150, 151, 163, 153, 167, 165, 168, + 155, 165, 168, 169, 144, 156, 170, 158, 160, 172, + + 173, 0, 175, 179, 161, 180, 179, 162, 180, 163, + 168, 167, 182, 0, 183, 187, 165, 169, 144, 185, + 170, 186, 188, 202, 172, 173, 175, 193, 189, 179, + 196, 189, 197, 196, 180, 168, 0, 182, 183, 187, + 165, 0, 198, 0, 185, 198, 186, 188, 202, 199, + 0, 193, 199, 179, 201, 0, 197, 201, 180, 189, + 203, 204, 0, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 199, 0, 0, 0, 0, + 0, 0, 0, 189, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 199, + + 206, 206, 0, 206, 206, 207, 207, 208, 208, 0, + 208, 208, 209, 0, 0, 209, 210, 0, 0, 210, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "engines/director/lingo/lingo-lex.l" +/* 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. + * + */ +#line 25 "engines/director/lingo/lingo-lex.l" + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/str.h" + +#include "director/lingo/lingo.h" +#include "director/lingo/lingo-gr.h" + +using namespace Director; + +int yyparse(); +static void count() { + g_lingo->_colnumber += strlen(yytext); +} + +#if defined(__PLAYSTATION2__) || defined(_MSC_VER) +// Stub for missing function +int isatty(int fileno) { return 0; } +#endif + +#ifdef _MSC_VER +#define YY_NO_UNISTD_H +#endif + +static void countnl() { + char *p = yytext; + + while(*p == '\n' || *p == '\r') + p++; + + g_lingo->_linenumber++; + g_lingo->_colnumber = strlen(p); +} + +#line 708 "engines/director/lingo/lingo-lex.cpp" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +yy_size_t yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + yy_size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 69 "engines/director/lingo/lingo-lex.l" + + +#line 896 "engines/director/lingo/lingo-lex.cpp" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 206 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 521 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 71 "engines/director/lingo/lingo-lex.l" + + YY_BREAK +case 2: +YY_RULE_SETUP +#line 72 "engines/director/lingo/lingo-lex.l" +{ count(); } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 73 "engines/director/lingo/lingo-lex.l" +{ count(); return ' '; } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 75 "engines/director/lingo/lingo-lex.l" +{ count(); return tAND; } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 76 "engines/director/lingo/lingo-lex.l" +{ count(); return tCONTAINS; } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 77 "engines/director/lingo/lingo-lex.l" +{ count(); return tDONE; } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 78 "engines/director/lingo/lingo-lex.l" +{ count(); return tDOWN; } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 79 "engines/director/lingo/lingo-lex.l" +{ count(); return tIF; } + YY_BREAK +case 9: +/* rule 9 can match eol */ +YY_RULE_SETUP +#line 80 "engines/director/lingo/lingo-lex.l" +{ countnl(); return tNLELSIF; } + YY_BREAK +case 10: +/* rule 10 can match eol */ +YY_RULE_SETUP +#line 81 "engines/director/lingo/lingo-lex.l" +{ countnl(); return tNLELSE; } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 82 "engines/director/lingo/lingo-lex.l" +{ count(); return tELSE; } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 83 "engines/director/lingo/lingo-lex.l" +{ count(); return tEND; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 84 "engines/director/lingo/lingo-lex.l" +{ count(); return tFACTORY; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 85 "engines/director/lingo/lingo-lex.l" +{ count(); return tEXIT; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 86 "engines/director/lingo/lingo-lex.l" +{ count(); return tFRAME; } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 87 "engines/director/lingo/lingo-lex.l" +{ count(); return tGLOBAL; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 88 "engines/director/lingo/lingo-lex.l" +{ count(); return tGO; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 89 "engines/director/lingo/lingo-lex.l" +{ count(); return tGO; } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 90 "engines/director/lingo/lingo-lex.l" +{ count(); return tINSTANCE; } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 91 "engines/director/lingo/lingo-lex.l" +{ count(); return tINTERSECTS; } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 92 "engines/director/lingo/lingo-lex.l" +{ count(); return tINTO; } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 93 "engines/director/lingo/lingo-lex.l" +{ count(); return tLOOP; } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 94 "engines/director/lingo/lingo-lex.l" +{ count(); return tMACRO; } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 95 "engines/director/lingo/lingo-lex.l" +{ count(); return tMETHOD; } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 96 "engines/director/lingo/lingo-lex.l" +{ count(); return tMOD; } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 97 "engines/director/lingo/lingo-lex.l" +{ count(); return tMOVIE; } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 98 "engines/director/lingo/lingo-lex.l" +{ count(); return tNEXT; } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 99 "engines/director/lingo/lingo-lex.l" +{ count(); return tNOT; } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 100 "engines/director/lingo/lingo-lex.l" +{ count(); return tOF; } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 101 "engines/director/lingo/lingo-lex.l" +{ count(); return tOPEN; } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 102 "engines/director/lingo/lingo-lex.l" +{ count(); return tOR; } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 103 "engines/director/lingo/lingo-lex.l" +{ count(); return tPLAY; } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 104 "engines/director/lingo/lingo-lex.l" +{ count(); return tPREVIOUS; } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 105 "engines/director/lingo/lingo-lex.l" +{ count(); return tPUT; } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 106 "engines/director/lingo/lingo-lex.l" +{ count(); return tREPEAT; } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 107 "engines/director/lingo/lingo-lex.l" +{ count(); return tSET; } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 108 "engines/director/lingo/lingo-lex.l" +{ count(); return tSTARTS; } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 109 "engines/director/lingo/lingo-lex.l" +{ + count(); + + yylval.e[0] = g_lingo->_theEntities["sqrt"]->entity; + yylval.e[1] = 0; // No field + + return THEENTITYWITHID; + } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 117 "engines/director/lingo/lingo-lex.l" +{ + count(); + + const char *ptr = &yytext[4]; // Skip 'the ' + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + Common::String field; + while (*ptr != ' ' && *ptr != '\t') + field += *ptr++; + + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + ptr += 3; // Skip 'of ' + + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + if (g_lingo->_theEntities.contains(ptr)) { + field = Common::String::format("%d%s", g_lingo->_theEntities[ptr]->entity, field.c_str()); + + if (!g_lingo->_theEntityFields.contains(field)) { + error("Unhandled the field %s", ptr); + } + + if (g_lingo->_theEntityFields[field]->entity != g_lingo->_theEntities[ptr]->entity) + error("Unsupported field '%s' for entity '%s'", field.c_str(), ptr); + + yylval.e[0] = g_lingo->_theEntities[ptr]->entity; + yylval.e[1] = g_lingo->_theEntityFields[field]->field; + + if (g_lingo->_theEntities[ptr]->hasId) + return THEENTITYWITHID; + else + return THEENTITY; + } + + warning("Unhandled the entity %s", ptr); + } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 157 "engines/director/lingo/lingo-lex.l" +{ + count(); + + const char *ptr = &yytext[4]; // Skip 'the ' + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + if (g_lingo->_theEntities.contains(ptr)) { + yylval.e[0] = g_lingo->_theEntities[ptr]->entity; + yylval.e[1] = 0; // No field + + if (g_lingo->_theEntities[ptr]->hasId) + return THEENTITYWITHID; + else + return THEENTITY; + } + + warning("Unhandled the entity %s", ptr); + } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 176 "engines/director/lingo/lingo-lex.l" +{ count(); return tTHEN; } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 177 "engines/director/lingo/lingo-lex.l" +{ count(); return tTO; } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 178 "engines/director/lingo/lingo-lex.l" +{ count(); return tSPRITE; } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 179 "engines/director/lingo/lingo-lex.l" +{ count(); return tWITH; } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 180 "engines/director/lingo/lingo-lex.l" +{ count(); return tWITHIN; } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 181 "engines/director/lingo/lingo-lex.l" +{ count(); return tWHEN; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 182 "engines/director/lingo/lingo-lex.l" +{ count(); return tWHILE; } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 184 "engines/director/lingo/lingo-lex.l" +{ count(); return tNEQ; } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 185 "engines/director/lingo/lingo-lex.l" +{ count(); return tGE; } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 186 "engines/director/lingo/lingo-lex.l" +{ count(); return tLE; } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 187 "engines/director/lingo/lingo-lex.l" +{ count(); return tCONCAT; } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 189 "engines/director/lingo/lingo-lex.l" +{ + count(); + yylval.s = new Common::String(yytext); + + if (g_lingo->_handlers.contains(yytext)) { + if (g_lingo->_handlers[yytext]->type == BLTIN && g_lingo->_handlers[yytext]->parens == false) { + if (g_lingo->_handlers[yytext]->nargs == 0) { + if (g_lingo->_handlers[yytext]->maxArgs == 0) + return BLTINNOARGS; + else if (g_lingo->_handlers[yytext]->maxArgs == 1) + return BLTINNOARGSORONE; + else + error("Incorrect setup for builtin: %s", yytext); + } else if (g_lingo->_handlers[yytext]->nargs == 1 && + g_lingo->_handlers[yytext]->maxArgs == 1) { + return BLTINONEARG; + } else if (g_lingo->_handlers[yytext]->nargs == -1) { + return BLTINARGLIST; + } else { + error("Incorrect setup for builtin: %s", yytext); + } + } + } + + return ID; + } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 215 "engines/director/lingo/lingo-lex.l" +{ count(); yylval.f = atof(yytext); return FLOAT; } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 216 "engines/director/lingo/lingo-lex.l" +{ count(); yylval.i = strtol(yytext, NULL, 10); return INT; } + YY_BREAK +case 55: +YY_RULE_SETUP +#line 217 "engines/director/lingo/lingo-lex.l" +{ count(); return *yytext; } + YY_BREAK +case 56: +/* rule 56 can match eol */ +YY_RULE_SETUP +#line 218 "engines/director/lingo/lingo-lex.l" +{ return '\n'; } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 219 "engines/director/lingo/lingo-lex.l" +{ count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; } + YY_BREAK +case 58: +YY_RULE_SETUP +#line 220 "engines/director/lingo/lingo-lex.l" + + YY_BREAK +case 59: +YY_RULE_SETUP +#line 222 "engines/director/lingo/lingo-lex.l" +ECHO; + YY_BREAK +#line 1367 "engines/director/lingo/lingo-lex.cpp" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 206 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 206 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 205); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register yy_size_t number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return 0; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n, i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +yy_size_t yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 222 "engines/director/lingo/lingo-lex.l" + + + +extern int yydebug; + +namespace Director { + +int Lingo::parse(const char *code) { + YY_BUFFER_STATE bp; + + yydebug = 0; + + yy_delete_buffer(YY_CURRENT_BUFFER); + + bp = yy_scan_string(code); + yy_switch_to_buffer(bp); + yyparse(); + yy_delete_buffer(bp); + + return 0; +} + +} + diff --git a/engines/director/lingo/lingo-lex.l b/engines/director/lingo/lingo-lex.l new file mode 100644 index 0000000000..c2a5b19fb9 --- /dev/null +++ b/engines/director/lingo/lingo-lex.l @@ -0,0 +1,243 @@ +/* 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. + * + */ + +%option noyywrap +%{ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/str.h" + +#include "director/lingo/lingo.h" +#include "director/lingo/lingo-gr.h" + +using namespace Director; + +int yyparse(); +static void count() { + g_lingo->_colnumber += strlen(yytext); +} + +#if defined(__PLAYSTATION2__) || defined(_MSC_VER) +// Stub for missing function +int isatty(int fileno) { return 0; } +#endif + +#ifdef _MSC_VER +#define YY_NO_UNISTD_H +#endif + +static void countnl() { + char *p = yytext; + + while(*p == '\n' || *p == '\r') + p++; + + g_lingo->_linenumber++; + g_lingo->_colnumber = strlen(p); +} + +%} + +identifier [_[:alpha:]][_[:alnum:]]* +constfloat [[:digit:]]+\.[[:digit:]]* +constinteger [[:digit:]]+ +conststring \"[^\"\r\n]*\" +operator [-+*/%=^:,()><&] +newline [ \t]*[\n\r] +whitespace [\t ] + +%% + +--[^\r\n]* +^{whitespace}+ { count(); } +[\t]+ { count(); return ' '; } + +(?i:and) { count(); return tAND; } +(?i:contains) { count(); return tCONTAINS; } +(?i:done) { count(); return tDONE; } +(?i:down) { count(); return tDOWN; } +(?i:if) { count(); return tIF; } +(?i:[\n\r]+[\t ]*else[\t ]+if) { countnl(); return tNLELSIF; } +(?i:[\n\r]+[\t ]*else) { countnl(); return tNLELSE; } +(?i:else) { count(); return tELSE; } +(?i:end) { count(); return tEND; } +(?i:factory) { count(); return tFACTORY; } +(?i:exit) { count(); return tEXIT; } +(?i:frame) { count(); return tFRAME; } +(?i:global) { count(); return tGLOBAL; } +(?i:go[\t ]+to) { count(); return tGO; } +(?i:go) { count(); return tGO; } +(?i:instance) { count(); return tINSTANCE; } +(?i:intersects) { count(); return tINTERSECTS; } +(?i:into) { count(); return tINTO; } +(?i:loop) { count(); return tLOOP; } +(?i:macro) { count(); return tMACRO; } +(?i:method) { count(); return tMETHOD; } +(?i:mod) { count(); return tMOD; } +(?i:movie) { count(); return tMOVIE; } +(?i:next) { count(); return tNEXT; } +(?i:not) { count(); return tNOT; } +(?i:of) { count(); return tOF; } +(?i:open) { count(); return tOPEN; } +(?i:or) { count(); return tOR; } +(?i:play) { count(); return tPLAY; } +(?i:previous) { count(); return tPREVIOUS; } +(?i:put) { count(); return tPUT; } +(?i:repeat) { count(); return tREPEAT; } +(?i:set) { count(); return tSET; } +(?i:starts) { count(); return tSTARTS; } +(?i:the[ \t]+sqrt[\t ]+of[\t ]+) { + count(); + + yylval.e[0] = g_lingo->_theEntities["sqrt"]->entity; + yylval.e[1] = 0; // No field + + return THEENTITYWITHID; + } +(?i:the[ \t]+[[:alpha:]]+[\t ]+of[\t ]+[[:alpha:]]+) { + count(); + + const char *ptr = &yytext[4]; // Skip 'the ' + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + Common::String field; + while (*ptr != ' ' && *ptr != '\t') + field += *ptr++; + + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + ptr += 3; // Skip 'of ' + + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + if (g_lingo->_theEntities.contains(ptr)) { + field = Common::String::format("%d%s", g_lingo->_theEntities[ptr]->entity, field.c_str()); + + if (!g_lingo->_theEntityFields.contains(field)) { + error("Unhandled the field %s", ptr); + } + + if (g_lingo->_theEntityFields[field]->entity != g_lingo->_theEntities[ptr]->entity) + error("Unsupported field '%s' for entity '%s'", field.c_str(), ptr); + + yylval.e[0] = g_lingo->_theEntities[ptr]->entity; + yylval.e[1] = g_lingo->_theEntityFields[field]->field; + + if (g_lingo->_theEntities[ptr]->hasId) + return THEENTITYWITHID; + else + return THEENTITY; + } + + warning("Unhandled the entity %s", ptr); + } +(?i:the[ \t]+[[:alpha:]]+) { + count(); + + const char *ptr = &yytext[4]; // Skip 'the ' + while (*ptr == ' ' || *ptr == '\t') + ptr++; + + if (g_lingo->_theEntities.contains(ptr)) { + yylval.e[0] = g_lingo->_theEntities[ptr]->entity; + yylval.e[1] = 0; // No field + + if (g_lingo->_theEntities[ptr]->hasId) + return THEENTITYWITHID; + else + return THEENTITY; + } + + warning("Unhandled the entity %s", ptr); + } +(?i:then) { count(); return tTHEN; } +(?i:to) { count(); return tTO; } +(?i:sprite) { count(); return tSPRITE; } +(?i:with) { count(); return tWITH; } +(?i:within) { count(); return tWITHIN; } +(?i:when) { count(); return tWHEN; } +(?i:while) { count(); return tWHILE; } + +[<][>] { count(); return tNEQ; } +[>][=] { count(); return tGE; } +[<][=] { count(); return tLE; } +[&][&] { count(); return tCONCAT; } + +{identifier} { + count(); + yylval.s = new Common::String(yytext); + + if (g_lingo->_handlers.contains(yytext)) { + if (g_lingo->_handlers[yytext]->type == BLTIN && g_lingo->_handlers[yytext]->parens == false) { + if (g_lingo->_handlers[yytext]->nargs == 0) { + if (g_lingo->_handlers[yytext]->maxArgs == 0) + return BLTINNOARGS; + else if (g_lingo->_handlers[yytext]->maxArgs == 1) + return BLTINNOARGSORONE; + else + error("Incorrect setup for builtin: %s", yytext); + } else if (g_lingo->_handlers[yytext]->nargs == 1 && + g_lingo->_handlers[yytext]->maxArgs == 1) { + return BLTINONEARG; + } else if (g_lingo->_handlers[yytext]->nargs == -1) { + return BLTINARGLIST; + } else { + error("Incorrect setup for builtin: %s", yytext); + } + } + } + + return ID; + } +{constfloat} { count(); yylval.f = atof(yytext); return FLOAT; } +{constinteger} { count(); yylval.i = strtol(yytext, NULL, 10); return INT; } +{operator} { count(); return *yytext; } +{newline} { return '\n'; } +{conststring} { count(); yylval.s = new Common::String(&yytext[1]); yylval.s->deleteLastChar(); return STRING; } +. + +%% + +extern int yydebug; + +namespace Director { + +int Lingo::parse(const char *code) { + YY_BUFFER_STATE bp; + + yydebug = 0; + + yy_delete_buffer(YY_CURRENT_BUFFER); + + bp = yy_scan_string(code); + yy_switch_to_buffer(bp); + yyparse(); + yy_delete_buffer(bp); + + return 0; +} + +} diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp new file mode 100644 index 0000000000..2bf6cfb724 --- /dev/null +++ b/engines/director/lingo/lingo-the.cpp @@ -0,0 +1,646 @@ +/* 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 "director/lingo/lingo.h" +#include "director/sprite.h" + +namespace Director { + +class Sprite; + +TheEntity entities[] = { + { kTheBeepOn, "beepOn", false }, // D2 property + { kTheButtonStyle, "buttonStyle", false }, // D2 p + { kTheCast, "cast", true }, + { kTheCenterStage, "centerStage", false }, // D2 p + { kTheCheckBoxAccess, "checkBoxAccess", false }, // D2 p + { kTheCheckBoxType, "checkBoxType", false }, // D2 p + { kTheClickOn, "clickOn", false }, // D2 function + { kTheColorDepth, "colorDepth", false }, // D2 p + { kTheColorQD, "colorQD", false }, // D2 f + { kTheCommandDown, "commandDown", false }, // D2 f + { kTheControlDown, "controlDown", false }, // D2 f + { kTheDoubleClick, "doubleClick", false }, // D2 f + { kTheExitLock, "exitLock", false }, // D2 p + { kTheFixStageSize, "fixStageSize", false }, // D2 p + { kTheFloatPrecision, "floatPrecision", false }, + { kTheFrame, "frame", false }, // D2 f + { kTheFreeBlock, "freeBlock", false }, // D2 f + { kTheFreeBytes, "freeBytes", false }, // D2 f + { kTheFullColorPermit, "fullColorPermit", false }, // D2 p + { kTheImageDirect, "imageDirect", false }, // D2 p + { kTheItemDelimiter, "itemDelimiter", false }, + { kTheKey, "key", false }, // D2 f + { kTheKeyCode, "keyCode", false }, // D2 f + { kTheKeyDownScript, "keyDownScript", false }, // D2 p + { kTheLastClick, "lastClick", false }, // D2 f + { kTheLastEvent, "lastEvent", false }, // D2 f + { kTheLastFrame, "lastFrame", false }, + { kTheLastKey, "lastKey", false }, // D2 f + { kTheLastRoll, "lastRoll", false }, // D2 f + { kTheMachineType, "machineType", false }, // D2 f + { kTheMemorySize, "memorySize", false }, // D2 f + { kTheMenu, "menu", true }, + { kTheMenus, "menus", false }, + { kTheMenuItem, "menuitem", true }, + { kTheMenuItems, "menuitems", false }, + { kTheMouseDown, "mouseDown", false }, // D2 f + { kTheMouseDownScript, "mouseDownScript", false }, // D2 p + { kTheMouseH, "mouseH", false }, // D2 f + { kTheMouseUp, "mouseUp", false }, // D2 f + { kTheMouseUpScript, "mouseUpScript", false }, // D2 p + { kTheMouseV, "mouseV", false }, // D2 f + { kTheMovie, "movie", false }, // D2 f + { kTheMultiSound, "multiSound", false }, + { kTheOptionDown, "optionDown", false }, // D2 f + { kThePathName, "pathName", false }, // D2 f + { kThePauseState, "pauseState", false }, // D2 f + { kThePerFrameHook, "perFrameHook", false }, // D2 p + { kThePreloadEventAbort,"preloadEventAbort",false }, + { kTheResult, "result", false }, // D2 f + { kTheRightMouseDown, "rightMouseDown", false }, + { kTheRightMouseUp, "rightMouseUp", false }, + { kTheRomanLingo, "romanLingo", false }, + { kTheSelection, "selection", false }, // D2 f + { kTheShiftDown, "shiftDown", false }, // D2 f + { kTheSoundEnabled, "soundEnabled", false }, // D2 p + { kTheSoundLevel, "soundLevel", false }, // D2 p + { kTheSprite, "sprite", true }, + { kTheSqrt, "sqrt", false }, // D2 f + { kTheStage, "stage", false }, + { kTheStageBottom, "stageBottom", false }, // D2 f + { kTheStageLeft, "stageLeft", false }, // D2 f + { kTheStageRight, "stageRight", false }, // D2 f + { kTheStageTop, "stageTop", false }, // D2 f + { kTheStillDown, "stillDown", false }, // D2 f + { kTheSwitchColorDepth, "switchColorDepth", false }, // D2 p + { kTheTicks, "ticks", false }, // D2 f + { kTheTimeoutKeydown, "timeoutKeydown", false }, // D2 p + { kTheTimeoutLapsed, "timeoutLapsed", false }, // D2 p + { kTheTimeoutLength, "timeoutLength", false }, // D2 p + { kTheTimeoutMouse, "timeoutMouse", false }, // D2 p + { kTheTimeoutPlay, "timeoutPlay", false }, // D2 p + { kTheTimeoutScript, "timeoutScript", false }, // D2 p + { kTheTimer, "timer", false }, // D2 p + { kTheWindow, "window", false }, + { kTheNOEntity, NULL, false } +}; + +TheEntityField fields[] = { + { kTheSprite, "backColor", kTheBackColor }, // D2 p + { kTheSprite, "blend", kTheBlend }, + { kTheSprite, "bottom", kTheBottom }, // D2 p + { kTheSprite, "castNum", kTheCastNum }, // D2 p + { kTheSprite, "constraint", kTheConstraint }, // D2 p + { kTheSprite, "cursor", kTheCursor }, // D2 p + { kTheSprite, "editableText", kTheEditableText }, + { kTheSprite, "foreColor", kTheForeColor }, // D2 p + { kTheSprite, "height", kTheHeight }, // D2 p + { kTheSprite, "immediate", kTheImmediate }, // D2 p + { kTheSprite, "ink", kTheInk }, // D2 p + { kTheSprite, "left", kTheLeft }, // D2 p + { kTheSprite, "lineSize", kTheLineSize }, // D2 p + { kTheSprite, "locH", kTheLocH }, // D2 p + { kTheSprite, "locV", kTheLocV }, // D2 p + { kTheSprite, "moveable", kTheMoveable }, + { kTheSprite, "movieRate", kTheMovieRate }, + { kTheSprite, "movieTime", kTheMovieTime }, + { kTheSprite, "pattern", kThePattern }, // D2 p + { kTheSprite, "puppet", kThePuppet }, // D2 p + { kTheSprite, "right", kTheRight }, // D2 p + { kTheSprite, "scriptNum", kTheScriptNum }, + { kTheSprite, "startTime", kTheStartTime }, + { kTheSprite, "stretch", kTheStrech }, // D2 p + { kTheSprite, "stopTime", kTheStopTime }, + { kTheSprite, "top", kTheTop }, // D2 p + { kTheSprite, "trails", kTheTrails }, + { kTheSprite, "type", kTheType }, // D2 p + { kTheSprite, "visible", kTheVisible }, + { kTheSprite, "volume", kTheVolume }, + { kTheSprite, "width", kTheWidth }, // D2 p + + // Common cast fields + { kTheCast, "castType", kTheCastType }, + { kTheCast, "filename", kTheFilename }, + { kTheCast, "height", kTheHeight }, + { kTheCast, "loaded", kTheLoaded }, + { kTheCast, "modified", kTheModified }, + { kTheCast, "name", kTheName }, + { kTheCast, "number", kTheNumber }, + { kTheCast, "rect", kTheRect }, + { kTheCast, "purgePriority",kThePurgePriority }, // 0 Never purge, 1 Purge Last, 2 Purge next, 2 Purge normal + { kTheCast, "scriptText", kTheScriptText }, + { kTheCast, "width", kTheWidth }, + + // Shape fields + { kTheCast, "backColor", kTheBackColor }, + { kTheCast, "foreColor", kTheForeColor }, + + // Digital video fields + { kTheCast, "controller", kTheController }, + { kTheCast, "directToStage",kTheDirectToStage }, + { kTheCast, "frameRate", kTheFrameRate }, + { kTheCast, "loop", kTheLoop }, + { kTheCast, "pausedAtStart",kThePausedAtStart }, + { kTheCast, "preload", kThePreload }, + { kTheCast, "sound", kTheSound }, // 0-1 off-on + + // Bitmap fields + { kTheCast, "depth", kTheDepth }, + { kTheCast, "regPoint", kTheRegPoint }, + { kTheCast, "palette", kThePalette }, + { kTheCast, "picture", kThePicture }, + + // TextCast fields + { kTheCast, "hilite", kTheHilite }, // D2 p + { kTheCast, "selEnd", kTheSelEnd }, // D2 p + { kTheCast, "selStart", kTheSelStart }, // D2 p + { kTheCast, "size", kTheSize }, + { kTheCast, "text", kTheText }, // D2 p + + { kTheWindow, "drawRect", kTheDrawRect }, + { kTheWindow, "filename", kTheFilename }, + { kTheWindow, "sourceRect", kTheSourceRect }, + { kTheWindow, "visible", kTheVisible }, + + { kTheMenuItem, "checkmark", kTheCheckMark }, + { kTheMenuItem, "enabled", kTheEnabled }, + { kTheMenuItem, "name", kTheName }, + { kTheMenuItem, "script", kTheScript }, + + { kTheMenu, "name", kTheName }, + + { kTheMenuItems,"number", kTheNumber }, + { kTheMenus, "number", kTheNumber }, + + { kTheNOEntity, NULL, kTheNOField } +}; + +void Lingo::initTheEntities() { + TheEntity *e = entities; + + while (e->entity != kTheNOEntity) { + _theEntities[e->name] = e; + e++; + } + + TheEntityField *f = fields; + + while (f->entity != kTheNOEntity) { + _theEntityFields[Common::String::format("%d%s", f->entity, f->name)] = f; + f++; + } +} + +void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) { + switch (entity) { + case kTheSprite: + setTheSprite(id, field, d); + break; + case kThePerFrameHook: + warning("STUB: setting the perframehook"); + break; + case kTheFloatPrecision: + _floatPrecision = d.toInt(); + _floatPrecision = MAX(0, MIN(_floatPrecision, 19)); // 0 to 19 + _floatPrecisionFormat = Common::String::format("%%.%df", _floatPrecision); + warning("set to %d: %s", _floatPrecision, _floatPrecisionFormat.c_str()); + break; + default: + warning("Unprocessed setting field %d of entity %d", field, entity); + } +} + +void Lingo::setTheSprite(Datum &id1, int field, Datum &d) { + int id = 0; + + if (id1.type == INT) { + id = id1.u.i; + } else { + warning("Unknown the sprite id type: %s", id1.type2str()); + return; + } + + d.toInt(); // Enforce Integer + + if (!_vm->_currentScore) { + warning("The sprite %d field %d setting over non-active score", id, field); + return; + } + + Sprite *sprite = _vm->_currentScore->getSpriteById(id); + + if (!sprite) + return; + + switch (field) { + case kTheCastNum: + if (_vm->_currentScore->_casts.contains(d.u.i)) { + sprite->_cast = _vm->_currentScore->_casts[d.u.i]; + sprite->_castId = d.u.i; + } + break; + case kTheWidth: + sprite->_width = d.u.i; + break; + case kTheHeight: + sprite->_height = d.u.i; + break; + case kTheTrails: + sprite->_trails = d.u.i; + break; + case kTheInk: + sprite->_ink = static_cast<InkType>(d.u.i); + break; + case kTheLocH: + sprite->_startPoint.x = d.u.i; + break; + case kTheLocV: + sprite->_startPoint.y = d.u.i; + break; + case kTheConstraint: + sprite->_constraint = d.u.i; + break; + case kTheMoveable: + sprite->_moveable = d.u.i; + break; + case kTheBackColor: + sprite->_backColor = d.u.i; + break; + case kTheForeColor: + sprite->_foreColor = d.u.i; + break; + case kTheLeft: + sprite->_left = d.u.i; + break; + case kTheRight: + sprite->_right = d.u.i; + break; + case kTheTop: + sprite->_top = d.u.i; + break; + case kTheBottom: + sprite->_bottom = d.u.i; + break; + case kTheBlend: + sprite->_blend = d.u.i; + break; + case kTheVisible: + sprite->_visible = (d.u.i == 0 ? false : true); + break; + case kTheType: + sprite->_type = static_cast<SpriteType>(d.u.i); + break; + case kTheMovieRate: + sprite->_movieRate = d.u.i; + break; + case kTheMovieTime: + sprite->_movieTime = d.u.i; + break; + case kTheStopTime: + sprite->_stopTime = d.u.i; + break; + case kTheStartTime: + sprite->_startTime = d.u.i; + break; + case kTheStretch: + sprite->_stretch = d.u.i; + break; + case kTheVolume: + sprite->_volume = d.u.i; + break; + case kTheLineSize: + sprite->_lineSize = d.u.i; + break; + case kTheEditableText: + sprite->_editableText = *d.toString(); + break; + default: + warning("Unprocessed setting field %d of sprite", field); + } +} + +Datum Lingo::getTheEntity(int entity, Datum &id, int field) { + Datum d; + + switch (entity) { + case kTheSprite: + d = getTheSprite(id, field); + break; + case kTheCast: + d = getTheCast(id, field); + break; + case kThePerFrameHook: + warning("STUB: getting the perframehook"); + break; + case kTheFloatPrecision: + d.type = INT; + d.u.i = _floatPrecision; + break; + case kTheSqrt: + id.toFloat(); + d.type = FLOAT; + d.u.f = sqrt(id.u.f); + break; + default: + warning("Unprocessed getting field %d of entity %d", field, entity); + d.type = VOID; + } + + return d; +} + +Datum Lingo::getTheSprite(Datum &id1, int field) { + Datum d; + int id = 0; + + if (id1.type == INT) { + id = id1.u.i; + } else { + warning("Unknown the sprite id type: %s", id1.type2str()); + return d; + } + + if (!_vm->_currentScore) { + warning("The sprite %d field %d setting over non-active score", id, field); + return d; + } + + Sprite *sprite = _vm->_currentScore->getSpriteById(id); + + if (!sprite) + return d; + + d.type = INT; + + switch (field) { + case kTheCastNum: + d.u.i = sprite->_castId; + break; + case kTheWidth: + d.u.i = sprite->_width; + break; + case kTheHeight: + d.u.i = sprite->_height; + break; + case kTheTrails: + d.u.i = sprite->_trails; + break; + case kTheInk: + d.u.i = sprite->_ink; + break; + case kTheLocH: + d.u.i = sprite->_startPoint.x; + break; + case kTheLocV: + d.u.i = sprite->_startPoint.y; + break; + case kTheConstraint: + d.u.i = sprite->_constraint; + break; + case kTheMoveable: + d.u.i = sprite->_moveable; + break; + case kTheBackColor: + d.u.i = sprite->_backColor; + break; + case kTheForeColor: + d.u.i = sprite->_foreColor; + break; + case kTheLeft: + d.u.i = sprite->_left; + break; + case kTheRight: + d.u.i = sprite->_right; + break; + case kTheBottom: + d.u.i = sprite->_bottom; + break; + case kTheTop: + d.u.i = sprite->_top; + break; + case kTheBlend: + d.u.i = sprite->_blend; + break; + case kTheVisible: + d.u.i = (sprite->_visible ? 1 : 0); + break; + case kTheType: + d.u.i = sprite->_type; + break; + case kTheMovieRate: + d.u.i = sprite->_movieRate; + break; + case kTheMovieTime: + d.u.i = sprite->_movieTime; + break; + case kTheStopTime: + d.u.i = sprite->_stopTime; + break; + case kTheStartTime: + d.u.i = sprite->_startTime; + break; + case kTheVolume: + d.u.i = sprite->_volume; + break; + case kTheStretch: + d.u.i = sprite->_stretch; + break; + case kTheLineSize: + d.u.i = sprite->_lineSize; + break; + case kTheEditableText: + d.toString(); + d.u.s = &sprite->_editableText; + break; + default: + warning("Unprocessed getting field %d of sprite", field); + d.type = VOID; + } + + return d; +} + +Datum Lingo::getTheCast(Datum &id1, int field) { + Datum d; + int id = 0; + + if (id1.type == INT) { + id = id1.u.i; + } else { + warning("Unknown the cast id type: %s", id1.type2str()); + return d; + } + + if (!_vm->_currentScore) { + warning("The cast %d field %d setting over non-active score", id, field); + return d; + } + + Cast *cast; + CastInfo *castInfo; + if (!_vm->_currentScore->_casts.contains(id)) { + if (field == kTheLoaded) { + d.type = INT; + d.u.i = 0; + } + + return d; + } else { + warning("The cast %d found", id); + } + + cast = _vm->_currentScore->_casts[id]; + castInfo = _vm->_currentScore->_castsInfo[id]; + + d.type = INT; + + switch (field) { + case kTheCastType: + d.u.i = cast->type; + break; + case kTheFilename: + d.toString(); + d.u.s = &castInfo->fileName; + break; + case kTheName: + d.toString(); + d.u.s = &castInfo->name; + break; + case kTheScriptText: + d.toString(); + d.u.s = &castInfo->script; + break; + case kTheWidth: + d.u.i = cast->initialRect.width(); + break; + case kTheHeight: + d.u.i = cast->initialRect.height(); + break; + case kTheBackColor: + { + if (cast->type != kCastShape) { + warning("Field %d of cast %d not found", field, id); + d.type = VOID; + return d; + } + + ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + d.u.i = shape->bgCol; + } + break; + case kTheForeColor: + { + if (cast->type != kCastShape) { + warning("Field %d of cast %d not found", field, id); + d.type = VOID; + return d; + } + + ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + d.u.i = shape->fgCol; + } + break; + case kTheLoaded: + d.u.i = 1; //Not loaded handled above + break; + default: + warning("Unprocessed getting field %d of cast %d", field, id); + d.type = VOID; + //TODO find out about String fields + } + + return d; +} + +void Lingo::setTheCast(Datum &id1, int field, Datum &d) { + int id = 0; + + if (id1.type == INT) { + id = id1.u.i; + } else { + warning("Unknown the cast id type: %s", id1.type2str()); + return; + } + + if (!_vm->_currentScore) { + warning("The cast %d field %d setting over non-active score", id, field); + return; + } + + Cast *cast = _vm->_currentScore->_casts[id]; + CastInfo *castInfo = _vm->_currentScore->_castsInfo[id]; + + if (!cast) { + warning("The cast %d found", id); + return; + } + + switch (field) { + case kTheCastType: + cast->type = static_cast<CastType>(d.u.i); + cast->modified = 1; + break; + case kTheFilename: + castInfo->fileName = *d.u.s; + break; + case kTheName: + castInfo->name = *d.u.s; + break; + case kTheScriptText: + castInfo->script = *d.u.s; + break; + case kTheWidth: + cast->initialRect.setWidth(d.u.i); + cast->modified = 1; + break; + case kTheHeight: + cast->initialRect.setHeight(d.u.i); + cast->modified = 1; + break; + case kTheBackColor: + { + if (cast->type != kCastShape) { + warning("Field %d of cast %d not found", field, id); + } + ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + shape->bgCol = d.u.i; + shape->modified = 1; + } + break; + case kTheForeColor: + { + if (cast->type != kCastShape) { + warning("Field %d of cast %d not found", field, id); + return; + } + ShapeCast *shape = static_cast<ShapeCast *>(_vm->_currentScore->_casts[id]); + shape->fgCol = d.u.i; + shape->modified = 1; + } + break; + default: + warning("Unprocessed getting field %d of cast %d", field, id); + } +} + +} // End of namespace Director diff --git a/engines/director/lingo/lingo-the.h b/engines/director/lingo/lingo-the.h new file mode 100644 index 0000000000..f68a81d363 --- /dev/null +++ b/engines/director/lingo/lingo-the.h @@ -0,0 +1,189 @@ +/* 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 DIRECTOR_LINGO_LINGO_THE_H + #define DIRECTOR_LINGO_LINGO_THE_H + +namespace Director { + +enum TheEntityType { + kTheNOEntity = 0, + kTheFrame = 1, + kTheFreeBlock, + kTheFreeBytes, + kThePathName, + kTheMenu, + kTheMenuItem, + kTheMenuItems, + kTheMenus, + kTheMovie, + kTheMouseH, + kTheMouseV, + kTheMouseDownScript, + kTheMouseUpScript, + + kTheSprite, + kTheCast, + kThePerFrameHook, + kTheTicks, + kTheTimer, + kTheTimeoutKeydown, + kTheTimeoutLapsed, + kTheTimeoutLength, + kTheTimeoutMouse, + kTheTimeoutPlay, + kTheTimeoutScript, + kTheWindow, + + kTheBeepOn, + kTheButtonStyle, + kTheCenterStage, + kTheCheckBoxAccess, + kTheCheckBoxType, + kTheClickOn, + kTheControlDown, + kTheCommandDown, + kTheDoubleClick, + kTheFixStageSize, + kTheFullColorPermit, + kTheImageDirect, + kTheKey, + kTheKeyDownScript, + kTheKeyCode, + kTheLastClick, + kTheLastEvent, + kTheLastFrame, + kTheLastKey, + kTheLastRoll, + kTheMachineType, + kTheMemorySize, + kTheMouseDown, + kTheMouseUp, + kTheOptionDown, + kThePauseState, + kTheRightMouseUp, + kTheRightMouseDown, + kTheSoundEnabled, + kTheSoundLevel, + kTheStillDown, + kTheSwitchColorDepth, + kTheResult, + kTheSelection, + kTheShiftDown, + kTheSqrt, + + kTheColorDepth, + kTheColorQD, + kTheExitLock, + kTheFloatPrecision, + kTheItemDelimiter, + kTheMultiSound, + kThePreloadEventAbort, + kTheRomanLingo, + kTheStage, + kTheStageBottom, + kTheStageLeft, + kTheStageRight, + kTheStageTop +}; + +enum TheFieldType { + kTheNOField = 0, + kTheCastNum = 1, + kTheCastType, + kTheCheckMark, + kTheController, + kTheCursor, + kTheDepth, + kTheDirectToStage, + kTheDrawRect, + kTheLocH, + kTheLocV, + kTheBackColor, + kTheBlend, + kTheBottom, + kTheConstraint, + kTheEditableText, + kTheEnabled, + kTheForeColor, + kTheFrameRate, + kTheFilename, + kTheHeight, + kTheHilite, + kTheImmediate, + kTheInk, + kTheLeft, + kTheLineSize, + kTheLoop, + kTheLoaded, + kTheModified, + kTheMoveable, + kTheMovieRate, + kTheMovieTime, + kTheNumber, + kTheName, + kThePalette, + kThePattern, + kThePausedAtStart, + kThePicture, + kThePreload, + kThePuppet, + kThePurgePriority, + kTheRect, + kTheRegPoint, + kTheRight, + kTheStopTime, + kTheStretch, + kTheStartTime, + kTheScript, + kTheScriptNum, + kTheScriptText, + kTheSelEnd, + kTheSelStart, + kTheSize, + kTheStrech, + kTheSound, + kTheSourceRect, + kTheText, + kTheTop, + kTheTrails, + kTheType, + kTheVisible, + kTheVolume, + kTheWidth +}; + +struct TheEntity { + TheEntityType entity; + const char *name; + bool hasId; +}; + +struct TheEntityField { + TheEntityType entity; + const char *name; + TheFieldType field; +}; + +} // End of namespace Director + +#endif diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp new file mode 100644 index 0000000000..17e8ea44fe --- /dev/null +++ b/engines/director/lingo/lingo.cpp @@ -0,0 +1,471 @@ +/* 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/archive.h" +#include "common/file.h" +#include "common/str-array.h" + +#include "director/lingo/lingo.h" +#include "director/lingo/lingo-gr.h" + +namespace Director { + +Lingo *g_lingo; + +struct EventHandlerType { + LEvent handler; + const char *name; +} static const eventHanlerDescs[] = { + { kEventPrepareMovie, "prepareMovie" }, + { kEventStartMovie, "startMovie" }, + { kEventStopMovie, "stopMovie" }, + + { kEventNew, "newSprite" }, + { kEventBeginSprite, "beginSprite" }, + { kEventEndSprite, "endSprite" }, + + { kEventEnterFrame, "enterFrame" }, + { kEventPrepareFrame, "prepareFrame" }, + { kEventIdle, "idle" }, + { kEventStepFrame, "stepFrame"}, + { kEventExitFrame, "exitFrame" }, + + { kEventActivateWindow, "activateWindow" }, + { kEventDeactivateWindow, "deactivateWindow" }, + { kEventMoveWindow, "moveWindow" }, + { kEventResizeWindow, "resizeWindow" }, + { kEventOpenWindow, "openWindow" }, + { kEventCloseWindow, "closeWindow" }, + { kEventStart, "start" }, + + { kEventKeyUp, "keyUp" }, + { kEventKeyDown, "keyDown" }, + { kEventMouseUp, "mouseUp" }, + { kEventMouseDown, "mouseDown" }, + { kEventRightMouseDown, "rightMouseDown" }, + { kEventRightMouseUp, "rightMouseUp" }, + { kEventMouseEnter, "mouseEnter" }, + { kEventMouseLeave, "mouseLeave" }, + { kEventMouseUpOutSide, "mouseUpOutSide" }, + { kEventMouseWithin, "mouseWithin" }, + + { kEventNone, 0 }, +}; + +Symbol::Symbol() { + name = NULL; + type = VOID; + u.s = NULL; + nargs = 0; + maxArgs = 0; + parens = true; + global = false; +} + +Lingo::Lingo(DirectorEngine *vm) : _vm(vm) { + g_lingo = this; + + for (const EventHandlerType *t = &eventHanlerDescs[0]; t->handler != kEventNone; ++t) + _eventHandlerTypes[t->handler] = t->name; + + initBuiltIns(); + initFuncs(); + initTheEntities(); + + _currentScript = 0; + _currentScriptType = kMovieScript; + _pc = 0; + _returning = false; + _indef = false; + + _linenumber = _colnumber = 0; + + _hadError = false; + + _inFactory = false; + + _floatPrecision = 4; + _floatPrecisionFormat = "%.4f"; + + _exitRepeat = false; + + _localvars = NULL; + + warning("Lingo Inited"); +} + +Lingo::~Lingo() { +} + +const char *Lingo::findNextDefinition(const char *s) { + const char *res = s; + + while (*res) { + while (*res && (*res == ' ' || *res == '\t' || *res == '\n')) + res++; + + if (!*res) + return NULL; + + if (!strncmp(res, "macro ", 6)) { + debugC(3, kDebugLingoCompile, "See macro"); + return res; + } + + if (!strncmp(res, "factory ", 8)) { + debugC(3, kDebugLingoCompile, "See factory"); + return res; + } + + if (!strncmp(res, "method ", 7)) { + debugC(3, kDebugLingoCompile, "See method"); + return res; + } + + while (*res && *res != '\n') + res++; + } + + return NULL; +} + +void Lingo::addCode(const char *code, ScriptType type, uint16 id) { + debugC(2, kDebugLingoCompile, "Add code \"%s\" for type %d with id %d", code, type, id); + + if (_scripts[type].contains(id)) { + delete _scripts[type][id]; + } + + _currentScript = new ScriptData; + _currentScriptType = type; + _scripts[type][id] = _currentScript; + + _linenumber = _colnumber = 1; + _hadError = false; + + const char *begin, *end; + + if (!strncmp(code, "menu:", 5)) { + debugC(2, kDebugLingoCompile, "Parsing menu"); + parseMenu(code); + + return; + } + + // macros and factories have conflicting grammar. Thus we ease life for the parser. + if ((begin = findNextDefinition(code))) { + bool first = true; + + while ((end = findNextDefinition(begin + 1))) { + + if (first) { + begin = code; + first = false; + } + Common::String chunk(begin, end); + + if (chunk.hasPrefix("factory") || chunk.hasPrefix("method")) + _inFactory = true; + else if (chunk.hasPrefix("macro")) + _inFactory = false; + else + _inFactory = false; + + debugC(2, kDebugLingoCompile, "Code chunk:\n#####\n%s#####", chunk.c_str()); + + parse(chunk.c_str()); + + if (debugChannelSet(3, kDebugLingoCompile)) { + int pc = 0; + while (pc < _currentScript->size()) { + Common::String instr = decodeInstruction(pc, &pc); + debugC(3, kDebugLingoCompile, "[%5d] %s", pc, instr.c_str()); + } + } + + _currentScript->clear(); + + begin = end; + } + + _hadError = true; // HACK: This is for preventing test execution + + debugC(2, kDebugLingoCompile, "Code chunk:\n#####\n%s#####", begin); + parse(begin); + } else { + parse(code); + + code1(STOP); + } + + _inFactory = false; + + if (debugChannelSet(3, kDebugLingoCompile)) { + if (_currentScript->size() && !_hadError) + Common::hexdump((byte *)&_currentScript->front(), _currentScript->size() * sizeof(inst)); + + int pc = 0; + while (pc < _currentScript->size()) { + Common::String instr = decodeInstruction(pc, &pc); + debugC(3, kDebugLingoCompile, "[%5d] %s", pc, instr.c_str()); + } + } +} + +void Lingo::executeScript(ScriptType type, uint16 id) { + if (!_scripts[type].contains(id)) { + warning("Request to execute non-existant script type %d id %d", type, id); + return; + } + + debugC(2, kDebugLingoExec, "Executing script type: %d, id: %d", type, id); + + _currentScript = _scripts[type][id]; + _pc = 0; + _returning = false; + + _localvars = new SymbolHash; + + execute(_pc); + + cleanLocalVars(); +} + +ScriptType Lingo::event2script(LEvent ev) { + if (_vm->getVersion() < 4) { + switch (ev) { + //case kEventStartMovie: // We are precompiling it now + // return kMovieScript; + case kEventEnterFrame: + return kFrameScript; + default: + return kNoneScript; + } + } + + return kNoneScript; +} + +void Lingo::processEvent(LEvent event, int entityId) { + if (!_eventHandlerTypes.contains(event)) + error("processEvent: Unknown event %d for entity %d", event, entityId); + + ScriptType st = event2script(event); + + if (st != kNoneScript) + executeScript(st, entityId + 1); + else + debugC(8, kDebugLingoExec, "STUB: processEvent(%s) for %d", _eventHandlerTypes[event], entityId); +} + +int Lingo::alignTypes(Datum &d1, Datum &d2) { + int opType = INT; + + if (d1.type == FLOAT || d2.type == FLOAT) { + opType = FLOAT; + d1.toFloat(); + d2.toFloat(); + } + + return opType; +} + +int Datum::toInt() { + switch (type) { + case INT: + // no-op + break; + case FLOAT: + u.i = (int)u.f; + type = INT; + break; + default: + warning("Incorrect operation toInt() for type: %s", type2str()); + } + + return u.i; +} + +double Datum::toFloat() { + switch (type) { + case INT: + u.f = (double)u.i; + type = FLOAT; + break; + case FLOAT: + // no-op + break; + default: + warning("Incorrect operation toFloat() for type: %s", type2str()); + } + + return u.f; +} + +Common::String *Datum::toString() { + Common::String *s = new Common::String; + switch (type) { + case INT: + *s = Common::String::format("%d", u.i); + break; + case FLOAT: + *s = Common::String::format(g_lingo->_floatPrecisionFormat.c_str(), u.f); + break; + case STRING: + delete s; + s = u.s; + break; + case OBJECT: + *s = Common::String::format("#%s", u.s->c_str()); + break; + case VOID: + *s = "#void"; + break; + case VAR: + *s = Common::String::format("var: #%s", u.sym->name); + break; + default: + warning("Incorrect operation toString() for type: %s", type2str()); + } + + u.s = s; + type = STRING; + + return u.s; +} + +const char *Datum::type2str(bool isk) { + static char res[20]; + + switch (isk ? u.i : type) { + case INT: + return isk ? "#integer" : "INT"; + case FLOAT: + return isk ? "#float" : "FLOAT"; + case STRING: + return isk ? "#string" : "STRING"; + case CASTREF: + return "CASTREF"; + case VOID: + return isk ? "#void" : "VOID"; + case POINT: + return isk ? "#point" : "POINT"; + case SYMBOL: + return isk ? "#symbol" : "SYMBOL"; + case OBJECT: + return isk ? "#object" : "OBJECT"; + case VAR: + return isk ? "#var" : "VAR"; + default: + snprintf(res, 20, "-- (%d) --", type); + return res; + } +} + +// This is table for built-in Macintosh font lowercasing. +// '.' means that the symbol should be not changed, rest +// of the symbols are stripping the diacritics +// The table starts from 0x80 +// +// TODO: Check it for correctness. +static char lowerCaseConvert[] = +"aacenoua" // 80 +"aaaaacee" // 88 +"eeiiiino" // 90 +"oooouuuu" // 98 +"........" // a0 +".......o" // a8 +"........" // b0 +".......o" // b8 +"........" // c0 +".. aao.." // c8 +"--.....y";// d0-d8 + +Common::String *Lingo::toLowercaseMac(Common::String *s) { + Common::String *res = new Common::String; + const unsigned char *p = (const unsigned char *)s->c_str(); + + while (*p) { + if (*p >= 0x80 && *p <= 0xd8) { + if (lowerCaseConvert[*p - 0x80] != '.') + *res += lowerCaseConvert[*p - 0x80]; + else + *res += *p; + } else if (*p < 0x80) { + *res += tolower(*p); + } else { + warning("Unacceptable symbol in toLowercaseMac: %c", *p); + + *res += *p; + } + p++; + } + + return res; +} + +void Lingo::parseMenu(const char *code) { + warning("STUB: parseMenu"); +} + +void Lingo::runTests() { + Common::File inFile; + Common::ArchiveMemberList fsList; + SearchMan.listMatchingMembers(fsList, "*.lingo"); + Common::StringArray fileList; + + int counter = 1; + + for (Common::ArchiveMemberList::iterator it = fsList.begin(); it != fsList.end(); ++it) + fileList.push_back((*it)->getName()); + + Common::sort(fileList.begin(), fileList.end()); + + for (uint i = 0; i < fileList.size(); i++) { + Common::SeekableReadStream *const stream = SearchMan.createReadStreamForMember(fileList[i]); + if (stream) { + uint size = stream->size(); + + char *script = (char *)calloc(size + 1, 1); + + stream->read(script, size); + + debugC(2, kDebugLingoCompile, "Compiling file %s of size %d, id: %d", fileList[i].c_str(), size, counter); + + _hadError = false; + addCode(script, kMovieScript, counter); + + if (!_hadError) + executeScript(kMovieScript, counter); + else + debugC(2, kDebugLingoCompile, "Skipping execution"); + + free(script); + + counter++; + } + + inFile.close(); + } +} + +} // End of namespace Director diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h new file mode 100644 index 0000000000..4dd00417b8 --- /dev/null +++ b/engines/director/lingo/lingo.h @@ -0,0 +1,460 @@ +/* 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 DIRECTOR_LINGO_LINGO_H +#define DIRECTOR_LINGO_LINGO_H + +#include "audio/audiostream.h" +#include "common/hash-str.h" + +#include "director/director.h" +#include "director/score.h" +#include "director/lingo/lingo-gr.h" +#include "director/lingo/lingo-the.h" + +namespace Director { + +enum LEvent { + kEventPrepareMovie, + kEventStartMovie, + kEventStopMovie, + + kEventNew, + kEventBeginSprite, + kEventEndSprite, + + kEventNone, + kEventEnterFrame, + kEventPrepareFrame, + kEventIdle, + kEventStepFrame, + kEventExitFrame, + + kEventActivateWindow, + kEventDeactivateWindow, + kEventMoveWindow, + kEventResizeWindow, + kEventOpenWindow, + kEventCloseWindow, + + kEventKeyUp, + kEventKeyDown, + kEventMouseUp, + kEventMouseDown, + kEventRightMouseUp, + kEventRightMouseDown, + kEventMouseEnter, + kEventMouseLeave, + kEventMouseUpOutSide, + kEventMouseWithin, + + kEventStart +}; + +typedef void (*inst)(void); +#define STOP (inst)0 + +typedef Common::Array<inst> ScriptData; +typedef Common::Array<double> FloatArray; + +struct FuncDesc { + Common::String name; + const char *proto; + + FuncDesc(Common::String n, const char *p) { name = n; proto = p; } +}; + +struct Pointer_EqualTo { + bool operator()(const void *x, const void *y) const { return x == y; } +}; + +struct Pointer_Hash { + uint operator()(const void *x) const { +#ifdef SCUMM_64BITS + uint64 v = (uint64)x; + return (v >> 32) ^ (v & 0xffffffff); +#else + return (uint)x; +#endif + } +}; + +typedef Common::HashMap<void *, FuncDesc *, Pointer_Hash, Pointer_EqualTo> FuncHash; + +struct Symbol { /* symbol table entry */ + char *name; + int type; + union { + int i; /* VAR */ + double f; /* FLOAT */ + ScriptData *defn; /* FUNCTION, PROCEDURE */ + void (*func)(); /* OPCODE */ + void (*bltin)(int); /* BUILTIN */ + Common::String *s; /* STRING */ + FloatArray *arr; /* ARRAY, POINT, RECT */ + } u; + int nargs; /* number of arguments */ + int maxArgs; /* maximal number of arguments, for builtins */ + bool parens; /* whether parens required or not, for builitins */ + + bool global; + + Symbol(); +}; + +struct Datum { /* interpreter stack type */ + int type; + + union { + int i; + double f; + Common::String *s; + Symbol *sym; + FloatArray *arr; /* ARRAY, POINT, RECT */ + } u; + + Datum() { u.sym = NULL; type = VOID; } + Datum(int val) { u.i = val; type = INT; } + Datum(double val) { u.f = val; type = FLOAT; } + Datum(Common::String *val) { u.s = val; type = STRING; } + + double toFloat(); + int toInt(); + Common::String *toString(); + + const char *type2str(bool isk = false); +}; + +struct Builtin { + void (*func)(void); + int nargs; + + Builtin(void (*func1)(void), int nargs1) : func(func1), nargs(nargs1) {} +}; + +typedef Common::HashMap<int32, ScriptData *> ScriptHash; +typedef Common::Array<Datum> StackData; +typedef Common::HashMap<Common::String, Symbol *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SymbolHash; +typedef Common::HashMap<Common::String, Builtin *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> BuiltinHash; + +typedef Common::HashMap<Common::String, TheEntity *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> TheEntityHash; +typedef Common::HashMap<Common::String, TheEntityField *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> TheEntityFieldHash; + +struct CFrame { /* proc/func call stack frame */ + Symbol *sp; /* symbol table entry */ + int retpc; /* where to resume after return */ + ScriptData *retscript; /* which script to resume after return */ + SymbolHash *localvars; +}; + +class Lingo { +public: + Lingo(DirectorEngine *vm); + ~Lingo(); + + void addCode(const char *code, ScriptType type, uint16 id); + void executeScript(ScriptType type, uint16 id); + void printStack(const char *s); + Common::String decodeInstruction(int pc, int *newPC = NULL); + + ScriptType event2script(LEvent ev); + + void processEvent(LEvent event, int entityId); + + void initBuiltIns(); + void initFuncs(); + void initTheEntities(); + + Common::String *toLowercaseMac(Common::String *s); + + void runTests(); + +private: + const char *findNextDefinition(const char *s); + +public: + void execute(int pc); + void pushContext(); + void popContext(); + Symbol *lookupVar(const char *name, bool create = true, bool putInGlobalList = false); + void cleanLocalVars(); + void define(Common::String &s, int start, int nargs, Common::String *prefix = NULL); + void processIf(int elselabel, int endlabel); + + int alignTypes(Datum &d1, Datum &d2); + + int code1(inst code) { _currentScript->push_back(code); return _currentScript->size() - 1; } + int code2(inst code_1, inst code_2) { int o = code1(code_1); code1(code_2); return o; } + int code3(inst code_1, inst code_2, inst code_3) { int o = code1(code_1); code1(code_2); code1(code_3); return o; } + int codeString(const char *s); + void codeLabel(int label); + int codeConst(int val); + + int calcStringAlignment(const char *s) { + return calcCodeAlignment(strlen(s) + 1); + } + int calcCodeAlignment(int l) { + int instLen = sizeof(inst); + return (l + instLen - 1) / instLen; + } + + void codeArg(Common::String *s); + void codeArgStore(); + int codeFunc(Common::String *s, int numpar); + int codeFloat(double f); + void codeFactory(Common::String &s); + + void pushVoid(); + + static void c_xpop(); + static void c_printtop(); + + static void c_add(); + static void c_sub(); + static void c_mul(); + static void c_div(); + static void c_mod(); + static void c_negate(); + + static void c_and(); + static void c_or(); + static void c_not(); + + static void c_ampersand(); + static void c_concat(); + static void c_contains(); + static void c_starts(); + + static void c_intersects(); + static void c_within(); + + static void c_constpush(); + static void c_voidpush(); + static void c_fconstpush(); + static void c_stringpush(); + static void c_varpush(); + static void c_assign(); + bool verify(Symbol *s); + static void c_eval(); + + static void c_swap(); + + static void c_theentitypush(); + static void c_theentityassign(); + + static void c_repeatwhilecode(); + static void c_repeatwithcode(); + static void c_ifcode(); + static void c_whencode(); + static void c_exitRepeat(); + static void c_eq(); + static void c_neq(); + static void c_gt(); + static void c_lt(); + static void c_ge(); + static void c_le(); + static void c_call(); + + void call(Common::String &name, int nargs); + + static void c_procret(); + + static void c_mci(); + static void c_mciwait(); + static void c_goto(); + static void c_gotoloop(); + static void c_gotonext(); + static void c_gotoprevious(); + static void c_global(); + static void c_instance(); + + static void c_play(); + static void c_playdone(); + + static void c_open(); + + void printStubWithArglist(const char *funcname, int nargs); + void convertVOIDtoString(int arg, int nargs); + void dropStack(int nargs); + void drop(int num); + + static void b_abs(int nargs); + static void b_atan(int nargs); + static void b_cos(int nargs); + static void b_exp(int nargs); + static void b_float(int nargs); + static void b_integer(int nargs); + static void b_integerp(int nargs); + static void b_log(int nargs); + static void b_pi(int nargs); + static void b_power(int nargs); + static void b_random(int nargs); + static void b_sin(int nargs); + static void b_sqrt(int nargs); + static void b_tan(int nargs); + + static void b_chars(int nargs); + static void b_charToNum(int nargs); + static void b_length(int nargs); + static void b_numToChar(int nargs); + static void b_offset(int nargs); + static void b_string(int nargs); + static void b_stringp(int nargs); + + static void b_ilk(int nargs); + static void b_alert(int nargs); + static void b_cursor(int nargs); + static void b_objectp(int nargs); + static void b_printFrom(int nargs); + static void b_showGlobals(int nargs); + static void b_showLocals(int nargs); + static void b_symbolp(int nargs); + static void b_value(int nargs); + + static void b_constrainH(int nargs); + static void b_constrainV(int nargs); + static void b_editableText(int nargs); + static void b_installMenu(int nargs); + static void b_label(int nargs); + static void b_marker(int nargs); + static void b_moveableSprite(int nargs); + static void b_puppetPalette(int nargs); + static void b_puppetSound(int nargs); + static void b_puppetSprite(int nargs); + static void b_puppetTempo(int nargs); + static void b_puppetTransition(int nargs); + static void b_rollOver(int nargs); + static void b_spriteBox(int nargs); + static void b_updateStage(int nargs); + static void b_zoomBox(int nargs); + + static void b_continue(int nargs); + static void b_dontPassEvent(int nargs); + static void b_delay(int nargs); + static void b_do(int nargs); + static void b_nothing(int nargs); + static void b_pause(int nargs); + static void b_playAccel(int nargs); + static void b_quit(int nargs); + static void b_restart(int nargs); + static void b_shutDown(int nargs); + static void b_startTimer(int nargs); + + static void b_closeDA(int nargs); + static void b_closeResFile(int nargs); + static void b_closeXlib(int nargs); + static void b_openDA(int nargs); + static void b_openResFile(int nargs); + static void b_openXlib(int nargs); + static void b_showResFile(int nargs); + static void b_showXlib(int nargs); + + static void b_point(int nargs); + + static void b_beep(int nargs); + static void b_mci(int nargs); + static void b_mciwait(int nargs); + + static void b_backspace(int nargs); + static void b_empty(int nargs); + static void b_enter(int nargs); + static void b_false(int nargs); + static void b_quote(int nargs); + static void b_return(int nargs); + static void b_tab(int nargs); + static void b_true(int nargs); + + static void b_factory(int nargs); + void factoryCall(Common::String &name, int nargs); + + void func_mci(Common::String &s); + void func_mciwait(Common::String &s); + void func_goto(Datum &frame, Datum &movie); + void func_gotoloop(); + void func_gotonext(); + void func_gotoprevious(); + +public: + void setTheEntity(int entity, Datum &id, int field, Datum &d); + void setTheSprite(Datum &id, int field, Datum &d); + void setTheCast(Datum &id, int field, Datum &d); + Datum getTheEntity(int entity, Datum &id, int field); + Datum getTheSprite(Datum &id, int field); + Datum getTheCast(Datum &id, int field); + +public: + ScriptData *_currentScript; + ScriptType _currentScriptType; + bool _returning; + bool _indef; + + Common::Array<CFrame *> _callstack; + Common::Array<Common::String *> _argstack; + TheEntityHash _theEntities; + TheEntityFieldHash _theEntityFields; + Common::Array<int> _labelstack; + + SymbolHash _handlers; + + int _linenumber; + int _colnumber; + + Common::String _floatPrecisionFormat; + + bool _hadError; + + bool _inFactory; + Common::String _currentFactory; + + bool _exitRepeat; + +private: + int parse(const char *code); + void parseMenu(const char *code); + + void push(Datum d); + Datum pop(void); + + Common::HashMap<uint32, const char *> _eventHandlerTypes; + Common::HashMap<Common::String, Audio::AudioStream *> _audioAliases; + + ScriptHash _scripts[kMaxScriptType + 1]; + + SymbolHash _globalvars; + SymbolHash *_localvars; + + FuncHash _functions; + + int _pc; + + StackData _stack; + + DirectorEngine *_vm; + + int _floatPrecision; +}; + +extern Lingo *g_lingo; + +} // End of namespace Director + +#endif diff --git a/engines/director/lingo/tests/Lingo bytecode.html b/engines/director/lingo/tests/Lingo bytecode.html new file mode 100644 index 0000000000..1fcb4a31fc --- /dev/null +++ b/engines/director/lingo/tests/Lingo bytecode.html @@ -0,0 +1,2360 @@ +<!DOCTYPE html> +<!-- saved from url=(0054)http://fileformats.archiveteam.org/wiki/Lingo_bytecode --> +<html lang="en" dir="ltr" class="client-js gr__fileformats_archiveteam_org"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Lingo bytecode - Just Solve the File Format Problem</title> + +<meta name="generator" content="MediaWiki 1.19.2"> +<link rel="shortcut icon" href="http://fileformats.archiveteam.org/favicon.ico"> +<link rel="search" type="application/opensearchdescription+xml" href="http://fileformats.archiveteam.org/opensearch_desc.php" title="Just Solve the File Format Problem (en)"> +<link rel="EditURI" type="application/rsd+xml" href="http://fileformats.archiveteam.org/api.php?action=rsd"> +<link rel="copyright" href="http://creativecommons.org/publicdomain/zero/1.0/"> +<link rel="alternate" type="application/atom+xml" title="Just Solve the File Format Problem Atom feed" href="http://fileformats.archiveteam.org/index.php?title=Special:RecentChanges&feed=atom"> +<link rel="stylesheet" href="./Lingo bytecode - Just Solve the File Format Problem_files/load.php"> +<style type="text/css" media="all">.js-messagebox{margin:1em 5%;padding:0.5em 2.5%;border:1px solid #ccc;background-color:#fcfcfc;font-size:0.8em}.js-messagebox .js-messagebox-group{margin:1px;padding:0.5em 2.5%;border-bottom:1px solid #ddd}.js-messagebox .js-messagebox-group:last-child{border-bottom:thin none transparent} + +/* cache key: justsolve:resourceloader:filter:minify-css:7:8b08bdc91c52a9ffba396dccfb5b473c */ + + +.mw-collapsible-toggle{float:right} li .mw-collapsible-toggle{float:none} .mw-collapsible-toggle-li{list-style:none} + +/* cache key: justsolve:resourceloader:filter:minify-css:7:4250852ed2349a0d4d0fc6509a3e7d4c */ +</style><meta name="ResourceLoaderDynamicStyles" content=""> +<style>a:lang(ar),a:lang(ckb),a:lang(fa),a:lang(kk-arab),a:lang(mzn),a:lang(ps),a:lang(ur){text-decoration:none}a.new,#quickbar a.new{color:#ba0000} + +/* cache key: justsolve:resourceloader:filter:minify-css:7:c88e2bcd56513749bec09a7e29cb3ffa */ +</style> + +<script src="./Lingo bytecode - Just Solve the File Format Problem_files/load(1).php"></script><script src="./Lingo bytecode - Just Solve the File Format Problem_files/load(2).php"></script> +<script>if(window.mw){ +mw.config.set({"wgCanonicalNamespace":"","wgCanonicalSpecialPageName":false,"wgNamespaceNumber":0,"wgPageName":"Lingo_bytecode","wgTitle":"Lingo bytecode","wgCurRevisionId":25053,"wgArticleId":6263,"wgIsArticle":true,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":["File Formats","Electronic File Formats","Development","FormatInfo without extensions","FormatInfo without mimetypes"],"wgBreakFrames":false,"wgPageContentLanguage":"en","wgSeparatorTransformTable":["",""],"wgDigitTransformTable":["",""],"wgRelevantPageName":"Lingo_bytecode","wgRestrictionEdit":[],"wgRestrictionMove":[]}); +}</script><script>if(window.mw){ +mw.loader.implement("user.options",function($){mw.user.options.set({"ccmeonemails":0,"cols":80,"date":"default","diffonly":0,"disablemail":0,"disablesuggest":0,"editfont":"default","editondblclick":0,"editsection":1,"editsectiononrightclick":0,"enotifminoredits":0,"enotifrevealaddr":0,"enotifusertalkpages":1,"enotifwatchlistpages":0,"extendwatchlist":0,"externaldiff":0,"externaleditor":0,"fancysig":0,"forceeditsummary":0,"gender":"unknown","hideminor":0,"hidepatrolled":0,"highlightbroken":1,"imagesize":2,"justify":0,"math":1,"minordefault":0,"newpageshidepatrolled":0,"nocache":0,"noconvertlink":0,"norollbackdiff":0,"numberheadings":0,"previewonfirst":0,"previewontop":1,"quickbar":5,"rcdays":7,"rclimit":50,"rememberpassword":0,"rows":25,"searchlimit":20,"showhiddencats":0,"showjumplinks":1,"shownumberswatching":1,"showtoc":1,"showtoolbar":1,"skin":"vector","stubthreshold":0,"thumbsize":2,"underline":2,"uselivepreview":0,"usenewrc":0,"watchcreations":0,"watchdefault":0,"watchdeletion":0, +"watchlistdays":3,"watchlisthideanons":0,"watchlisthidebots":0,"watchlisthideliu":0,"watchlisthideminor":0,"watchlisthideown":0,"watchlisthidepatrolled":0,"watchmoves":0,"wllimit":250,"variant":"en","language":"en","searchNs0":true,"searchNs1":false,"searchNs2":false,"searchNs3":false,"searchNs4":false,"searchNs5":false,"searchNs6":false,"searchNs7":false,"searchNs8":false,"searchNs9":false,"searchNs10":false,"searchNs11":false,"searchNs12":false,"searchNs13":false,"searchNs14":false,"searchNs15":false});;},{},{});mw.loader.implement("user.tokens",function($){mw.user.tokens.set({"editToken":"+\\","watchToken":false});;},{},{}); + +/* cache key: justsolve:resourceloader:filter:minify-js:7:9983699ab6150ffa89a90653b2338ac8 */ +}</script> +<script>if(window.mw){ +mw.loader.load(["mediawiki.page.startup","mediawiki.legacy.wikibits","mediawiki.legacy.ajax"]); +}</script><script type="text/javascript" src="./Lingo bytecode - Just Solve the File Format Problem_files/load(3).php"></script> +<!--[if lt IE 7]><style type="text/css">body{behavior:url("/skins/vector/csshover.min.htc")}</style><![endif]--><meta name="chromesniffer" id="chromesniffer_meta" content="{"MediaWiki":-1,"jQuery":"1.7.1"}"><script type="text/javascript" src="chrome-extension://homgcnaoacgigpkkljjjekpignblkeae/detector.js"></script></head> +<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-Lingo_bytecode skin-vector action-view" data-gr-c-s-loaded="true"> + <div id="mw-page-base" class="noprint"></div> + <div id="mw-head-base" class="noprint"></div> + <!-- content --> + <div id="content" class="mw-body"> + <a id="top"></a> + <div id="mw-js-message" style="display:none;" class="js-messagebox"></div> + <!-- firstHeading --> + <h1 id="firstHeading" class="firstHeading"> + <span dir="auto">Lingo bytecode</span> + </h1> + <!-- /firstHeading --> + <!-- bodyContent --> + <div id="bodyContent"> + <!-- tagline --> + <div id="siteSub">From Just Solve the File Format Problem</div> + <!-- /tagline --> + <!-- subtitle --> + <div id="contentSub"></div> + <!-- /subtitle --> + <!-- jumpto --> + <div id="jump-to-nav" class="mw-jump"> + Jump to: <a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#mw-head">navigation</a>, + <a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#p-search">search</a> + </div> + <!-- /jumpto --> + <!-- bodycontent --> + <div id="mw-content-text" lang="en" dir="ltr" class="mw-content-ltr"><table class="infobox formatinfo" border="0" style="float: right; border: 1px solid #666666; max-width: 25%; overflow: hidden; background-color: #F8E0F7; padding: 0.25em; margin: 0.25em 1em;"> +<tbody><tr> +<th colspan="2"><a href="http://fileformats.archiveteam.org/wiki/File_Formats" title="File Formats">File Format</a></th> +</tr> + +<tr> +<th>Name</th> +<td>Lingo bytecode</td> +</tr> + + +<tr> +<th> Ontology +</th> +<td> +<ul><li> +<a href="http://fileformats.archiveteam.org/wiki/Electronic_File_Formats" title="Electronic File Formats">Electronic File Formats</a> +<ul><li> +<a href="http://fileformats.archiveteam.org/wiki/Development" title="Development">Development</a> +<ul><li> +<strong class="selflink">Lingo bytecode</strong> +</li></ul> +</li></ul> +</li></ul> +</td> +</tr> + + + +</tbody></table> +<p>This is a partial, work-in-progress examination of the bytecode created when Lingo code is compiled in Macromedia Director 4.0. It describes instructions for a stack-based virtual machine. This virtual machine is sometimes known as the IML, or Idealized Machine Layer. +</p><p>Each instruction is one, two or three bytes. +</p> +<ul><li> If the first byte is in the range 0x00-0x3F, then the full instruction is one byte. +</li><li> If the first byte is in the range 0x40-0x7F, then the full instruction is two bytes. +</li><li> If the first byte is in the range 0x80-0xFF, then the full instruction is three bytes. +</li></ul> +<p>Constant blobs like string literals are stored after the bytecode, and referred to by records that are six bytes long regardless of the actual length of the data. This means the first constant will be referred to as 0x00, the second constant as 0x06, the third as 0x0C, and so on. Integer literals over 32767 and floating-point number literals are also stored as constants. +</p><p>There is also a namelist for referring to external identifiers, stored separately from the bytecode. This is a simple array of strings. +</p> +<table id="toc" class="toc"><tbody><tr><td><div id="toctitle"><h2>Contents</h2><span class="toctoggle"> [<a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#" class="internal" id="togglelink">hide</a>] </span></div> +<ul> +<li class="toclevel-1 tocsection-1"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#One-Byte_Instructions"><span class="tocnumber">1</span> <span class="toctext">One-Byte Instructions</span></a></li> +<li class="toclevel-1 tocsection-2"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Two-Byte_Instructions"><span class="tocnumber">2</span> <span class="toctext">Two-Byte Instructions</span></a></li> +<li class="toclevel-1 tocsection-3"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Three_Byte_Instructions"><span class="tocnumber">3</span> <span class="toctext">Three Byte Instructions</span></a></li> +<li class="toclevel-1 tocsection-4"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Syntactic_Sugar"><span class="tocnumber">4</span> <span class="toctext">Syntactic Sugar</span></a></li> +<li class="toclevel-1 tocsection-5"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Lscr_bytecode-container_chunk_layout"><span class="tocnumber">5</span> <span class="toctext">Lscr bytecode-container chunk layout</span></a> +<ul> +<li class="toclevel-2 tocsection-6"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Header"><span class="tocnumber">5.1</span> <span class="toctext">Header</span></a></li> +<li class="toclevel-2 tocsection-7"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Function_Record"><span class="tocnumber">5.2</span> <span class="toctext">Function Record</span></a></li> +<li class="toclevel-2 tocsection-8"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Bytecode_Trailer"><span class="tocnumber">5.3</span> <span class="toctext">Bytecode Trailer</span></a></li> +<li class="toclevel-2 tocsection-9"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Constants"><span class="tocnumber">5.4</span> <span class="toctext">Constants</span></a></li> +</ul> +</li> +<li class="toclevel-1 tocsection-10"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Projector_File_.28Windows.29"><span class="tocnumber">6</span> <span class="toctext">Projector File (Windows)</span></a> +<ul> +<li class="toclevel-2 tocsection-11"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Director_3.0"><span class="tocnumber">6.1</span> <span class="toctext">Director 3.0</span></a></li> +<li class="toclevel-2 tocsection-12"><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#Director_4.0"><span class="tocnumber">6.2</span> <span class="toctext">Director 4.0</span></a></li> +</ul> +</li> +</ul> +</td></tr></tbody></table> +<h1> <span class="mw-headline" id="One-Byte_Instructions"> One-Byte Instructions </span></h1> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>exit</code> +</td> +<td> +</td> +<td> +</td> +<td> Leave the current function immediately and return to its caller. Automatically added as the final step of a function. +</td></tr> +<tr> +<th> 02 +</th></tr> +<tr> +<th> 03 +</th> +<td> +<p><code>0</code> +</p><p><code>FALSE</code> +</p> +</td> +<td> +</td> +<td> +1 +</td> +<td> +<p>Push zero onto the stack. +</p> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>(a * b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, multiply them together and push the result. +</td></tr> +<tr> +<th> 05 +</th> +<td> <code>(a + b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, add them together and push the result. +</td></tr> +<tr> +<th> 06 +</th> +<td> <code>(a - b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, subtract the second from the first and push the result. +</td></tr> +<tr> +<th> 07 +</th> +<td> <code>(a / b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, divide the first by the second and push the result. +</td></tr> +<tr> +<th> 08 +</th> +<td> <code>(a mod b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, perform a modulo operation and push the result. +</td></tr> +<tr> +<th> 09 +</th> +<td> <code>(-a)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Pop one value from the stack, negate it and push the result. +</td></tr> +<tr> +<th> 0A +</th> +<td> <code>(a & b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, concatenate them and push the resulting string. +</td></tr> +<tr> +<th> 0B +</th> +<td> <code>(a && b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, concatenate them with one space character added in between, and push the resulting string. +</td></tr> +<tr> +<th> 0C +</th> +<td> <code>(a < b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if the first is less than the second and 0 if not. +</td></tr> +<tr> +<th> 0D +</th> +<td> <code>(a <= b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if the first is less than or equal to the second and 0 if not. +</td></tr> +<tr> +<th> 0E +</th> +<td> <code>(a <> b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 0 if the two values are the same and 1 if they are not. +</td></tr> +<tr> +<th> 0F +</th> +<td> <code>(a = b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if the two values are the same and 0 if they are not. +</td></tr> +<tr> +<th> 10 +</th> +<td> <code>(a > b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if the first is greater than the second and 0 if not. +</td></tr> +<tr> +<th> 11 +</th> +<td> <code>(a >= b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if the first is greater than or equal to the sceond and 0 if not. +</td></tr> +<tr> +<th> 12 +</th> +<td> <code>(a and b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if both are logically true and 0 if not. +</td></tr> +<tr> +<th> 13 +</th> +<td> <code>(a or b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two values from the stack, push 1 if either are logically true and 0 if not. +</td></tr> +<tr> +<th> 14 +</th> +<td> <code>(not a)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Pop one value from the stack, push 0 if it is logically true and 1 if not. +</td></tr> +<tr> +<th> 15 +</th> +<td> <code>(a contains b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop two values from the stack, push 1 if the first is a string that contains the second and 0 if not. +</p><p>The text comparison is case-insensitive and ignores diacritic marks, e.g. "a" and "Ã…" are treated the same. +</p> +</td></tr> +<tr> +<th> 16 +</th> +<td> <code>(a starts b)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop two values from the stack, push 1 if the first is a string that begins with second string and 0 if not. +</p><p>The text comparison is case-insensitive and ignores diacritic marks, e.g. "a" and "Ã…" are treated the same. +</p> +</td></tr> +<tr> +<th> 17 +</th> +<td> <code>(char a of c)</code> +<p><code>(char a to b of c)</code> +</p><p><code>(item 1 to 3 of someItems)</code> +</p> +</td> +<td> -9 +</td> +<td> +1 +</td> +<td> String slice/split operation. It takes nine arguments from the stack: +<table class="wikitable"> + +<tbody><tr> +<th> -9 +</th> +<td> First char position +</td></tr> +<tr> +<th> -8 +</th> +<td> Last char position +</td></tr> +<tr> +<th> -7 +</th> +<td> First word position +</td></tr> +<tr> +<th> -6 +</th> +<td> Last word position +</td></tr> +<tr> +<th> -5 +</th> +<td> First item position <i>(items separated by</i> <code>the itemDelimiter</code><i>, which is a comma by default)</i> +</td></tr> +<tr> +<th> -4 +</th> +<td> Last item position +</td></tr> +<tr> +<th> -3 +</th> +<td> First line position +</td></tr> +<tr> +<th> -2 +</th> +<td> Last line position +</td></tr> +<tr> +<th> -1 +</th> +<td> The string to slice +</td></tr></tbody></table> +<p>The positions used here are one-based, so zero is invalid as a position and is instead used to indicate unused parameters. Only one "first X position" can be set, the rest must be zero. The corresponding "last X position" may either be set too, or it can be zero, in which case the first position will also be used as the last. +</p> +</td></tr> +<tr> +<th> 18 +</th> +<td> <code>hilite word 1 of field 10</code> +</td> +<td> -9 +</td> +<td> +</td> +<td> Highlight (select) some text. The nine arguments taken from the stack are: +<table class="wikitable"> + +<tbody><tr> +<th> -9 +</th> +<td> First char position +</td></tr> +<tr> +<th> -8 +</th> +<td> Last char position +</td></tr> +<tr> +<th> -7 +</th> +<td> First word position +</td></tr> +<tr> +<th> -6 +</th> +<td> Last word position +</td></tr> +<tr> +<th> -5 +</th> +<td> First item position +</td></tr> +<tr> +<th> -4 +</th> +<td> Last item position +</td></tr> +<tr> +<th> -3 +</th> +<td> First line position +</td></tr> +<tr> +<th> -2 +</th> +<td> Last line position +</td></tr> +<tr> +<th> -1 +</th> +<td> Field number (cast ID) +</td></tr></tbody></table> +<p>The positions used here are one-based, so zero is invalid as a position and is instead used to indicate unused parameters. Only one "first X position" can be set, the rest must be zero. The corresponding "last X position" may either be set too, or it can be zero, in which case the first position will also be used as the last. +</p> +</td></tr> +<tr> +<th> 19 +</th> +<td> <code>(sprite 1 intersects 2)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two sprite IDs and push 1 if the bounding rectangles of the two sprites touch at all, or 0 if they do not. +</td></tr> +<tr> +<th> 1A +</th> +<td> <code>(sprite 1 within 2)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> Pop two sprite IDs and push 1 if the bounding rectangle of the first is entirely inside the bounding rectangle of the second, or 0 if not. +</td></tr> +<tr> +<th> 1B +</th> +<td> <code>(field 1)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Pop a cast ID (name or number), push the value of that cast member's <code>text</code> property. +</td></tr> +<tr> +<th> 1C +</th> +<td> <code>tell someObject to go to frame 1</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> Pop an object from the stack and begin running subsequent bytecodes in the context of that object, until code 1D is encountered. +</td></tr> +<tr> +<th> 1D +</th> +<td> <code>tell someObject to go to frame 1</code> +</td> +<td> +</td> +<td> +</td> +<td> Marker for the end of a sequence of bytecodes started by 1C. Similar to 01 except for nested bytecode chunks instead of the main one. +</td></tr> +<tr> +<th> 1E +</th> +<td> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Some kind of list transformation or check, seen used just before setting the actorList to []. More research is needed to know exactly what is happening there. +</td></tr> +<tr> +<th> 1F +</th> +<td> <code>[#key: value]</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Pops a list that must be in the form [#symbol1, val1, #symbol2, val2 ...] to transform into [#symbol1: val1, #symbol2: val2 ...] +</td></tr></tbody></table> +<h1> <span class="mw-headline" id="Two-Byte_Instructions"> Two-Byte Instructions </span></h1> +<table class="wikitable"> + +<tbody><tr> +<th> 41 XX +</th> +<td> <code>1</code> .. <code>127</code> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push integer of value XX, which must be between 1 and 127, inclusive. To push zero, use 03. To push larger integers, use 81 XX YY. +</td></tr> +<tr> +<th> 42 XX +</th> +<td> <code>a, b, c</code> +</td> +<td> -XX +</td> +<td> +1 +</td> +<td> Pop the specified number of values off the top of the stack, create an unparenthesized argument list containing them (i.e. for a call statement like <code>myFunction 1, 2, 3</code>), and push that to the stack. +</td></tr> +<tr> +<th> 43 XX +</th> +<td> <code>[a, b, c]</code> +</td> +<td> -XX +</td> +<td> +1 +</td> +<td> Pop the specified number of values off the top of the stack, create a list for them (which can also be used for a parenthesized call expression like <code>set result = myFunction(1, 2, 3)</code>), and push that to the stack. +</td></tr> +<tr> +<th> 44 XX +</th> +<td> +<p><code>"literal"</code> +</p><p><code>0.5</code> +</p><p><code>32768</code> +</p> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push a constant from local constant records onto the stack. These records seem to be six bytes long (regardless of the actual size of the constant value), so pushing the first one is <code>44 00</code>, the second is <code>44 06</code>, the third is <code>44 0C</code>, etc. +</td></tr> +<tr> +<th> 45 XX +</th> +<td> <code>#symbol</code> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push a symbol with a name from namelist[XX]. Note that the name will be stored as "name", not "#name". +</td></tr> +<tr> +<th> 46 XX +</th></tr> +<tr> +<th> 47 XX +</th></tr> +<tr> +<th> 48 XX +</th></tr> +<tr> +<th> 49 XX +</th> +<td> +<p><code>(someGlobal)</code> +</p><p><i>where previously declared:</i> +</p><p><code>global someGlobal</code> +</p> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push the value of a global variable with a name from namelist[XX]. +</td></tr> +<tr> +<th> 4A XX +</th></tr> +<tr> +<th> 4B XX +</th> +<td> <code>(someParam)</code> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push the value of a function call parameter. The parameter records seem to be 6 bytes long, so the first is pushed with 4B 00, the second with 4B 06, etc. +</td></tr> +<tr> +<th> 4C XX +</th> +<td> <code>(someLocal)</code> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push the value of a local variable. The local variable records seem to be 6 bytes long, so the first is pushed with <code>4C 00</code>, the second with <code>4C 06</code>, etc. +</td></tr> +<tr> +<th> 4D XX +</th></tr> +<tr> +<th> 4E XX +</th></tr> + +<tr> +<th> 4F XX +</th> +<td> <code>set someGlobal = 0</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> Pop one value and use it to set the global variable with name from namelist[XX]. +</td></tr> +<tr> +<th> 50 XX +</th></tr> +<tr> +<th> 51 XX +</th></tr> +<tr> +<th> 52 XX +</th> +<td> <code>set someLocal = 0</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> Pop one value and use it to set a local variable. See code 4C 00 for a note about local variable records. +</td></tr> +<tr> +<th> 53 XX +</th></tr> +<tr> +<th> 54 XX +</th> +<td> <code>end repeat</code> +</td> +<td> +</td> +<td> +</td> +<td> Unconditional backwards jump by XX bytes, relative to the first byte of this instruction. +</td></tr> +<tr> +<th> 55 XX +</th></tr> +<tr> +<th> 56 XX +</th> +<td> <code>localFunction(1,2,3)</code> +</td> +<td> -1 +</td> +<td> +1 or +0 +</td> +<td> Call a function defined in this script with the name at namelist[XX]. The top value on the stack must be an argument list. If the argument list was created with code 43 XX, one return value will be pushed to the stack. If the argument list was created with code 42 XX, no return value will be pushed. +</td></tr> +<tr> +<th> 57 XX +</th> +<td> <code>someFunction 1,2,3</code> +<p><code>(someFunction(1,2,3))</code> +</p> +</td> +<td> -1 +</td> +<td> +1 OR +0 +</td> +<td> Call the external function with name from namelist[XX]. The top value on the stack must be an argument list. If the argument list was created with code 43 XX, one return value will be pushed to the stack. If the argument list was created with code 42 XX, no return value will be pushed. +</td></tr> +<tr> +<th> 58 XX +</th> +<td> <code>someObject(mSomeMethod, 1,2,3)</code> +</td> +<td> -2 +</td> +<td> +1 OR +0 +</td> +<td> Pop [argument list, call target] to make a method call. If the call target is a literal number, this indicates a local variable is the target. It must be divided by six to get the actual local variable number. The first argument of the argument list will be a symbol with the name of the method. Note: It is still unclear what difference the value of XX makes. It has been seen as 0x01 and 0x05. More research is needed to know more. (Possibly local variables vs. call parameters?) +</td></tr> +<tr> +<th> 59 16 +</th> +<td> <code>put "extra" into textVar</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> (Not sure how the target value is specified, needs more research) +</td></tr> +<tr> +<th> 59 25 +</th> +<td> <code>put "extra" after textVar</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> (See above) +</td></tr> +<tr> +<th> 59 35 +</th> +<td> <code>put "extra" before textVar</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> (See above) +</td></tr> +<tr> +<th> 5A XX +</th></tr> +<tr> +<th> 5B 05 +</th> +<td> <code>delete word 3 of textVar</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> (See above) +</td></tr> +<tr> +<th> 5C 00 +</th> +<td> +<p><code>(the abbr time)</code> +</p><p><code>(the short date)</code> +</p><p><code>(the last word in someText)</code> +</p> +</td> +<td> -1 OR -2 +</td> +<td> +1 +</td> +<td> +<p>If the top value is one of the following setting IDs, pop it from the stack, and push the current value of the setting: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 00 +</th> +<td> <code>the floatPrecision</code> +</td></tr> +<tr> +<th> 01 +</th> +<td> <code>the mouseDownScript</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>the mouseUpScript</code> +</td></tr> +<tr> +<th> 03 +</th> +<td> <code>the keyDownScript</code> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>the keyUpScript</code> +</td></tr> +<tr> +<th> 05 +</th> +<td> <code>the timeoutScript</code> +</td></tr></tbody></table> +<p>If the top value is a time-formatting ID, pop it from the stack, and push the current time formatted using it: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 06 +</th> +<td> <code>the short time</code> +</td> +<td> 1:09 AM +</td></tr> +<tr> +<th> 07 +</th> +<td> <code>the abbreviated time</code>, <code>the abbrev time</code>, <code>the abbr time</code> +</td> +<td> 1:09 AM +</td></tr> +<tr> +<th> 08 +</th> +<td> <code>the long time</code> +</td> +<td> 1:09:38 AM +</td></tr></tbody></table> +<p>If the top value is a date-formatting ID, pop it from the stack, and push the current date formatted using it: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 09 +</th> +<td> <code>the short date</code> +</td> +<td> 3/4/16 +</td></tr> +<tr> +<th> 0A +</th> +<td> <code>the abbreviated date</code>, <code>the abbrev date</code>, <code>the abbr date</code> +</td> +<td> Mon, Mar 14, 2016 +</td></tr> +<tr> +<th> 0B +</th> +<td> <code>the long date</code> +</td> +<td> Monday, March 14, 2016 +</td></tr></tbody></table> +<p>If the top value is a slice type ID, pop both it and the previous value from the stack. The previous value will be a string, slice the last "bit" of it according to the slice type, and push the sliced value: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 0C +</th> +<td> <code>the last char</code> +</td></tr> +<tr> +<th> 0D +</th> +<td> <code>the last word</code> +</td></tr> +<tr> +<th> 0E +</th> +<td> <code>the last item</code> +</td></tr> +<tr> +<th> 0F +</th> +<td> <code>the last line</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 01 +</th> +<td> <code>(the number of chars in someText)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [text, stat ID] and push the stat value for the given text, using these stat IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> chars +</td></tr> +<tr> +<th> 02 +</th> +<td> words +</td></tr> +<tr> +<th> 03 +</th> +<td> items <i>(separated by</i> <code>the itemDelimiter</code><i>, which is a comma by default)</i> +</td></tr> +<tr> +<th> 04 +</th> +<td> lines +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 02 +</th> +<td> <code>(the name of menu 1)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [menu ID, property ID] and push the value of the specified menu property, using these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>name</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>number of menuItems</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 03 +</th> +<td> <code>(the name of menuItem 3 of menu 1)</code> +</td> +<td> -3 +</td> +<td> +1 +</td> +<td> +<p>Pop [item ID, menu ID, property ID] and push the value of the specified menu item property, using these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>name</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>checkMark</code> +</td></tr> +<tr> +<th> 03 +</th> +<td> <code>enabled</code> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>script</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 04 +</th> +<td> <code>(the volume of sound 1)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [sound ID, property ID] and push the value of the specified sound property, using these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>volume</code> (0 to 255) +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 06 +</th> +<td> <code>(the cursor of sprite 3)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [sprite ID, property ID] and push the value of the specified sprite property, using these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>type</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>backColor</code> +</td></tr> +<tr> +<th> 03 +</th> +<td> <code>bottom</code> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>castNum</code> +</td></tr> +<tr> +<th> 05 +</th> +<td> <code>constraint</code> +</td></tr> +<tr> +<th> 06 +</th> +<td> <code>cursor</code> +</td></tr> +<tr> +<th> 07 +</th> +<td> <code>foreColor</code> +</td></tr> +<tr> +<th> 08 +</th> +<td> <code>height</code> +</td></tr> +<tr> +<th> 0A +</th> +<td> <code>ink</code> +</td></tr> +<tr> +<th> 0B +</th> +<td> <code>left</code> +</td></tr> +<tr> +<th> 0C +</th> +<td> <code>lineSize</code> +</td></tr> +<tr> +<th> 0D +</th> +<td> <code>locH</code> +</td></tr> +<tr> +<th> 0E +</th> +<td> <code>locV</code> +</td></tr> +<tr> +<th> 0F +</th> +<td> <code>movieRate</code> +</td></tr> +<tr> +<th> 10 +</th> +<td> <code>movieTime</code> +</td></tr> +<tr> +<th> 12 +</th> +<td> <code>puppet</code> +</td></tr> +<tr> +<th> 13 +</th> +<td> <code>right</code> +</td></tr> +<tr> +<th> 14 +</th> +<td> <code>startTime</code> +</td></tr> +<tr> +<th> 15 +</th> +<td> <code>stopTime</code> +</td></tr> +<tr> +<th> 16 +</th> +<td> <code>stretch</code> +</td></tr> +<tr> +<th> 17 +</th> +<td> <code>top</code> +</td></tr> +<tr> +<th> 18 +</th> +<td> <code>trails</code> +</td></tr> +<tr> +<th> 19 +</th> +<td> <code>visible</code> +</td></tr> +<tr> +<th> 1A +</th> +<td> <code>volume</code> (-256 to 256, <= 0 is silent) +</td></tr> +<tr> +<th> 1B +</th> +<td> <code>width</code> +</td></tr> +<tr> +<th> 1D +</th> +<td> <code>scriptNum</code> +</td></tr> +<tr> +<th> 1E +</th> +<td> <code>moveableSprite</code> +</td></tr> +<tr> +<th> 20 +</th> +<td> <code>scoreColor</code> +</td></tr></tbody></table> +<p>The values for <code>type</code> are: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 0 +</th> +<td> inactive +</td></tr> +<tr> +<th> 1 +</th> +<td> bitmap +</td></tr> +<tr> +<th> 2 +</th> +<td> rectangle +</td></tr> +<tr> +<th> 3 +</th> +<td> rounded rectangle +</td></tr> +<tr> +<th> 4 +</th> +<td> oval +</td></tr> +<tr> +<th> 5 +</th> +<td> line top-left to bottom-right +</td></tr> +<tr> +<th> 6 +</th> +<td> line bottom-left to top-right +</td></tr> +<tr> +<th> 7 +</th> +<td> text +</td></tr> +<tr> +<th> 8 +</th> +<td> button +</td></tr> +<tr> +<th> 9 +</th> +<td> checkbox +</td></tr> +<tr> +<th> 10 +</th> +<td> radio button +</td></tr> +<tr> +<th> 16 +</th> +<td> undetermined (try the castType of the associated cast member) +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 07 +</th> +<td> <code>(the exitLock)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> +<p>Pop a setting ID from the stack and push its value, using these setting IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>the beepOn</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>the buttonStyle</code> +</td></tr> +<tr> +<th> 03 +</th> +<td> <code>the centerStage</code> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>the checkBoxAccess</code> +</td></tr> +<tr> +<th> 05 +</th> +<td> <code>the checkBoxType</code> +</td></tr> +<tr> +<th> 06 +</th> +<td> <code>the colorDepth</code> +</td></tr> +<tr> +<th> 08 +</th> +<td> <code>the exitLock</code> +</td></tr> +<tr> +<th> 09 +</th> +<td> <code>the fixStageSize</code> +</td></tr> +<tr> +<th> 13 +</th> +<td> <code>the timeoutLapsed</code> +</td></tr> +<tr> +<th> 17 +</th> +<td> <code>the selEnd</code> +</td></tr> +<tr> +<th> 18 +</th> +<td> <code>the selStart</code> +</td></tr> +<tr> +<th> 19 +</th> +<td> <code>the soundEnabled</code> +</td></tr> +<tr> +<th> 1A +</th> +<td> <code>the soundLevel</code> +</td></tr> +<tr> +<th> 1B +</th> +<td> <code>the stageColor</code> +</td></tr> +<tr> +<th> 1D +</th> +<td> <code>the stillDown</code> +</td></tr> +<tr> +<th> 1E +</th> +<td> <code>the timeoutKeyDown</code> +</td></tr> +<tr> +<th> 1F +</th> +<td> <code>the timeoutLength</code> +</td></tr> +<tr> +<th> 20 +</th> +<td> <code>the timeoutMouse</code> +</td></tr> +<tr> +<th> 21 +</th> +<td> <code>the timeoutPlay</code> +</td></tr> +<tr> +<th> 22 +</th> +<td> <code>the timer</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 08 +</th> +<td> <code>(the number of castMembers)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> +<p>Pop a stat ID from the stack and push the stat, using these stat IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>the perFrameHook</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>number of castMembers</code> +</td></tr> +<tr> +<th> 03 +</th> +<td> <code>number of menus</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 09 +</th> +<td> +<p><code>(the picture of cast "bob")</code> +</p><p><code>(the name of cast 3)</code> +</p> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [cast ID, property ID] from the stack and push the value of the cast property, using these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>name</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>text</code> +</td></tr> +<tr> +<th> 08 +</th> +<td> <code>picture</code> +</td></tr> +<tr> +<th> 0A +</th> +<td> <code>number</code> +</td></tr> +<tr> +<th> 0B +</th> +<td> <code>size</code> +</td></tr> +<tr> +<th> 11 +</th> +<td> <code>foreColor</code> +</td></tr> +<tr> +<th> 12 +</th> +<td> <code>backColor</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 0C +</th> +<td> <code>(the textSize of field 1)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [field ID, property ID] and push the value of the property for the given field according to these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 03 +</th> +<td> <code>textStyle</code> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>textFont</code> +</td></tr> +<tr> +<th> 05 +</th> +<td> <code>textHeight</code> +</td></tr> +<tr> +<th> 06 +</th> +<td> <code>textAlign</code> +</td></tr> +<tr> +<th> 07 +</th> +<td> <code>textSize</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5C 0D +</th> +<td> <code>(the sound of cast 5)</code> +</td> +<td> -2 +</td> +<td> +1 +</td> +<td> +<p>Pop [cast ID, property ID] and push the value of property for the given cast according to these property IDs: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 10 +</th> +<td> <code>sound</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5D 00 +</th> +<td> <code>when keyDown then beep</code> +</td> +<td> -2 +</td> +<td> +</td> +<td> +<p>Pop [statement, eventID] and set the statement (Lingo source code in a text string) to run on the given event: +</p> +<table class="wikitable"> + +<tbody><tr> +<th> 01 +</th> +<td> <code>mouseDown</code> +</td></tr> +<tr> +<th> 02 +</th> +<td> <code>mouseUp</code> +</td></tr> +<tr> +<th> 03 +</th> +<td> <code>keyDown</code> +</td></tr> +<tr> +<th> 04 +</th> +<td> <code>keyUp</code> +</td></tr> +<tr> +<th> 05 +</th> +<td> <code>timeOut</code> +</td></tr></tbody></table> +</td></tr> +<tr> +<th> 5D 03 +</th> +<td> <code>set the enabled of menuItem 3 of menu 5 to FALSE</code> +</td> +<td> -4 +</td> +<td> +</td> +<td> Pop [menuItem ID, menu ID, new value, property ID] and set the menu item property. See the table for code 5C 03 for menu item property IDs. +</td></tr> +<tr> +<th> 5D 04 +</th> +<td> <code>set the volume of sound 3 to 255</code> +</td> +<td> -3 +</td> +<td> +</td> +<td> Pop [sound ID, new value, property ID] and set the menu item property. See the table for code 5C 04 for sound property IDs. +</td></tr> +<tr> +<th> 5D 06 +</th> +<td> <code>set the constraint of sprite 3 to 0</code> +</td> +<td> -3 +</td> +<td> +</td> +<td> Pop [sprite ID, new value, property ID] and set the sprite property. See the table for code 5C 06 for sprite property IDs. +</td></tr> +<tr> +<th> 5D 07 +</th> +<td> <code>set the exitLock to TRUE</code> +</td> +<td> -2 +</td> +<td> +</td> +<td> Pop [new value, setting ID] and change the relevant setting. See the table for code 5C 07 for setting IDs. +</td></tr> +<tr> +<th> 5D 09 +</th> +<td> <code>set the backColor of cast "bob" to 0</code> +</td> +<td> -3 +</td> +<td> +</td> +<td> Pop [cast ID, new value, property ID] and set the cast property. See the table for code 5C 09 for cast property IDs. +</td></tr> +<tr> +<th> 5D 0C +</th> +<td> <code>set the textAlign of field 3 to "right"</code> +</td> +<td> -3 +</td> +<td> +</td> +<td> Pop [field ID, new value, property ID] and set the field property. See the table for code 5C 0C for cast property IDs. +</td></tr> +<tr> +<th> 5D 0D +</th> +<td> <code>set the sound of cast 3 to TRUE</code> +</td> +<td> -3 +</td> +<td> +</td> +<td> Pop [cast ID, new value, property ID] and set the cast property. See the table for code 5C 0D for cast property IDs. +</td></tr> +<tr> +<th> 5E XX +</th></tr> +<tr> +<th> 5F XX +</th> +<td> <code>(the someProperty)</code> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push the value of the contextual property with the name at namelist[XX]. +</td></tr> +<tr> +<th> 60 XX +</th> +<td> <code>set the someProperty to 0</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> Pop a value and use it to set the contextual property with the name at namelist[XX]. +</td></tr> +<tr> +<th> 61 XX +</th> +<td> <code>(the someProperty of someVariable)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Pop a property-owning object from the stack, and push the value of this object's property with the name at namelist[XX]. +</td></tr> +<tr> +<th> 62 XX +</th> +<td> <code>set the someProperty of someVariable to 1</code> +</td> +<td> -2 +</td> +<td> +</td> +<td> Pop [property-owning object, new value] from the stack and set the property of the object with the name at namelist[XX]. +</td></tr> +<tr> +<th> 63 XX +</th> +<td> <code>tell someObject to go to frame 1</code> +</td> +<td> -1 +</td> +<td> +</td> +<td> Remote call: Similar to 57 XX except runs in the context of a <code>tell ... to</code> block. +</td></tr> +<tr> +<th> 64 XX +</th> +<td> +</td> +<td> +</td> +<td> +1 +</td> +<td> +<p>Push a copy of a value already on the stack, relative to the top where 00 is the top slot, 01 is one slot beneath the top, etc. +</p><p>This is used by the compiler when generating bytecode for the <code>repeat with i in list</code> block, to keep state in the loop without allocating new local variables. +</p> +</td></tr> +<tr> +<th> 65 XX +</th> +<td> +</td> +<td> -XX +</td> +<td> +</td> +<td> +<p>Pop and discard XX values from the top of the stack. +</p><p>This is used in the bytecode generated for a <code>repeat with i in list</code> block, to clean up at the end. +</p> +</td></tr> +<tr> +<th> 66 XX +</th> +<td> <code>(the pathName)</code> +</td> +<td> -1 +</td> +<td> +1 +</td> +<td> Pop an empty list and push the value of a read-only property named at namelist[XX]. +</td></tr></tbody></table> +<h1> <span class="mw-headline" id="Three_Byte_Instructions"> Three Byte Instructions </span></h1> +<table class="wikitable"> + +<tbody><tr> +<th> 81 XX YY +</th> +<td> <code>128</code> .. <code>32767</code> +</td> +<td> +</td> +<td> +1 +</td> +<td> Push the integer ((XX * 0x100) + YY). Larger integers and floats are pushed using constants. +</td></tr> +<tr> +<th> 82 XX YY +</th> +<td> <code>someFunc 1, 2, 3,</code> <i>(...)</i> <code>254, 255, 256, 257</code> +</td> +<td> -((XX * 0x100) + YY) +</td> +<td> +1 +</td> +<td> Pop ((XX * 0x100) + YY) values from the stack and push a no-return-value argument list object containing these values. Similar to code 42 XX, only necessary when there are more than 255 arguments in the list. +</td></tr> + +<tr> +<th> 83 XX YY +</th> +<td> <code>[1, 2, 3,</code> <i>(...)</i> <code>254, 255, 256, 257]</code> +</td> +<td> -((XX * 0x100) + YY) +</td> +<td> +1 +</td> +<td> Pop ((XX * 0x100) + YY) values from the stack and push a list object containing these values. Similar to code 43 XX, only necessary when there are more than 255 items in the list. +</td></tr> +<tr> +<th> 93 XX YY +</th> +<td> +<p><code>else</code> +</p><p><code>exit repeat</code> +</p><p><code>next repeat</code> +</p> +</td> +<td> +</td> +<td> +</td> +<td> Unconditional jump: Advance by ((XX * 0x100) + YY) bytes, relative to the first byte of this instruction (i.e. it may be 3 more than you are expecting) +<p>(<code>next repeat</code> jumps forward to <code>end repeat</code> instead of jumping back itself) +</p> +</td></tr> +<tr> +<th> 95 XX YY +</th> +<td> +<p><code>if somethingIsTrue then</code> +</p><p><code>repeat while somethingIsTrue</code> +</p> +</td> +<td> -1 +</td> +<td> +</td> +<td> Conditional jump: Pop a value, and if it is logically FALSE, advance by ((XX * 0x100) + YY) bytes, relative to the first byte of this instruction +</td></tr></tbody></table> +<h1> <span class="mw-headline" id="Syntactic_Sugar"> Syntactic Sugar </span></h1> +<p>Some functions get special syntax when written out in source code, but under the hood, the compiler just transforms it into more regular syntax. Here is a mapping that shows the equivalent in plain, generalized Lingo that gets used for the bytecode. +</p> +<table class="wikitable"> + +<tbody><tr> +<th> Specialized Syntax +</th> +<th> Generalized Syntax +</th></tr> +<tr> +<td><code>play frame 10 of movie "theMovie"</code> +</td> +<td><code>play 10, "theMovie"</code> +</td></tr> +<tr> +<td><code>play frame 10</code> +</td> +<td><code>play 10</code> +</td></tr> +<tr> +<td><code>play movie "theMovie"</code> +</td> +<td><code>play 1, "theMovie"</code> +</td></tr> +<tr> +<td><code>play done</code> +</td> +<td><code>play</code> +</td></tr> +<tr> +<td><pre>repeat with i = 15 to 20 + ... + +end repeat</pre> +</td> +<td><pre>set i = 15 +repeat while i <= 20 + ... + set i = i + 1 +end repeat</pre> +</td></tr> +<tr> +<td><pre>repeat with i = 15 down to 10 + ... + +end repeat</pre> +</td> +<td><pre>set i = 15 +repeat while i >= 10 + ... + set i = i - 1 +end repeat</pre> +</td></tr> +<tr> +<td><code>sound playFile 1, "Thunder"</code> +</td> +<td><code>sound #playFile, 1, "Thunder"</code> +</td></tr> +<tr> +<td><code>sound fadeIn 5</code> +</td> +<td><code>sound #fadeIn, 5</code> +</td></tr> +<tr> +<td><code>sound fadeIn 5, 10</code> +</td> +<td><code>sound #fadeIn, 5, 10</code> +</td></tr> +<tr> +<td><code>sound fadeOut 5</code> +</td> +<td><code>sound #fadeOut, 5</code> +</td></tr> +<tr> +<td><code>sound fadeOut 5, 10</code> +</td> +<td><code>sound #fadeOut, 5, 10</code> +</td></tr> +<tr> +<td><code>sound stop 1</code> +</td> +<td><code>sound #stop, 1</code> +</td></tr> +<tr> +<td><code>sound close 1</code> +</td> +<td><code>sound #close, 1</code> +</td></tr> +<tr> +<td><code>go to frame 10</code> +<p><code>go frame 10</code> +</p><p><code>go to 10</code> +</p> +</td> +<td><code>go 10</code> +</td></tr> +<tr> +<td><code>go to movie "theMovie"</code> +<p><code>go movie "theMovie"</code> +</p> +</td> +<td><code>go 1, "theMovie"</code> +</td></tr> +<tr> +<td><code>go to frame 10 of movie "theMovie"</code> +<p><code>go frame 10 of movie "theMovie"</code> +</p><p><code>go to 10 of movie "theMovie"</code> +</p><p><code>go 10 of movie "theMovie"</code> +</p> +</td> +<td><code>go 10, "theMovie"</code> +</td></tr> +<tr> +<td><code>go loop</code> +</td> +<td><code>go #loop</code> +</td></tr> +<tr> +<td><code>go next</code> +</td> +<td><code>go #next</code> +</td></tr> +<tr> +<td><code>go previous</code> +</td> +<td><code>go #previous</code> +</td></tr> +<tr> +<td><code>open "document" with "application"</code> +</td> +<td><code>open "document", "application"</code> +</td></tr> +<tr> +<td><code>set obj = GetObject()<br>obj(mSomeMethod, 1, 2, 3)</code> +</td> +<td><code>set obj = GetObject()<br>obj(#mSomeMethod, 1, 2, 3)</code> +</td></tr></tbody></table> +<h1> <span class="mw-headline" id="Lscr_bytecode-container_chunk_layout"> <code>Lscr</code> bytecode-container chunk layout </span></h1> +<h2> <span class="mw-headline" id="Header"> Header </span></h2> +<table class="wikitable"> + +<tbody><tr> +<td colspan="3">... +</td></tr> +<tr> +<th> $0040-$0041 +</th> +<td> uint16 +</td> +<td> Offset to the function records block +</td></tr> +<tr> +<td colspan="3">... +</td></tr> +<tr> +<th> $004E-$004F +</th> +<td> uint16 +</td> +<td> Number of constants +</td></tr> +<tr> +<td colspan="3">... +</td></tr> +<tr> +<th> $0048-$0049 +</th> +<td> uint16 +</td> +<td> Number of function records +</td></tr> +<tr> +<td colspan="3">... +</td></tr> +<tr> +<th> $0052-$0053 +</th> +<td> uint16 +</td> +<td> Offset to the constant records block +</td></tr> +<tr> +<td colspan="3">... +</td></tr> +<tr> +<th> $005A-$005B +</th> +<td> uint16 +</td> +<td> Base address for constant data +</td></tr></tbody></table> +<h2> <span class="mw-headline" id="Function_Record"> Function Record </span></h2> +<p>Each function record is 42 bytes long. +</p> +<table class="wikitable"> + +<tbody><tr> +<th> $0000-$0001 +</th> +<td> uint16 +</td> +<td> Namelist index for the function's name, or 0xFFFF if there is no name(?) +</td></tr> +<tr> +<th> $0002-$0003 +</th> +<td> uint16 +</td> +<td> Unknown +</td></tr> +<tr> +<th> $0004-$0007 +</th> +<td> uint32 +</td> +<td> Length of the function bytecode in bytes +</td></tr> +<tr> +<th> $0008-$000B +</th> +<td> uint32 +</td> +<td> Offset to the function bytecode +</td></tr> +<tr> +<th> $000C-$000D +</th> +<td> uint16 +</td> +<td> Number of arguments +</td></tr> +<tr> +<th> $000E-$0011 +</th> +<td> uint32 +</td> +<td> Unknown +</td></tr> +<tr> +<th> $0012-$0013 +</th> +<td> uint16 +</td> +<td> Number of local variables +</td></tr> +<tr> +<th> $0014-$0017 +</th> +<td> uint32 +</td> +<td> Unknown +</td></tr> +<tr> +<th> $0018-$0019 +</th> +<td> uint16 +</td> +<td> Count (C) +</td></tr> +<tr> +<th> $001A-$001D +</th> +<td> uint32 +</td> +<td> Unknown +</td></tr> +<tr> +<th> $001E-$0021 +</th> +<td> uint32 +</td> +<td> Unknown +</td></tr> +<tr> +<th> $0022-$0023 +</th> +<td> uint16 +</td> +<td> Unknown +</td></tr> +<tr> +<th> $0024-$0025 +</th> +<td> uint16 +</td> +<td> Count (D) +</td></tr> +<tr> +<th> $0026-$0029 +</th> +<td> uint32 +</td> +<td> Unknown +</td></tr></tbody></table> +<h2> <span class="mw-headline" id="Bytecode_Trailer"> Bytecode Trailer </span></h2> +<p>After the bytecode section for a function (determined using the offset and length fields from the function record), and then after an additional padding byte if there are an odd number of bytes in the bytecode, are the following values: +</p> +<ul><li> For each argument: uint16 namelist index for the argument's name +</li><li> For each local variable: uint16 namelist index for the variable's name +</li><li> Count (C) * uint16 +</li><li> Count (D) * uint8 +</li><li> A padding byte if Count (D) is an odd number +</li></ul> +<h2> <span class="mw-headline" id="Constants"> Constants </span></h2> +<p>Each constant record is six bytes long and has this format: +</p> +<ul><li> uint16: Value type ID +</li><li> uint32: Data address, relative to the base address given in the header +</li></ul> +<p>Here is how the value type IDs correspond to the data found at the given address: +</p> +<table class="wikitable"> +<tbody><tr> +<th> 01 +</th> +<td> Text string +</td> +<td> uint32 length (including null terminator) followed immediately by the character data +</td></tr> +<tr> +<th> 04 +</th> +<td> 32-bit unsigned integer +</td> +<td> "Data address" not an address, but the value itself +</td></tr> +<tr> +<th> 09 +</th> +<td> Floating point +</td> +<td> uint32 length followed by the floating point data. In practice, the length always seems to be 10, so the number is an 80-bit extended precision number. +</td></tr></tbody></table> +<h1> <span class="mw-headline" id="Projector_File_.28Windows.29"> Projector File (Windows) </span></h1> +<h2> <span class="mw-headline" id="Director_3.0"> Director 3.0 </span></h2> +<p>At the very end of the projector executable is a 32-bit little-endian file address. +</p><p>At this location is found: +</p> +<ul><li> 7 bytes: Not sure/more research needed +</li><li> uint32: Length of the RIFF block +</li><li> uint8: Length of the original RIFF file's name +</li><li> ASCII: Original RIFF file's name +</li><li> uint8: Length of the original RIFF file's parent folder +</li><li> ASCII: Original RIFF file's parent folder +</li><li> RIFF block +</li></ul> +<h2> <span class="mw-headline" id="Director_4.0"> Director 4.0 </span></h2> +<p>At the very end of the projector executable is a 32-bit little-endian file address. +</p><p>At this location is found: +</p> +<ul><li> ASCII "PJ93" +</li><li> The file address of the main RIFF data file +</li><li> Six further addresses for other embedded data (more research required to know more about these) +</li></ul> + +<!-- +NewPP limit report +Preprocessor node count: 196/1000000 +Post-expand include size: 1279/2097152 bytes +Template argument size: 338/2097152 bytes +Expensive parser function count: 0/100 +--> + +<!-- Saved in parser cache with key justsolve:pcache:idhash:6263-0!*!0!!en!*!* and timestamp 20160712223455 --> +</div> <!-- /bodycontent --> + <!-- printfooter --> + <div class="printfooter"> + Retrieved from "<a href="http://fileformats.archiveteam.org/index.php?title=Lingo_bytecode&oldid=25053">http://fileformats.archiveteam.org/index.php?title=Lingo_bytecode&oldid=25053</a>" </div> + <!-- /printfooter --> + <!-- catlinks --> + <div id="catlinks" class="catlinks"><div id="mw-normal-catlinks" class="mw-normal-catlinks"><a href="http://fileformats.archiveteam.org/wiki/Special:Categories" title="Special:Categories">Categories</a>: <ul><li><a href="http://fileformats.archiveteam.org/wiki/Category:File_Formats" title="Category:File Formats">File Formats</a></li><li><a href="http://fileformats.archiveteam.org/wiki/Category:Electronic_File_Formats" title="Category:Electronic File Formats">Electronic File Formats</a></li><li><a href="http://fileformats.archiveteam.org/wiki/Category:Development" title="Category:Development">Development</a></li></ul></div><div id="mw-hidden-catlinks" class="mw-hidden-catlinks mw-hidden-cats-hidden">Hidden categories: <ul><li><a href="http://fileformats.archiveteam.org/wiki/Category:FormatInfo_without_extensions" title="Category:FormatInfo without extensions">FormatInfo without extensions</a></li><li><a href="http://fileformats.archiveteam.org/wiki/Category:FormatInfo_without_mimetypes" title="Category:FormatInfo without mimetypes">FormatInfo without mimetypes</a></li></ul></div></div> <!-- /catlinks --> + <div class="visualClear"></div> + <!-- debughtml --> + <!-- /debughtml --> + </div> + <!-- /bodyContent --> + </div> + <!-- /content --> + <!-- header --> + <div id="mw-head" class="noprint"> + +<!-- 0 --> +<div id="p-personal" class=""> + <h5>Personal tools</h5> + <ul> + <li id="pt-login"><a href="http://fileformats.archiveteam.org/index.php?title=Special:UserLogin&returnto=Lingo+bytecode" title="You are encouraged to log in; however, it is not mandatory [ctrl-option-o]" accesskey="o">Log in / create account</a></li> + </ul> +</div> + +<!-- /0 --> + <div id="left-navigation"> + +<!-- 0 --> +<div id="p-namespaces" class="vectorTabs"> + <h5>Namespaces</h5> + <ul> + <li id="ca-nstab-main" class="selected"><span><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode" title="View the content page [ctrl-option-c]" accesskey="c">Page</a></span></li> + <li id="ca-talk" class="new"><span><a href="http://fileformats.archiveteam.org/index.php?title=Talk:Lingo_bytecode&action=edit&redlink=1" title="Discussion about the content page [ctrl-option-t]" accesskey="t">Discussion</a></span></li> + </ul> +</div> + +<!-- /0 --> + +<!-- 1 --> +<div id="p-variants" class="vectorMenu emptyPortlet"> + <h4> + </h4> + <h5><span>Variants</span><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#"></a></h5> + <div class="menu"> + <ul> + </ul> + </div> +</div> + +<!-- /1 --> + </div> + <div id="right-navigation"> + +<!-- 0 --> +<div id="p-views" class="vectorTabs"> + <h5>Views</h5> + <ul> + <li id="ca-view" class="selected"><span><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode">Read</a></span></li> + <li id="ca-viewsource"><span><a href="http://fileformats.archiveteam.org/index.php?title=Lingo_bytecode&action=edit" title="This page is protected. +You can view its source [ctrl-option-e]" accesskey="e">View source</a></span></li> + <li id="ca-history" class="collapsible"><span><a href="http://fileformats.archiveteam.org/index.php?title=Lingo_bytecode&action=history" title="Past revisions of this page [ctrl-option-h]" accesskey="h">View history</a></span></li> + </ul> +</div> + +<!-- /0 --> + +<!-- 1 --> +<div id="p-cactions" class="vectorMenu emptyPortlet"> + <h5><span>Actions</span><a href="http://fileformats.archiveteam.org/wiki/Lingo_bytecode#"></a></h5> + <div class="menu"> + <ul> + </ul> + </div> +</div> + +<!-- /1 --> + +<!-- 2 --> +<div id="p-search"> + <h5><label for="searchInput">Search</label></h5> + <form action="http://fileformats.archiveteam.org/index.php" id="searchform"> + <div> + <input type="search" name="search" title="Search Just Solve the File Format Problem [ctrl-option-f]" accesskey="f" id="searchInput"> <input type="submit" name="go" value="Go" title="Go to a page with this exact name if exists" id="searchGoButton" class="searchButton"> <input type="submit" name="fulltext" value="Search" title="Search the pages for this text" id="mw-searchButton" class="searchButton"> <input type="hidden" name="title" value="Special:Search"> + </div> + </form> +</div> + +<!-- /2 --> + </div> + </div> + <!-- /header --> + <!-- panel --> + <div id="mw-panel" class="noprint"> + <!-- logo --> + <div id="p-logo"><a style="background-image: url(/thumbsup.png);" href="http://fileformats.archiveteam.org/wiki/Main_Page" title="Visit the main page"></a></div> + <!-- /logo --> + +<!-- navigation --> +<div class="portal" id="p-navigation"> + <h5>Navigation</h5> + <div class="body"> + <ul> + <li id="n-mainpage-description"><a href="http://fileformats.archiveteam.org/wiki/Main_Page" title="Visit the main page [ctrl-option-z]" accesskey="z">Main page</a></li> + <li id="n-File-formats"><a href="http://fileformats.archiveteam.org/wiki/File_Formats">File formats</a></li> + <li id="n-Formats-by-extension"><a href="http://fileformats.archiveteam.org/wiki/Category:File_formats_by_extension">Formats by extension</a></li> + <li id="n-Still-more-extensions"><a href="http://fileformats.archiveteam.org/wiki/Category:File_Format_Extension">Still more extensions</a></li> + <li id="n-Software"><a href="http://fileformats.archiveteam.org/wiki/Software">Software</a></li> + <li id="n-Glossary"><a href="http://fileformats.archiveteam.org/wiki/Glossary">Glossary</a></li> + <li id="n-Library"><a href="http://fileformats.archiveteam.org/wiki/Library">Library</a></li> + <li id="n-Sources"><a href="http://fileformats.archiveteam.org/wiki/Sources">Sources</a></li> + <li id="n-Categories"><a href="http://fileformats.archiveteam.org/wiki/Category:Top_Level_Categories">Categories</a></li> + <li id="n-portal"><a href="http://fileformats.archiveteam.org/wiki/Just_Solve_the_File_Format_Problem:Community_portal" title="About the project, what you can do, where to find things">Community portal</a></li> + <li id="n-recentchanges"><a href="http://fileformats.archiveteam.org/wiki/Special:RecentChanges" title="A list of recent changes in the wiki [ctrl-option-r]" accesskey="r">Recent changes</a></li> + <li id="n-randompage"><a href="http://fileformats.archiveteam.org/wiki/Special:Random" title="Load a random page [ctrl-option-x]" accesskey="x">Random page</a></li> + </ul> + </div> +</div> + +<!-- /navigation --> + +<!-- SEARCH --> + +<!-- /SEARCH --> + +<!-- TOOLBOX --> +<div class="portal" id="p-tb"> + <h5>Toolbox</h5> + <div class="body"> + <ul> + <li id="t-whatlinkshere"><a href="http://fileformats.archiveteam.org/wiki/Special:WhatLinksHere/Lingo_bytecode" title="A list of all wiki pages that link here [ctrl-option-j]" accesskey="j">What links here</a></li> + <li id="t-recentchangeslinked"><a href="http://fileformats.archiveteam.org/wiki/Special:RecentChangesLinked/Lingo_bytecode" title="Recent changes in pages linked from this page [ctrl-option-k]" accesskey="k">Related changes</a></li> + <li id="t-specialpages"><a href="http://fileformats.archiveteam.org/wiki/Special:SpecialPages" title="A list of all special pages [ctrl-option-q]" accesskey="q">Special pages</a></li> + <li><a href="http://fileformats.archiveteam.org/index.php?title=Lingo_bytecode&printable=yes" rel="alternate">Printable version</a></li> + <li id="t-permalink"><a href="http://fileformats.archiveteam.org/index.php?title=Lingo_bytecode&oldid=25053" title="Permanent link to this revision of the page">Permanent link</a></li> + </ul> + </div> +</div> + +<!-- /TOOLBOX --> + +<!-- LANGUAGES --> + +<!-- /LANGUAGES --> + </div> + <!-- /panel --> + <!-- footer --> + <div id="footer"> + <ul id="footer-info"> + <li id="footer-info-lastmod"> This page was last modified on 17 March 2016, at 18:25.</li> + <li id="footer-info-viewcount">This page has been accessed 586 times.</li> + <li id="footer-info-copyright">Content is available under <a class="external" href="http://creativecommons.org/publicdomain/zero/1.0/">Creative Commons 0</a>.</li> + </ul> + <ul id="footer-places"> + <li id="footer-places-privacy"><a href="http://fileformats.archiveteam.org/wiki/Just_Solve_the_File_Format_Problem:Privacy_policy" title="Just Solve the File Format Problem:Privacy policy">Privacy policy</a></li> + <li id="footer-places-about"><a href="http://fileformats.archiveteam.org/wiki/Just_Solve_the_File_Format_Problem:About" title="Just Solve the File Format Problem:About">About Just Solve the File Format Problem</a></li> + <li id="footer-places-disclaimer"><a href="http://fileformats.archiveteam.org/wiki/Just_Solve_the_File_Format_Problem:General_disclaimer" title="Just Solve the File Format Problem:General disclaimer">Disclaimers</a></li> + </ul> + <ul id="footer-icons" class="noprint"> + <li id="footer-copyrightico"> + <a href="http://creativecommons.org/publicdomain/zero/1.0/"><img src="./Lingo bytecode - Just Solve the File Format Problem_files/cc-0.png" alt="Creative Commons 0" width="88" height="31"></a> + </li> + <li id="footer-poweredbyico"> + <a href="http://www.mediawiki.org/"><img src="./Lingo bytecode - Just Solve the File Format Problem_files/poweredby_mediawiki_88x31.png" alt="Powered by MediaWiki" width="88" height="31"></a> + </li> + </ul> + <div style="clear:both"></div> + </div> + <!-- /footer --> + <script src="./Lingo bytecode - Just Solve the File Format Problem_files/load(4).php"></script> +<script>if(window.mw){ +mw.loader.load(["mediawiki.user","mediawiki.page.ready"], null, true); +}</script><script src="./Lingo bytecode - Just Solve the File Format Problem_files/load(5).php" type="text/javascript"></script> +<!-- Served in 0.102 secs. --> + + +<script type="text/javascript" src="chrome-extension://cmjeonfdjdekpggjkoknhhkcifnaichh/src/rules.js"></script><script type="text/javascript" src="chrome-extension://cmjeonfdjdekpggjkoknhhkcifnaichh/src/inject.js"></script></body><span class="gr__tooltip"><span class="gr__tooltip-content"></span><i class="gr__tooltip-logo"></i><span class="gr__triangle"></span></span></html>
\ No newline at end of file diff --git a/engines/director/lingo/tests/builtin.lingo b/engines/director/lingo/tests/builtin.lingo new file mode 100644 index 0000000000..351efdb12c --- /dev/null +++ b/engines/director/lingo/tests/builtin.lingo @@ -0,0 +1,24 @@ +beep +beep 3 +alert "Hi" +alert "Hi" && "there" + +open "Hello" +open "Hello" with "Finder" +open "Hello" && "more" with "Finder" + +puppetPalette "Rainbow" +puppetPalette "System",30 +puppetPalette "custompal", 15,4 + +puppetSound "Air Lock Lock" +puppetSound 0 +puppetSound midiStart +puppetSound midiSong, 3 +puppetSound midisongPointer, 2, 120 + +puppetSprite 15, true + +puppetTempo 30 +puppetTransition 1 +puppetTransition 2,4,20 diff --git a/engines/director/lingo/tests/factory.lingo b/engines/director/lingo/tests/factory.lingo new file mode 100644 index 0000000000..388d2c3a51 --- /dev/null +++ b/engines/director/lingo/tests/factory.lingo @@ -0,0 +1,69 @@ +-- +macro AimGun2 +global aim1 +set aim1 = aim2(mNew) +-- +factory aim2 +method mNew + dontpassevent + global aim1 + when mousedown then aim1(fire) + when keydown then aim1(mExit) + set the locv of sprite 24 to 540 +method mMove x, y + set the locH of sprite 15 to x + set the locV of sprite 15 to y-250 +method mAtFrame + dontpassevent + me(mMove, the mouseH, the mouseV) +method fire + global fire1, targeth, targetv + set fire1 = fire2(mNew) + set the perframehook to fire1 + me(mDispose) +method mExit + set the perframehook to false + postfire + me(mDispose) +method mDispose + global aim1 + set aim1 = 1 + when keydown then nothing +-- +factory fire2 +method mNew + dontpassevent + when mousedown then nothing + set the castnum of sprite 14 to f15 +method mAtFrame + Global StartH, StartV, targetv, stepH, stepV, bcast + dontpassevent + set the castnum of sprite 14 to bcast + set the LocV of sprite 14 to (startV-stepV) + if sprite 14 intersects 10 and (startV-6) <= targetV then + set the castnum of sprite 14 to f16 + set the perframehook to false + me(hit) + exit + end if + if startV < targetV or bcast>g17 then + set the perframehook to false + set the locV of sprite 14 to 340 + aimgun2 + exit + end if + set startV to (startV-stepV) + set bcast = bcast + 1 +method hit + global KillLoc + set killloc to the loch of sprite 3 + go "Death" + set the locV of sprite 14 to 400 + aimgun2 +method mDispose + global fire1 + set fire1 = 0 +-- +macro KillIt2 +global KillLoc +set the locH of sprite 3 to KillLoc diff --git a/engines/director/lingo/tests/factory2.lingo b/engines/director/lingo/tests/factory2.lingo new file mode 100644 index 0000000000..a7b2317e17 --- /dev/null +++ b/engines/director/lingo/tests/factory2.lingo @@ -0,0 +1,4 @@ +global aim1 +AimGun2 + +aim1(mDispose) diff --git a/engines/director/lingo/tests/goto.lingo b/engines/director/lingo/tests/goto.lingo new file mode 100644 index 0000000000..854506e260 --- /dev/null +++ b/engines/director/lingo/tests/goto.lingo @@ -0,0 +1,26 @@ +go to frame "Open23" of movie "OpenCabin23" +go "CARDBACK" +go movie "BAR 1" +go to "Open23" of movie "OpenCabin23" +go to "Chair" + +set varframe to "VARFrame" +set varmovie to "VARMovie" + +go to frame 35 +go "label two" +go to movie "Chicago" +go to frame 23 of movie "Chicago" +go to frame "main loop" of movie "Basic With" +play frame varFrame of movie varMovie +go to marker(1) + +play frame 37 +play frame "label one" +play movie "Desert Scene" +play frame 23 of movie "Chicago" +play frame varframe of movie varmovie +play frame "main loop" of movie "Basic With" + +playAccel "Lungs.mma" +playAccel "Bolitas.mma", loop, clickStop, whatFits diff --git a/engines/director/lingo/tests/if.lingo b/engines/director/lingo/tests/if.lingo new file mode 100644 index 0000000000..8f1e2391e6 --- /dev/null +++ b/engines/director/lingo/tests/if.lingo @@ -0,0 +1,27 @@ +-- +set x = 1 +if x = 5 then exit +else put 10.0 + +repeat with x = 1 to 6 + if x = 3 then put 30 + else if x = 4 then put 40 + else if x = 5 then put 50 + else put 10.0 + if x = 1 then + put 1 + else if x = 2 then + put 1232.12345678901234 + put 2.2 + else if x = 3 then + put 3 + else if x = 4 then + put 4 + else if x = 5 then + put 5 + else if x = 6 then + put 6 + end if + if x = 4 then put 40 + else put 50 +end repeat diff --git a/engines/director/lingo/tests/ilk.lingo b/engines/director/lingo/tests/ilk.lingo new file mode 100644 index 0000000000..686d9a5118 --- /dev/null +++ b/engines/director/lingo/tests/ilk.lingo @@ -0,0 +1,7 @@ +put ilk(10) +put ilk(20.0) +put ilk("Macromedia") +put ilk(point(10, 20)) +put ilk(ilk(10)) +set x = point(10, 20) +put ilk(x) diff --git a/engines/director/lingo/tests/lingotests.lingo b/engines/director/lingo/tests/lingotests.lingo new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/engines/director/lingo/tests/lingotests.lingo diff --git a/engines/director/lingo/tests/loops.lingo b/engines/director/lingo/tests/loops.lingo new file mode 100644 index 0000000000..e4c5ccefc5 --- /dev/null +++ b/engines/director/lingo/tests/loops.lingo @@ -0,0 +1,22 @@ +set x = 5 +if x <= 5 then set x = 6 +if (x = 5) then +set x = 7 -- this is comment +else +set x = 8 +-- this is another comment +end if +put x +-- this is more comment +set y = 1 +repeat while (y < 5) +set y = y + 1 +put y +end repeat + +repeat with z = 10 to 15 +put z +end repeat +repeat with y = 5 down to 1 +put y +end repeat diff --git a/engines/director/lingo/tests/macros.lingo b/engines/director/lingo/tests/macros.lingo new file mode 100644 index 0000000000..7ffa557cb7 --- /dev/null +++ b/engines/director/lingo/tests/macros.lingo @@ -0,0 +1,42 @@ +-- +macro SHIPX +global x, y +set x = Random(5) +if x = 1 then +go "Zoom" +exit +end if +if x >1 then +set y = 10 +exit +end if +put 100 + +-- +macro ZIPX +set x = Random(5) +if x = 1 then +go "ZIP" +exit +end if +if x >1 then +put x +exit +end if + +-- +macro check par1, par2 +, par3 +if par1 = 3 then +put -3 +else +put 0 +end if +if par2 = 2 then +put 2 +else +put 0 +end if +put par1 +put par2 +put par3 diff --git a/engines/director/lingo/tests/macros2.lingo b/engines/director/lingo/tests/macros2.lingo new file mode 100644 index 0000000000..b587ae421c --- /dev/null +++ b/engines/director/lingo/tests/macros2.lingo @@ -0,0 +1,11 @@ +check(2, 3) +global x, y +set y = 8 +shipx +put x +zipx +put x +put y +check(1, 2, 3) +check 4, 5, 6 +check 7, 8 diff --git a/engines/director/lingo/tests/math.lingo b/engines/director/lingo/tests/math.lingo new file mode 100644 index 0000000000..f38b061b6a --- /dev/null +++ b/engines/director/lingo/tests/math.lingo @@ -0,0 +1,24 @@ +if random(4) > 2 then put 1000 +set z = 5.5 +set z1 = 2 +set z2 = z / z1 +put z +put z1 +put z2 +put integer(z2) +put cos(z2) + +set x = 2 + 3 * (4 / 2) +put x + +put power(2, 8) +put power(2, 8, 0) +put power(2) +updatestage + +-- Type conversion +put (1024/4096)*100 -- 0 +put (1024/4096)*100.0 -- 0.0 +put ((1024*1.0)/4096)*100.0 -- 25.0 + +put the sqrt of 9 diff --git a/engines/director/lingo/tests/mci.lingo b/engines/director/lingo/tests/mci.lingo new file mode 100644 index 0000000000..04130bf907 --- /dev/null +++ b/engines/director/lingo/tests/mci.lingo @@ -0,0 +1,2 @@ +mci "open MM\T005045a.wav type WaveAudio alias T005045a" +mci "play T005045a from 22710 to 32872" diff --git a/engines/director/lingo/tests/point.lingo b/engines/director/lingo/tests/point.lingo new file mode 100644 index 0000000000..4e90ddb684 --- /dev/null +++ b/engines/director/lingo/tests/point.lingo @@ -0,0 +1,3 @@ +put point(10, 20) +set x = point(20,30) +put x diff --git a/engines/director/lingo/tests/strings.lingo b/engines/director/lingo/tests/strings.lingo new file mode 100644 index 0000000000..568eb74640 --- /dev/null +++ b/engines/director/lingo/tests/strings.lingo @@ -0,0 +1,13 @@ +set z = "foo bar baz" +set z1 = z & " meow" +set z1 = z1 && "woof" +put z +put z1 +put chars("Macromedia", 6, 6) +put chars("Macromedia", 6, 10) +put chars("Macromedia", -1, 15) +if z1 contains "MeÍW" then + put "Contains" +else + put "Doesn't contain" +end if diff --git a/engines/director/lingo/tests/the.lingo b/engines/director/lingo/tests/the.lingo new file mode 100644 index 0000000000..65c0d6ea5c --- /dev/null +++ b/engines/director/lingo/tests/the.lingo @@ -0,0 +1,6 @@ +put 1.0 / 3 +set the floatPrecision to 6 +put 1.0 / 3 +put the loch of sprite 4 +set the loch of sprite 5 to 10 +set the castnum of sprite 8 to the number of cast "A Blank Castmember" diff --git a/engines/director/module.mk b/engines/director/module.mk new file mode 100644 index 0000000000..c37e9d9b9b --- /dev/null +++ b/engines/director/module.mk @@ -0,0 +1,33 @@ +MODULE := engines/director + +MODULE_OBJS = \ + detection.o \ + director.o \ + frame.o \ + images.o \ + movie.o \ + resource.o \ + score.o \ + sound.o \ + sprite.o \ + lingo/lingo-gr.o \ + lingo/lingo.o \ + lingo/lingo-builtins.o \ + lingo/lingo-code.o \ + lingo/lingo-codegen.o \ + lingo/lingo-funcs.o \ + lingo/lingo-lex.o \ + lingo/lingo-the.o + +director-grammar: + flex -o engines/director/lingo/lingo-lex.cpp engines/director/lingo/lingo-lex.l + bison -dv -o engines/director/lingo/lingo-gr.cpp engines/director/lingo/lingo-gr.y + mv engines/director/lingo/lingo-gr.hpp engines/director/lingo/lingo-gr.h + +# This module can be built as a plugin +ifeq ($(ENABLE_DIRECTOR), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp new file mode 100644 index 0000000000..fef2b57ff3 --- /dev/null +++ b/engines/director/movie.cpp @@ -0,0 +1,67 @@ +/* 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. + * + * Additional copyright for this file: + * Copyright (C) 1995-1997 Presto Studios, Inc. + * + * 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/system.h" +#include "video/qt_decoder.h" + +#include "director/movie.h" +#include "director/score.h" + +namespace Director { + +Movie::Movie(Common::String fileName, DirectorEngine *vm) { + _vm = vm; + _currentVideo = new Video::QuickTimeDecoder(); + if (!_currentVideo->loadFile(fileName)) { + warning("Can not open file %s", fileName.c_str()); + return; + } +} + +void Movie::play(Common::Point dest) { + + _currentVideo->start(); + + uint16 width = _currentVideo->getWidth(); + uint16 height = _currentVideo->getHeight(); + + while (!_currentVideo->endOfVideo()) { + if (_currentVideo->needsUpdate()) { + const Graphics::Surface *frame = _currentVideo->decodeNextFrame(); + g_system->copyRectToScreen(frame->getPixels(), frame->pitch, dest.x, dest.y, width, height); + g_system->updateScreen(); + } + g_system->delayMillis(10); + _vm->getCurrentScore()->processEvents(); + } +} + +void Movie::stop() { + _currentVideo->stop(); +} + +Movie::~Movie() { + delete _currentVideo; +} + +} //End of namespace Director diff --git a/engines/director/movie.h b/engines/director/movie.h new file mode 100644 index 0000000000..84bc116134 --- /dev/null +++ b/engines/director/movie.h @@ -0,0 +1,50 @@ +/* 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. + * + * Additional copyright for this file: + * Copyright (C) 1995-1997 Presto Studios, Inc. + * + * 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 DIRECTOR_MOVIE_H +#define DIRECTOR_MOVIE_H + +#include "graphics/managed_surface.h" + +#include "director/director.h" + +namespace Video { +class VideoDecoder; +} + +namespace Director { + +class Movie { +public: + Movie(Common::String fileName, DirectorEngine *vm); + ~Movie(); + void play(Common::Point dest); + void stop(); + +private: + Video::VideoDecoder *_currentVideo; + DirectorEngine *_vm; +}; +} //End of namespace Director + +#endif diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp new file mode 100644 index 0000000000..787becf28c --- /dev/null +++ b/engines/director/resource.cpp @@ -0,0 +1,441 @@ +/* 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 "director/resource.h" + +#include "common/debug.h" +#include "common/macresman.h" + +namespace Director { + +// Base Archive code + +Archive::Archive() { + _stream = 0; + _isBigEndian = true; +} + +Archive::~Archive() { + close(); +} + +bool Archive::openFile(const Common::String &fileName) { + Common::File *file = new Common::File(); + + if (!file->open(fileName)) { + delete file; + return false; + } + + if (!openStream(file)) { + close(); + return false; + } + + return true; +} + +void Archive::close() { + _types.clear(); + + if (_stream) + delete _stream; + + _stream = 0; +} + +bool Archive::hasResource(uint32 tag, uint16 id) const { + if (!_types.contains(tag)) + return false; + + return _types[tag].contains(id); +} + +bool Archive::hasResource(uint32 tag, const Common::String &resName) const { + if (!_types.contains(tag) || resName.empty()) + return false; + + const ResourceMap &resMap = _types[tag]; + + for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++) + if (it->_value.name.matchString(resName)) + return true; + + return false; +} + +Common::SeekableSubReadStreamEndian *Archive::getResource(uint32 tag, uint16 id) { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const Resource &res = resMap[id]; + + return new Common::SeekableSubReadStreamEndian(_stream, res.offset, res.offset + res.size, _isBigEndian, DisposeAfterUse::NO); +} + +uint32 Archive::getOffset(uint32 tag, uint16 id) const { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + return resMap[id].offset; +} + +uint16 Archive::findResourceID(uint32 tag, const Common::String &resName) const { + if (!_types.contains(tag) || resName.empty()) + return 0xFFFF; + + const ResourceMap &resMap = _types[tag]; + + for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++) + if (it->_value.name.matchString(resName)) + return it->_key; + + return 0xFFFF; +} + +Common::String Archive::getName(uint32 tag, uint16 id) const { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + return resMap[id].name; +} + +Common::Array<uint32> Archive::getResourceTypeList() const { + Common::Array<uint32> typeList; + + for (TypeMap::const_iterator it = _types.begin(); it != _types.end(); it++) + typeList.push_back(it->_key); + + return typeList; +} + +Common::Array<uint16> Archive::getResourceIDList(uint32 type) const { + Common::Array<uint16> idList; + + if (!_types.contains(type)) + return idList; + + const ResourceMap &resMap = _types[type]; + + for (ResourceMap::const_iterator it = resMap.begin(); it != resMap.end(); it++) + idList.push_back(it->_key); + + return idList; +} + +uint32 Archive::convertTagToUppercase(uint32 tag) { + uint32 newTag = toupper(tag >> 24) << 24; + newTag |= toupper((tag >> 16) & 0xFF) << 16; + newTag |= toupper((tag >> 8) & 0xFF) << 8; + + return newTag | toupper(tag & 0xFF); +} + +// Mac Archive code + +MacArchive::MacArchive() : Archive(), _resFork(0) { +} + +MacArchive::~MacArchive() { + delete _resFork; +} + +void MacArchive::close() { + Archive::close(); + delete _resFork; + _resFork = 0; +} + +bool MacArchive::openFile(const Common::String &fileName) { + close(); + + _resFork = new Common::MacResManager(); + + if (!_resFork->open(fileName) || !_resFork->hasResFork()) { + close(); + return false; + } + + Common::MacResTagArray tagArray = _resFork->getResTagArray(); + + for (uint32 i = 0; i < tagArray.size(); i++) { + ResourceMap &resMap = _types[tagArray[i]]; + Common::MacResIDArray idArray = _resFork->getResIDArray(tagArray[i]); + + for (uint32 j = 0; j < idArray.size(); j++) { + Resource &res = resMap[idArray[j]]; + + res.offset = res.size = 0; // unused + res.name = _resFork->getResName(tagArray[i], idArray[j]); + debug(3, "Found MacArchive resource '%s' %d: %s", tag2str(tagArray[i]), idArray[j], res.name.c_str()); + } + } + + return true; +} + +bool MacArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) { + // TODO: Add support for this (v4 Windows games) + return false; +} + +Common::SeekableSubReadStreamEndian *MacArchive::getResource(uint32 tag, uint16 id) { + assert(_resFork); + Common::SeekableReadStream *stream = _resFork->getResource(tag, id); + return new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), true, DisposeAfterUse::NO); +} + +// RIFF Archive code + +bool RIFFArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) { + close(); + + stream->seek(startOffset); + + if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('R', 'I', 'F', 'F')) + return false; + + stream->readUint32LE(); // size + + if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('R', 'M', 'M', 'P')) + return false; + + if (convertTagToUppercase(stream->readUint32BE()) != MKTAG('C', 'F', 'T', 'C')) + return false; + + uint32 cftcSize = stream->readUint32LE(); + uint32 startPos = stream->pos(); + stream->readUint32LE(); // unknown (always 0?) + + while ((uint32)stream->pos() < startPos + cftcSize) { + uint32 tag = convertTagToUppercase(stream->readUint32BE()); + + uint32 size = stream->readUint32LE(); + uint32 id = stream->readUint32LE(); + uint32 offset = stream->readUint32LE(); + + if (tag == 0) + break; + + uint16 startResPos = stream->pos(); + stream->seek(offset + 12); + + Common::String name = ""; + byte nameSize = stream->readByte(); + + if (nameSize) { + for (uint8 i = 0; i < nameSize; i++) { + name += stream->readByte(); + } + } + + stream->seek(startResPos); + + debug(3, "Found RIFF resource '%s' %d: %d @ 0x%08x", tag2str(tag), id, size, offset); + + ResourceMap &resMap = _types[tag]; + Resource &res = resMap[id]; + res.offset = offset; + res.size = size; + res.name = name; + } + + _stream = stream; + return true; +} + +Common::SeekableSubReadStreamEndian *RIFFArchive::getResource(uint32 tag, uint16 id) { + if (!_types.contains(tag)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const ResourceMap &resMap = _types[tag]; + + if (!resMap.contains(id)) + error("Archive does not contain '%s' %04x", tag2str(tag), id); + + const Resource &res = resMap[id]; + + // Adjust to skip the resource header + uint32 offset = res.offset + 12; + uint32 size = res.size - 4; + // Skip the Pascal string + _stream->seek(offset); + byte stringSize = _stream->readByte(); // 1 for this byte + + offset += stringSize + 1; + size -= stringSize + 1; + + // Align to nearest word boundary + if (offset & 1) { + offset++; + size--; + } + + return new Common::SeekableSubReadStreamEndian(_stream, offset, offset + size, true, DisposeAfterUse::NO); +} + +// RIFX Archive code + +bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOffset) { + close(); + + stream->seek(startOffset); + + uint32 headerTag = stream->readUint32BE(); + + if (headerTag == MKTAG('R', 'I', 'F', 'X')) + _isBigEndian = true; + else if (SWAP_BYTES_32(headerTag) == MKTAG('R', 'I', 'F', 'X')) + _isBigEndian = false; + else + return false; + + Common::SeekableSubReadStreamEndian subStream(stream, startOffset + 4, stream->size(), _isBigEndian, DisposeAfterUse::NO); + + subStream.readUint32(); // size + + uint32 rifxType = subStream.readUint32(); + + if (rifxType != MKTAG('M', 'V', '9', '3') && rifxType != MKTAG('A', 'P', 'P', 'L')) + return false; + + if (subStream.readUint32() != MKTAG('i', 'm', 'a', 'p')) + return false; + + subStream.readUint32(); // imap length + subStream.readUint32(); // unknown + uint32 mmapOffset = subStream.readUint32() - startOffset - 4; + + subStream.seek(mmapOffset); + + if (subStream.readUint32() != MKTAG('m', 'm', 'a', 'p')) + return false; + + subStream.readUint32(); // mmap length + subStream.readUint16(); // unknown + subStream.readUint16(); // unknown + subStream.readUint32(); // resCount + empty entries + uint32 resCount = subStream.readUint32(); + subStream.skip(8); // all 0xFF + subStream.readUint32(); // unknown + + Common::Array<Resource> resources; + + // Need to look for these two resources + const Resource *keyRes = 0; + const Resource *casRes = 0; + + for (uint32 i = 0; i < resCount; i++) { + uint32 tag = subStream.readUint32(); + uint32 size = subStream.readUint32(); + uint32 offset = subStream.readUint32(); + /*uint16 flags = */ subStream.readUint16(); + /*uint16 unk1 = */ subStream.readUint16(); + /*uint32 unk2 = */ subStream.readUint32(); + + debug(3, "Found RIFX resource index %d: '%s', %d @ 0x%08x", i, tag2str(tag), size, offset); + + Resource res; + res.offset = offset; + res.size = size; + resources.push_back(res); + + // APPL is a special case; it has an embedded "normal" archive + if (rifxType == MKTAG('A', 'P', 'P', 'L') && tag == MKTAG('F', 'i', 'l', 'e')) + return openStream(stream, offset); + + // Looking for two types here + if (tag == MKTAG('K', 'E', 'Y', '*')) + keyRes = &resources[resources.size() - 1]; + else if (tag == MKTAG('C', 'A', 'S', '*')) + casRes = &resources[resources.size() - 1]; + } + + // We need to have found the 'File' resource already + if (rifxType == MKTAG('A', 'P', 'P', 'L')) { + warning("No 'File' resource present in APPL archive"); + return false; + } + + // A KEY* must be present + if (!keyRes) { + warning("No 'KEY*' resource present"); + return false; + } + + // Parse the CAS*, if present + Common::Array<uint32> casEntries; + if (casRes) { + Common::SeekableSubReadStreamEndian casStream(stream, casRes->offset + 8, casRes->offset + 8 + casRes->size, _isBigEndian, DisposeAfterUse::NO); + casEntries.resize(casRes->size / 4); + + for (uint32 i = 0; i < casEntries.size(); i++) + casEntries[i] = casStream.readUint32(); + } + + // Parse the KEY* + Common::SeekableSubReadStreamEndian keyStream(stream, keyRes->offset + 8, keyRes->offset + 8 + keyRes->size, _isBigEndian, DisposeAfterUse::NO); + /*uint16 unk1 = */ keyStream.readUint16(); + /*uint16 unk2 = */ keyStream.readUint16(); + /*uint32 unk3 = */ keyStream.readUint32(); + uint32 keyCount = keyStream.readUint32(); + + for (uint32 i = 0; i < keyCount; i++) { + uint32 index = keyStream.readUint32(); + uint32 id = keyStream.readUint32(); + uint32 resTag = keyStream.readUint32(); + + // Handle CAS*/CASt nonsense + if (resTag == MKTAG('C', 'A', 'S', 't')) { + for (uint32 j = 0; j < casEntries.size(); j++) { + if (casEntries[j] == index) { + id += j + 1; + break; + } + } + } + + const Resource &res = resources[index]; + debug(3, "Found RIFX resource: '%s' 0x%04x, %d @ 0x%08x", tag2str(resTag), id, res.size, res.offset); + _types[resTag][id] = res; + } + + _stream = stream; + return true; +} + +} // End of namespace Director diff --git a/engines/director/resource.h b/engines/director/resource.h new file mode 100644 index 0000000000..2d5a4aeba1 --- /dev/null +++ b/engines/director/resource.h @@ -0,0 +1,105 @@ +/* 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 DIRECTOR_RESOURCE_H +#define DIRECTOR_RESOURCE_H + +#include "common/file.h" +#include "common/substream.h" + +namespace Common { +class MacResManager; +} + +namespace Director { + +// Completely ripped off of Mohawk's Archive code + +class Archive { +public: + Archive(); + virtual ~Archive(); + + virtual bool openFile(const Common::String &fileName); + virtual bool openStream(Common::SeekableReadStream *stream, uint32 offset = 0) = 0; + virtual void close(); + + bool isOpen() const { return _stream != 0; } + + bool hasResource(uint32 tag, uint16 id) const; + bool hasResource(uint32 tag, const Common::String &resName) const; + virtual Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); + uint32 getOffset(uint32 tag, uint16 id) const; + uint16 findResourceID(uint32 tag, const Common::String &resName) const; + Common::String getName(uint32 tag, uint16 id) const; + + Common::Array<uint32> getResourceTypeList() const; + Common::Array<uint16> getResourceIDList(uint32 type) const; + bool _isBigEndian; + static uint32 convertTagToUppercase(uint32 tag); + +protected: + Common::SeekableReadStream *_stream; + struct Resource { + uint32 offset; + uint32 size; + Common::String name; + }; + typedef Common::HashMap<uint16, Resource> ResourceMap; + typedef Common::HashMap<uint32, ResourceMap> TypeMap; + TypeMap _types; +}; + +class MacArchive : public Archive { +public: + MacArchive(); + ~MacArchive(); + + void close(); + bool openFile(const Common::String &fileName); + bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0); + Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); + +private: + Common::MacResManager *_resFork; +}; + +class RIFFArchive : public Archive { +public: + RIFFArchive() : Archive() {} + ~RIFFArchive() {} + + bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0); + Common::SeekableSubReadStreamEndian *getResource(uint32 tag, uint16 id); +}; + +class RIFXArchive : public Archive { +public: + RIFXArchive() : Archive(){ _isBigEndian = true; } + ~RIFXArchive() {} + + bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0); +}; + +} // End of namespace Director + +#endif diff --git a/engines/director/score.cpp b/engines/director/score.cpp new file mode 100644 index 0000000000..8a252a26ed --- /dev/null +++ b/engines/director/score.cpp @@ -0,0 +1,849 @@ +/* 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/system.h" +#include "common/config-manager.h" +#include "common/events.h" + +#include "engines/util.h" +#include "graphics/font.h" +#include "graphics/palette.h" + +#include "director/score.h" +#include "director/frame.h" +#include "director/resource.h" +#include "director/sound.h" +#include "director/sprite.h" +#include "director/lingo/lingo.h" + +namespace Director { + +static byte defaultPalette[768] = { + 0, 0, 0, 17, 17, 17, 34, 34, 34, 68, 68, 68, 85, 85, 85, 119, + 119, 119, 136, 136, 136, 170, 170, 170, 187, 187, 187, 221, 221, 221, 238, 238, + 238, 0, 0, 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, + 0, 0, 136, 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, + 17, 0, 0, 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, + 0, 0, 170, 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 17, 0, 0, + 34, 0, 0, 68, 0, 0, 85, 0, 0, 119, 0, 0, 136, 0, 0, 170, + 0, 0, 187, 0, 0, 221, 0, 0, 238, 0, 0, 0, 0, 51, 0, 0, + 102, 0, 0, 153, 0, 0, 204, 0, 0, 255, 0, 51, 0, 0, 51, 51, + 0, 51, 102, 0, 51, 153, 0, 51, 204, 0, 51, 255, 0, 102, 0, 0, + 102, 51, 0, 102, 102, 0, 102, 153, 0, 102, 204, 0, 102, 255, 0, 153, + 0, 0, 153, 51, 0, 153, 102, 0, 153, 153, 0, 153, 204, 0, 153, 255, + 0, 204, 0, 0, 204, 51, 0, 204, 102, 0, 204, 153, 0, 204, 204, 0, + 204, 255, 0, 255, 0, 0, 255, 51, 0, 255, 102, 0, 255, 153, 0, 255, + 204, 0, 255, 255, 51, 0, 0, 51, 0, 51, 51, 0, 102, 51, 0, 153, + 51, 0, 204, 51, 0, 255, 51, 51, 0, 51, 51, 51, 51, 51, 102, 51, + 51, 153, 51, 51, 204, 51, 51, 255, 51, 102, 0, 51, 102, 51, 51, 102, + 102, 51, 102, 153, 51, 102, 204, 51, 102, 255, 51, 153, 0, 51, 153, 51, + 51, 153, 102, 51, 153, 153, 51, 153, 204, 51, 153, 255, 51, 204, 0, 51, + 204, 51, 51, 204, 102, 51, 204, 153, 51, 204, 204, 51, 204, 255, 51, 255, + 0, 51, 255, 51, 51, 255, 102, 51, 255, 153, 51, 255, 204, 51, 255, 255, + 102, 0, 0, 102, 0, 51, 102, 0, 102, 102, 0, 153, 102, 0, 204, 102, + 0, 255, 102, 51, 0, 102, 51, 51, 102, 51, 102, 102, 51, 153, 102, 51, + 204, 102, 51, 255, 102, 102, 0, 102, 102, 51, 102, 102, 102, 102, 102, 153, + 102, 102, 204, 102, 102, 255, 102, 153, 0, 102, 153, 51, 102, 153, 102, 102, + 153, 153, 102, 153, 204, 102, 153, 255, 102, 204, 0, 102, 204, 51, 102, 204, + 102, 102, 204, 153, 102, 204, 204, 102, 204, 255, 102, 255, 0, 102, 255, 51, + 102, 255, 102, 102, 255, 153, 102, 255, 204, 102, 255, 255, 153, 0, 0, 153, + 0, 51, 153, 0, 102, 153, 0, 153, 153, 0, 204, 153, 0, 255, 153, 51, + 0, 153, 51, 51, 153, 51, 102, 153, 51, 153, 153, 51, 204, 153, 51, 255, + 153, 102, 0, 153, 102, 51, 153, 102, 102, 153, 102, 153, 153, 102, 204, 153, + 102, 255, 153, 153, 0, 153, 153, 51, 153, 153, 102, 153, 153, 153, 153, 153, + 204, 153, 153, 255, 153, 204, 0, 153, 204, 51, 153, 204, 102, 153, 204, 153, + 153, 204, 204, 153, 204, 255, 153, 255, 0, 153, 255, 51, 153, 255, 102, 153, + 255, 153, 153, 255, 204, 153, 255, 255, 204, 0, 0, 204, 0, 51, 204, 0, + 102, 204, 0, 153, 204, 0, 204, 204, 0, 255, 204, 51, 0, 204, 51, 51, + 204, 51, 102, 204, 51, 153, 204, 51, 204, 204, 51, 255, 204, 102, 0, 204, + 102, 51, 204, 102, 102, 204, 102, 153, 204, 102, 204, 204, 102, 255, 204, 153, + 0, 204, 153, 51, 204, 153, 102, 204, 153, 153, 204, 153, 204, 204, 153, 255, + 204, 204, 0, 204, 204, 51, 204, 204, 102, 204, 204, 153, 204, 204, 204, 204, + 204, 255, 204, 255, 0, 204, 255, 51, 204, 255, 102, 204, 255, 153, 204, 255, + 204, 204, 255, 255, 255, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153, + 255, 0, 204, 255, 0, 255, 255, 51, 0, 255, 51, 51, 255, 51, 102, 255, + 51, 153, 255, 51, 204, 255, 51, 255, 255, 102, 0, 255, 102, 51, 255, 102, + 102, 255, 102, 153, 255, 102, 204, 255, 102, 255, 255, 153, 0, 255, 153, 51, + 255, 153, 102, 255, 153, 153, 255, 153, 204, 255, 153, 255, 255, 204, 0, 255, + 204, 51, 255, 204, 102, 255, 204, 153, 255, 204, 204, 255, 204, 255, 255, 255, + 0, 255, 255, 51, 255, 255, 102, 255, 255, 153, 255, 255, 204, 255, 255, 255 }; + +Score::Score(DirectorEngine *vm) { + _vm = vm; + _surface = new Graphics::ManagedSurface; + _trailSurface = new Graphics::ManagedSurface; + _movieArchive = _vm->getMainArchive(); + _lingo = _vm->getLingo(); + _soundManager = _vm->getSoundManager(); + _lingo->processEvent(kEventPrepareMovie, 0); + _movieScriptCount = 0; + _labels = NULL; + _font = NULL; + + _versionMinor = _versionMajor = 0; + _currentFrameRate = 20; + _castArrayStart = _castArrayEnd = 0; + _currentFrame = 0; + _nextFrameTime = 0; + _flags = 0; + _stopPlay = false; + _stageColor = 0; + + if (_movieArchive->hasResource(MKTAG('M','C','N','M'), 0)) { + _macName = _movieArchive->getName(MKTAG('M','C','N','M'), 0).c_str(); + } + + if (_movieArchive->hasResource(MKTAG('V','W','L','B'), 1024)) { + loadLabels(*_movieArchive->getResource(MKTAG('V','W','L','B'), 1024)); + } +} + +void Score::loadArchive() { + Common::Array<uint16> clutList = _movieArchive->getResourceIDList(MKTAG('C','L','U','T')); + + if (clutList.size() > 1) + warning("More than one palette was found (%d)", clutList.size()); + + if (clutList.size() == 0) { + warning("CLUT resource not found, using default Mac palette"); + g_system->getPaletteManager()->setPalette(defaultPalette, 0, 256); + _vm->setPalette(defaultPalette, 256); + } else { + Common::SeekableSubReadStreamEndian *pal = _movieArchive->getResource(MKTAG('C', 'L', 'U', 'T'), clutList[0]); + + loadPalette(*pal); + g_system->getPaletteManager()->setPalette(_vm->getPalette(), 0, _vm->getPaletteColorCount()); + } + + assert(_movieArchive->hasResource(MKTAG('V','W','S','C'), 1024)); + assert(_movieArchive->hasResource(MKTAG('V','W','C','F'), 1024)); + + loadFrames(*_movieArchive->getResource(MKTAG('V','W','S','C'), 1024)); + loadConfig(*_movieArchive->getResource(MKTAG('V','W','C','F'), 1024)); + + if (_vm->getVersion() < 4) { + assert(_movieArchive->hasResource(MKTAG('V','W','C','R'), 1024)); + loadCastData(*_movieArchive->getResource(MKTAG('V','W','C','R'), 1024)); + } + + if (_movieArchive->hasResource(MKTAG('V','W','A','C'), 1024)) { + loadActions(*_movieArchive->getResource(MKTAG('V','W','A','C'), 1024)); + } + + if (_movieArchive->hasResource(MKTAG('V','W','F','I'), 1024)) { + loadFileInfo(*_movieArchive->getResource(MKTAG('V','W','F','I'), 1024)); + } + + if (_movieArchive->hasResource(MKTAG('V','W','F','M'), 1024)) { + loadFontMap(*_movieArchive->getResource(MKTAG('V','W','F','M'), 1024)); + } + + Common::Array<uint16> vwci = _movieArchive->getResourceIDList(MKTAG('V','W','C','I')); + + if (vwci.size() > 0) { + Common::Array<uint16>::iterator iterator; + + for (iterator = vwci.begin(); iterator != vwci.end(); ++iterator) + loadCastInfo(*_movieArchive->getResource(MKTAG('V','W','C','I'), *iterator), *iterator); + } + + Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T')); + + if (stxt.size() > 0) { + loadScriptText(*_movieArchive->getResource(MKTAG('S','T','X','T'), *stxt.begin())); + } +} + +Score::~Score() { + if (_surface) + _surface->free(); + + if (_trailSurface) + _trailSurface->free(); + + delete _surface; + delete _trailSurface; + + if (_movieArchive) + _movieArchive->close(); + + delete _font; + delete _labels; +} + +void Score::loadPalette(Common::SeekableSubReadStreamEndian &stream) { + uint16 steps = stream.size() / 6; + uint16 index = (steps * 3) - 1; + uint16 _paletteColorCount = steps; + byte *_palette = new byte[index + 1]; + + for (uint8 i = 0; i < steps; i++) { + _palette[index - 2] = stream.readByte(); + stream.readByte(); + + _palette[index - 1] = stream.readByte(); + stream.readByte(); + + _palette[index] = stream.readByte(); + stream.readByte(); + index -= 3; + } + _vm->setPalette(_palette, _paletteColorCount); +} + +void Score::loadFrames(Common::SeekableSubReadStreamEndian &stream) { + uint32 size = stream.readUint32(); + size -= 4; + + if (_vm->getVersion() > 3) { + stream.skip(16); + //Unknown, some bytes - constant (refer to contuinity). + } + + uint16 channelSize; + uint16 channelOffset; + + Frame *initial = new Frame(_vm); + _frames.push_back(initial); + + while (size != 0) { + uint16 frameSize = stream.readUint16(); + size -= frameSize; + frameSize -= 2; + Frame *frame = new Frame(*_frames.back()); + + while (frameSize != 0) { + if (_vm->getVersion() < 4) { + channelSize = stream.readByte() * 2; + channelOffset = stream.readByte() * 2; + frameSize -= channelSize + 2; + } else { + channelSize = stream.readByte(); + channelOffset = stream.readByte(); + frameSize -= channelSize + 4; + } + frame->readChannel(stream, channelOffset, channelSize); + + } + + _frames.push_back(frame); + } + + //remove initial frame + _frames.remove_at(0); +} + +void Score::loadConfig(Common::SeekableSubReadStreamEndian &stream) { + /*uint16 unk1 = */ stream.readUint16(); + /*ver1 = */ stream.readUint16(); + _movieRect = Score::readRect(stream); + + _castArrayStart = stream.readUint16(); + _castArrayEnd = stream.readUint16(); + _currentFrameRate = stream.readByte(); + stream.skip(9); + _stageColor = stream.readUint16(); +} + +void Score::readVersion(uint32 rid) { + _versionMinor = rid & 0xffff; + _versionMajor = rid >> 16; + + debug("Version: %d.%d", _versionMajor, _versionMinor); +} + +void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream) { + for (uint16 id = _castArrayStart; id <= _castArrayEnd; id++) { + byte size = stream.readByte(); + if (size == 0) + continue; + + uint8 castType = stream.readByte(); + + switch (castType) { + case kCastBitmap: + _casts[id] = new BitmapCast(stream); + _casts[id]->type = kCastBitmap; + break; + case kCastText: + _casts[id] = new TextCast(stream); + _casts[id]->type = kCastText; + break; + case kCastShape: + _casts[id] = new ShapeCast(stream); + _casts[id]->type = kCastShape; + break; + case kCastButton: + _casts[id] = new ButtonCast(stream); + _casts[id]->type = kCastButton; + break; + default: + warning("Unhandled cast type: %d", castType); + stream.skip(size - 1); + break; + } + } + + //Set cast pointers to sprites + for (uint16 i = 0; i < _frames.size(); i++) { + for (uint16 j = 0; j < _frames[i]->_sprites.size(); j++) { + byte castId = _frames[i]->_sprites[j]->_castId; + + if (_casts.contains(castId)) + _frames[i]->_sprites[j]->_cast = _casts.find(castId)->_value; + } + } +} + +void Score::loadLabels(Common::SeekableSubReadStreamEndian &stream) { + _labels = new Common::SortedArray<Label *>(compareLabels); + uint16 count = stream.readUint16() + 1; + uint16 offset = count * 4 + 2; + + uint16 frame = stream.readUint16(); + uint16 stringPos = stream.readUint16() + offset; + + for (uint16 i = 0; i < count; i++) { + uint16 nextFrame = stream.readUint16(); + uint16 nextStringPos = stream.readUint16() + offset; + uint16 streamPos = stream.pos(); + + stream.seek(stringPos); + Common::String label; + for (uint16 j = stringPos; j < nextStringPos; j++) { + label += stream.readByte(); + } + _labels->insert(new Label(label, frame)); + stream.seek(streamPos); + + frame = nextFrame; + stringPos = nextStringPos; + } + + Common::SortedArray<Label *>::iterator j; + + for (j = _labels->begin(); j != _labels->end(); ++j) { + debug("Frame %d, Label %s", (*j)->number, (*j)->name.c_str()); + } +} + +int Score::compareLabels(const void *a, const void *b) { + return ((const Label *)a)->number - ((const Label *)b)->number; +} + +void Score::loadActions(Common::SeekableSubReadStreamEndian &stream) { + uint16 count = stream.readUint16() + 1; + uint16 offset = count * 4 + 2; + + byte id = stream.readByte(); + /*byte subId = */ stream.readByte(); //I couldn't find how it used in continuity (except print). Frame actionId = 1 byte. + uint16 stringPos = stream.readUint16() + offset; + + for (uint16 i = 0; i < count; i++) { + uint16 nextId = stream.readByte(); + /*byte subId = */ stream.readByte(); + uint16 nextStringPos = stream.readUint16() + offset; + uint16 streamPos = stream.pos(); + + stream.seek(stringPos); + + for (uint16 j = stringPos; j < nextStringPos; j++) { + byte ch = stream.readByte(); + if (ch == 0x0d) { + ch = '\n'; + } + _actions[id] += ch; + } + + stream.seek(streamPos); + + id = nextId; + stringPos = nextStringPos; + + if (stringPos == stream.size()) + break; + } + + Common::HashMap<uint16, Common::String>::iterator j; + + if (ConfMan.getBool("dump_scripts")) + for (j = _actions.begin(); j != _actions.end(); ++j) { + if (!j->_value.empty()) + dumpScript(j->_value.c_str(), kFrameScript, j->_key); + } + + for (j = _actions.begin(); j != _actions.end(); ++j) + if (!j->_value.empty()) + _lingo->addCode(j->_value.c_str(), kFrameScript, j->_key); +} + +void Score::loadScriptText(Common::SeekableSubReadStreamEndian &stream) { + /*uint32 unk1 = */ stream.readUint32(); + uint32 strLen = stream.readUint32(); + /*uin32 dataLen = */ stream.readUint32(); + Common::String script; + + for (uint32 i = 0; i < strLen; i++) { + byte ch = stream.readByte(); + + if (ch == 0x0d) { + //in old Mac systems \r was the code for end-of-line instead. + ch = '\n'; + } + script += ch; + } + + if (!script.empty() && ConfMan.getBool("dump_scripts")) + dumpScript(script.c_str(), kMovieScript, _movieScriptCount); + + if (!script.empty()) + _lingo->addCode(script.c_str(), kMovieScript, _movieScriptCount); + + _movieScriptCount++; +} + +void Score::setStartToLabel(Common::String label) { + if (!_labels) { + warning("setStartToLabel: No labels set"); + return; + } + + Common::SortedArray<Label *>::iterator i; + + for (i = _labels->begin(); i != _labels->end(); ++i) { + if ((*i)->name == label) { + _currentFrame = (*i)->number; + return; + } + } + warning("Label %s not found", label.c_str()); +} + +void Score::dumpScript(const char *script, ScriptType type, uint16 id) { + Common::DumpFile out; + Common::String typeName; + char buf[256]; + + switch (type) { + case kNoneScript: + error("Incorrect dumpScript() call"); + case kFrameScript: + typeName = "frame"; + break; + case kMovieScript: + typeName = "movie"; + break; + case kSpriteScript: + typeName = "sprite"; + break; + } + + sprintf(buf, "./dumps/%s-%s-%d.txt", _macName.c_str(), typeName.c_str(), id); + + if (!out.open(buf)) { + warning("Can not open dump file %s", buf); + return; + } + + out.write(script, strlen(script)); + + out.flush(); + out.close(); +} + +void Score::loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id) { + uint32 entryType = 0; + Common::Array<Common::String> castStrings = loadStrings(stream, entryType); + CastInfo *ci = new CastInfo(); + + ci->script = castStrings[0]; + + if (!ci->script.empty() && ConfMan.getBool("dump_scripts")) + dumpScript(ci->script.c_str(), kSpriteScript, id); + + if (!ci->script.empty()) + _lingo->addCode(ci->script.c_str(), kSpriteScript, id); + + ci->name = getString(castStrings[1]); + ci->directory = getString(castStrings[2]); + ci->fileName = getString(castStrings[3]); + ci->type = castStrings[4]; + + _castsInfo[id] = ci; +} + +void Score::gotoloop() { + //This command has the playback head contonuously return to the first marker to to the left and then loop back. + //If no marker are to the left of the playback head, the playback head continues to the right. + Common::SortedArray<Label *>::iterator i; + + for (i = _labels->begin(); i != _labels->end(); ++i) { + if ((*i)->name == _currentLabel) { + _currentFrame = (*i)->number; + return; + } + } +} + +void Score::gotonext() { + Common::SortedArray<Label *>::iterator i; + + for (i = _labels->begin(); i != _labels->end(); ++i) { + if ((*i)->name == _currentLabel) { + if (i != _labels->end()) { + //return to the first marker to to the right + ++i; + _currentFrame = (*i)->number; + return; + } else { + //if no markers are to the right of the playback head, + //the playback head goes to the first marker to the left + _currentFrame = (*i)->number; + return; + } + } + } + //If there are not markers to the left, + //the playback head goes to frame 1, (Director frame array start from 1, engine from 0) + _currentFrame = 0; +} + +void Score::gotoprevious() { + //One label + if (_labels->begin() == _labels->end()) { + _currentFrame = (*_labels->begin())->number; + return; + } + + Common::SortedArray<Label *>::iterator previous = _labels->begin(); + Common::SortedArray<Label *>::iterator i = previous++; + + for (i = _labels->begin(); i != _labels->end(); ++i, ++previous) { + if ((*i)->name == _currentLabel) { + _currentFrame = (*previous)->number; + return; + } else { + _currentFrame = (*i)->number; + return; + } + } + _currentFrame = 0; +} + +Common::String Score::getString(Common::String str) { + if (str.size() == 0) { + return str; + } + + uint8 f = static_cast<uint8>(str.firstChar()); + + if (f == 0) { + return ""; + } + + str.deleteChar(0); + + if (str.lastChar() == '\x00') { + str.deleteLastChar(); + } + + return str; +} + +void Score::loadFileInfo(Common::SeekableSubReadStreamEndian &stream) { + Common::Array<Common::String> fileInfoStrings = loadStrings(stream, _flags); + _script = fileInfoStrings[0]; + + if (!_script.empty() && ConfMan.getBool("dump_scripts")) + dumpScript(_script.c_str(), kMovieScript, _movieScriptCount); + + if (!_script.empty()) + _lingo->addCode(_script.c_str(), kMovieScript, _movieScriptCount); + + _movieScriptCount++; + _changedBy = fileInfoStrings[1]; + _createdBy = fileInfoStrings[2]; + _directory = fileInfoStrings[3]; +} + +Common::Array<Common::String> Score::loadStrings(Common::SeekableSubReadStreamEndian &stream, uint32 &entryType, bool hasHeader) { + Common::Array<Common::String> strings; + uint32 offset = 0; + + if (hasHeader) { + offset = stream.readUint32(); + /*uint32 unk1 = */ stream.readUint32(); + /*uint32 unk2 = */ stream.readUint32(); + entryType = stream.readUint32(); + stream.seek(offset); + } + + uint16 count = stream.readUint16(); + offset += (count + 1) * 4 + 2; //positions info + uint16 count + uint32 startPos = stream.readUint32() + offset; + + for (uint16 i = 0; i < count; i++) { + Common::String entryString; + uint32 nextPos = stream.readUint32() + offset; + uint32 streamPos = stream.pos(); + + stream.seek(startPos); + + while (startPos != nextPos) { + entryString += stream.readByte(); + ++startPos; + } + + strings.push_back(entryString); + + stream.seek(streamPos); + startPos = nextPos; + } + + return strings; +} + +void Score::loadFontMap(Common::SeekableSubReadStreamEndian &stream) { + uint16 count = stream.readUint16(); + uint32 offset = (count * 2) + 2; + uint16 currentRawPosition = offset; + + for (uint16 i = 0; i < count; i++) { + uint16 id = stream.readUint16(); + uint32 positionInfo = stream.pos(); + + stream.seek(currentRawPosition); + + uint16 size = stream.readByte(); + Common::String font; + + for (uint16 k = 0; k < size; k++) { + font += stream.readByte(); + } + + _fontMap[id] = font; + debug(3, "Fontmap. ID %d Font %s", id, font.c_str()); + currentRawPosition = stream.pos(); + stream.seek(positionInfo); + } +} + +BitmapCast::BitmapCast(Common::SeekableSubReadStreamEndian &stream) { + flags = stream.readByte(); + someFlaggyThing = stream.readUint16(); + initialRect = Score::readRect(stream); + boundingRect = Score::readRect(stream); + regY = stream.readUint16(); + regX = stream.readUint16(); + unk1 = unk2 = 0; + + if (someFlaggyThing & 0x8000) { + unk1 = stream.readUint16(); + unk2 = stream.readUint16(); + } + modified = 0; +} + +TextCast::TextCast(Common::SeekableSubReadStreamEndian &stream) { + /*byte flags =*/ stream.readByte(); + borderSize = static_cast<SizeType>(stream.readByte()); + gutterSize = static_cast<SizeType>(stream.readByte()); + boxShadow = static_cast<SizeType>(stream.readByte()); + textType = static_cast<TextType>(stream.readByte()); + textAlign = static_cast<TextAlignType>(stream.readUint16()); + stream.skip(6); //palinfo + + int t = stream.readUint32(); + assert(t == 0); // So far we saw only 0 here + + initialRect = Score::readRect(stream); + textShadow = static_cast<SizeType>(stream.readByte()); + byte flags = stream.readByte(); + if (flags & 0x1) + textFlags.push_back(kTextFlagEditable); + if (flags & 0x2) + textFlags.push_back(kTextFlagAutoTab); + if (flags & 0x4) + textFlags.push_back(kTextFlagDoNotWrap); + + //TODO: FIXME: guesswork + fontId = stream.readByte(); + fontSize = stream.readByte(); + + modified = 0; +} + +ShapeCast::ShapeCast(Common::SeekableSubReadStreamEndian &stream) { + /*byte flags = */ stream.readByte(); + /*unk1 = */ stream.readByte(); + shapeType = static_cast<ShapeType>(stream.readByte()); + initialRect = Score::readRect(stream); + pattern = stream.readUint16BE(); + fgCol = stream.readByte(); + bgCol = stream.readByte(); + fillType = stream.readByte(); + lineThickness = stream.readByte(); + lineDirection = stream.readByte(); + modified = 0; +} + +Common::Rect Score::readRect(Common::SeekableSubReadStreamEndian &stream) { + Common::Rect *rect = new Common::Rect(); + rect->top = stream.readUint16(); + rect->left = stream.readUint16(); + rect->bottom = stream.readUint16(); + rect->right = stream.readUint16(); + + return *rect; +} + +void Score::startLoop() { + initGraphics(_movieRect.width(), _movieRect.height(), true); + + _surface->create(_movieRect.width(), _movieRect.height()); + _trailSurface->create(_movieRect.width(), _movieRect.height()); + + if (_stageColor == 0) + _trailSurface->clear(_vm->getPaletteColorCount() - 1); + else + _trailSurface->clear(_stageColor); + + _currentFrame = 0; + _stopPlay = false; + _nextFrameTime = 0; + + _lingo->processEvent(kEventStartMovie, 0); + _frames[_currentFrame]->prepareFrame(this); + + while (!_stopPlay && _currentFrame < _frames.size() - 2) { + debugC(1, kDebugImages, "Current frame: %d", _currentFrame); + update(); + processEvents(); + } +} + +void Score::update() { + if (g_system->getMillis() < _nextFrameTime) + return; + + _surface->clear(); + _surface->copyFrom(*_trailSurface); + + //Enter and exit from previous frame (Director 4) + _lingo->processEvent(kEventEnterFrame, _frames[_currentFrame]->_actionId); + _lingo->processEvent(kEventExitFrame, _frames[_currentFrame]->_actionId); + //TODO Director 6 - another order + + + //TODO Director 6 step: send beginSprite event to any sprites whose span begin in the upcoming frame + //for (uint16 i = 0; i < CHANNEL_COUNT; i++) { + // if (_frames[_currentFrame]->_sprites[i]->_enabled) + // _lingo->processEvent(kEventBeginSprite, i); + //} + + //TODO Director 6 step: send prepareFrame event to all sprites and the script channel in upcoming frame + //_lingo->processEvent(kEventPrepareFrame, _currentFrame); + _currentFrame++; + + Common::SortedArray<Label *>::iterator i; + for (i = _labels->begin(); i != _labels->end(); ++i) { + if ((*i)->number == _currentFrame) { + _currentLabel = (*i)->name; + } + } + + _frames[_currentFrame]->prepareFrame(this); + //Stage is drawn between the prepareFrame and enterFrame events (Lingo in a Nutshell) + + byte tempo = _frames[_currentFrame]->_tempo; + + if (tempo) { + if (tempo > 161) { + //Delay + _nextFrameTime = g_system->getMillis() + (256 - tempo) * 1000; + + return; + } else if (tempo <= 60) { + //FPS + _nextFrameTime = g_system->getMillis() + (float)tempo / 60 * 1000; + _currentFrameRate = tempo; + } else if (tempo >= 136) { + //TODO Wait for channel tempo - 135 + } else if (tempo == 128) { + //TODO Wait for Click/Key + } else if (tempo == 135) { + //Wait for sound channel 1 + while (_soundManager->isChannelActive(1)) { + processEvents(); + } + } else if (tempo == 134) { + //Wait for sound channel 2 + while (_soundManager->isChannelActive(2)) { + processEvents(); + } + } + } + _nextFrameTime = g_system->getMillis() + (float)_currentFrameRate / 60 * 1000; +} + +void Score::processEvents() { + if (_currentFrame > 0) + _lingo->processEvent(kEventIdle, _currentFrame - 1); + + Common::Event event; + + int endTime = g_system->getMillis() + 200; + + while (g_system->getMillis() < endTime) { + while (g_system->getEventManager()->pollEvent(event)) { + if (event.type == Common::EVENT_QUIT) + _stopPlay = true; + + if (event.type == Common::EVENT_LBUTTONDOWN) { + Common::Point pos = g_system->getEventManager()->getMousePos(); + + //TODO there is dont send frame id + _lingo->processEvent(kEventMouseDown, _frames[_currentFrame]->getSpriteIDFromPos(pos)); + } + + if (event.type == Common::EVENT_LBUTTONUP) { + Common::Point pos = g_system->getEventManager()->getMousePos(); + + _lingo->processEvent(kEventMouseUp, _frames[_currentFrame]->getSpriteIDFromPos(pos)); + } + } + + g_system->updateScreen(); + g_system->delayMillis(10); + } +} + +Sprite *Score::getSpriteById(uint16 id) { + if (_frames[_currentFrame]->_sprites[id]) { + return _frames[_currentFrame]->_sprites[id]; + } else { + warning("Sprite on frame %d width id %d not found", _currentFrame, id); + return nullptr; + } +} + +} //End of namespace Director diff --git a/engines/director/score.h b/engines/director/score.h new file mode 100644 index 0000000000..8ddbed0bd5 --- /dev/null +++ b/engines/director/score.h @@ -0,0 +1,244 @@ +/* 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 DIRECTOR_SCORE_H +#define DIRECTOR_SCORE_H + +#include "common/substream.h" +#include "common/rect.h" + +namespace Graphics { + class ManagedSurface; + class Font; +} + +namespace Director { + +class Archive; +class DirectorEngine; +class DirectorSound; +class Frame; +class Lingo; +class Sprite; + +enum CastType { + kCastBitmap = 1, + kCastFilmLoop, + kCastText, + kCastPalette, + kCastPicture, + kCastSound, + kCastButton, + kCastShape, + kCastMovie, + kCastDigitalVideo, + kCastScript +}; + +enum ScriptType { + kMovieScript = 0, + kSpriteScript = 1, + kFrameScript = 2, + kNoneScript = -1, + kMaxScriptType = 2 +}; + +struct Cast { + CastType type; + Common::Rect initialRect; + byte modified; +}; + +struct BitmapCast : Cast { + BitmapCast(Common::SeekableSubReadStreamEndian &stream); + + Common::Rect boundingRect; + uint16 regX; + uint16 regY; + uint8 flags; + uint16 someFlaggyThing; + uint16 unk1, unk2; +}; + +enum ShapeType { + kShapeRectangle, + kShapeRoundRect, + kShapeOval, + kShapeLine +}; + +struct ShapeCast : Cast { + ShapeCast(Common::SeekableSubReadStreamEndian &stream); + + ShapeType shapeType; + uint16 pattern; + byte fgCol; + byte bgCol; + byte fillType; + byte lineThickness; + byte lineDirection; +}; + +enum TextType { + kTextTypeAdjustToFit, + kTextTypeScrolling, + kTextTypeFixed +}; + +enum TextAlignType { + kTextAlignRight = -1, + kTextAlignLeft, + kTextAlignCenter +}; + +enum TextFlag { + kTextFlagEditable, + kTextFlagAutoTab, + kTextFlagDoNotWrap +}; + +enum SizeType { + kSizeNone, + kSizeSmallest, + kSizeSmall, + kSizeMedium, + kSizeLarge, + kSizeLargest +}; + +struct TextCast : Cast { + TextCast(Common::SeekableSubReadStreamEndian &stream); + + SizeType borderSize; + SizeType gutterSize; + SizeType boxShadow; + + uint32 fontId; + uint16 fontSize; + TextType textType; + TextAlignType textAlign; + SizeType textShadow; + Common::Array<TextFlag> textFlags; +}; + +enum ButtonType { + kTypeButton, + kTypeCheckBox, + kTypeRadio +}; + +struct ButtonCast : TextCast { + ButtonCast(Common::SeekableSubReadStreamEndian &stream) : TextCast(stream) { + buttonType = static_cast<ButtonType>(stream.readUint16BE()); + } + + ButtonType buttonType; +}; + +struct CastInfo { + Common::String script; + Common::String name; + Common::String directory; + Common::String fileName; + Common::String type; +}; + +struct Label { + Common::String name; + uint16 number; + Label(Common::String name1, uint16 number1) { name = name1; number = number1; } +}; + +class Score { +public: + Score(DirectorEngine *vm); + ~Score(); + + static Common::Rect readRect(Common::SeekableSubReadStreamEndian &stream); + static int compareLabels(const void *a, const void *b); + void loadArchive(); + void setStartToLabel(Common::String label); + void gotoloop(); + void gotonext(); + void gotoprevious(); + void startLoop(); + void processEvents(); + Archive *getArchive() const { return _movieArchive; }; + void loadCastData(Common::SeekableSubReadStreamEndian &stream); + void setCurrentFrame(uint16 frameId) { _currentFrame = frameId; } + Common::String getMacName() const { return _macName; } + Sprite *getSpriteById(uint16 id); +private: + void update(); + void readVersion(uint32 rid); + void loadConfig(Common::SeekableSubReadStreamEndian &stream); + void loadPalette(Common::SeekableSubReadStreamEndian &stream); + void loadFrames(Common::SeekableSubReadStreamEndian &stream); + void loadLabels(Common::SeekableSubReadStreamEndian &stream); + void loadActions(Common::SeekableSubReadStreamEndian &stream); + void loadCastInfo(Common::SeekableSubReadStreamEndian &stream, uint16 id); + void loadScriptText(Common::SeekableSubReadStreamEndian &stream); + void loadFileInfo(Common::SeekableSubReadStreamEndian &stream); + void loadFontMap(Common::SeekableSubReadStreamEndian &stream); + void dumpScript(const char *script, ScriptType type, uint16 id); + Common::String getString(Common::String str); + Common::Array<Common::String> loadStrings(Common::SeekableSubReadStreamEndian &stream, uint32 &entryType, bool hasHeader = true); + +public: + Common::Array<Frame *> _frames; + Common::HashMap<int, Cast *> _casts; + Common::HashMap<uint16, CastInfo *> _castsInfo; + Common::SortedArray<Label *> *_labels; + Common::HashMap<uint16, Common::String> _actions; + Common::HashMap<uint16, Common::String> _fontMap; + Graphics::ManagedSurface *_surface; + Graphics::ManagedSurface *_trailSurface; + Graphics::Font *_font; + Archive *_movieArchive; + Common::Rect _movieRect; + +private: + uint16 _versionMinor; + uint16 _versionMajor; + Common::String _macName; + Common::String _createdBy; + Common::String _changedBy; + Common::String _script; + Common::String _directory; + byte _currentFrameRate; + uint16 _castArrayStart; + uint16 _currentFrame; + Common::String _currentLabel; + uint32 _nextFrameTime; + uint32 _flags; + bool _stopPlay; + uint16 _castArrayEnd; + uint16 _movieScriptCount; + uint16 _stageColor; + Lingo *_lingo; + DirectorSound *_soundManager; + DirectorEngine *_vm; +}; + +} //End of namespace Director + +#endif diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp new file mode 100644 index 0000000000..af6e0d2e1c --- /dev/null +++ b/engines/director/sound.cpp @@ -0,0 +1,105 @@ +/* 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 "audio/decoders/wave.h" +#include "common/file.h" +#include "audio/decoders/aiff.h" +#include "common/system.h" + +#include "director/sound.h" + +namespace Director { + +DirectorSound::DirectorSound() { + _sound1 = new Audio::SoundHandle(); + _sound2 = new Audio::SoundHandle(); + _scriptSound = new Audio::SoundHandle(); + _mixer = g_system->getMixer(); +} + +DirectorSound::~DirectorSound() { + delete _sound1; + delete _sound2; + delete _scriptSound; +} + +void DirectorSound::playWAV(Common::String filename, uint8 soundChannel) { + Common::File *file = new Common::File(); + + if (!file->open(filename)) { + warning("Failed to open %s", filename.c_str()); + + delete file; + + return; + } + + Audio::RewindableAudioStream *sound = Audio::makeWAVStream(file, DisposeAfterUse::YES); + + if (soundChannel == 1) + _mixer->playStream(Audio::Mixer::kSFXSoundType, _sound1, sound); + else + _mixer->playStream(Audio::Mixer::kSFXSoundType, _sound2, sound); +} + +void DirectorSound::playAIFF(Common::String filename, uint8 soundChannel) { + Common::File *file = new Common::File(); + + if (!file->open(filename)) { + warning("Failed to open %s", filename.c_str()); + delete file; + return; + } + + Audio::RewindableAudioStream *sound = Audio::makeAIFFStream(file, DisposeAfterUse::YES); + + if (soundChannel == 1) + _mixer->playStream(Audio::Mixer::kSFXSoundType, _sound1, sound); + else + _mixer->playStream(Audio::Mixer::kSFXSoundType, _sound2, sound); +} + +void DirectorSound::playMCI(Audio::AudioStream &stream, uint32 from, uint32 to) { + Audio::SeekableAudioStream *seekStream = dynamic_cast<Audio::SeekableAudioStream *>(&stream); + Audio::SubSeekableAudioStream *subSeekStream = new Audio::SubSeekableAudioStream(seekStream, Audio::Timestamp(from, seekStream->getRate()), Audio::Timestamp(to, seekStream->getRate())); + + _mixer->playStream(Audio::Mixer::kSFXSoundType, _scriptSound, subSeekStream); +} + +bool DirectorSound::isChannelActive(uint8 channelID) { + if (channelID == 1) { + return _mixer->isSoundHandleActive(*_sound1); + } else if (channelID == 2) { + return _mixer->isSoundHandleActive(*_sound2); + } + + error("Incorrect sound channel"); + + return false; +} + +void DirectorSound::stopSound() { + _mixer->stopHandle(*_sound1); + _mixer->stopHandle(*_sound2); +} + +} //End of namespace Director diff --git a/engines/director/sound.h b/engines/director/sound.h new file mode 100644 index 0000000000..850842be21 --- /dev/null +++ b/engines/director/sound.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. +* +*/ + +#include "audio/audiostream.h" +#include "audio/mixer.h" + +#ifndef DIRECTOR_SOUND_H +#define DIRECTOR_SOUND_H + +namespace Director { + +class DirectorSound { + +private: + Audio::SoundHandle *_sound1; + Audio::SoundHandle *_sound2; + Audio::SoundHandle *_scriptSound; + Audio::Mixer *_mixer; + +public: + DirectorSound(); + ~DirectorSound(); + + void playWAV(Common::String filename, uint8 channelID); + void playAIFF(Common::String filename, uint8 channelID); + void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to); + bool isChannelActive(uint8 channelID); + void stopSound(); +}; + +} // End of namespace Director + +#endif diff --git a/engines/director/sprite.cpp b/engines/director/sprite.cpp new file mode 100644 index 0000000000..77d53ae1da --- /dev/null +++ b/engines/director/sprite.cpp @@ -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. + * + */ + +#include "director/director.h" +#include "director/score.h" +#include "director/sprite.h" + +namespace Director { + +Sprite::Sprite() { + _enabled = false; + _trails = 0; + _width = 0; + _ink = kInkTypeCopy; + _flags = 0; + _height = 0; + _castId = 0; + _constraint = 0; + _moveable = 0; + _castId = 0; + _backColor = 0; + _foreColor = 0; + _left = 0; + _right = 0; + _top = 0; + _bottom = 0; + _visible = false; + _movieRate = 0; + _movieTime = 0; + _startTime = 0; + _stopTime = 0; + _volume = 0; + _stretch = 0; + _type = kInactiveSprite; + + _cast = nullptr; + _blend = 0; + _lineSize = 1; +} + +Sprite::Sprite(const Sprite &sprite) { + _enabled = sprite._enabled; + _castId = sprite._castId; + _flags = sprite._flags; + _trails = sprite._trails; + _ink = sprite._ink; + _width = sprite._width; + _height = sprite._height; + _startPoint.x = sprite._startPoint.x; + _startPoint.y = sprite._startPoint.y; + _backColor = sprite._backColor; + _foreColor = sprite._foreColor; + _left = sprite._left; + _right = sprite._right; + _top = sprite._top; + _bottom = sprite._bottom; + _visible = sprite._visible; + _movieRate = sprite._movieRate; + _movieTime = sprite._movieTime; + _stopTime = sprite._stopTime; + _volume = sprite._volume; + _stretch = sprite._stretch; + _type = sprite._type; + + _cast = sprite._cast; + _constraint = sprite._constraint; + _moveable = sprite._moveable; + _blend = sprite._blend; + _startTime = sprite._startTime; + _lineSize = sprite._lineSize; +} + +Sprite::~Sprite() { + delete _cast; +} + +} //End of namespace Director diff --git a/engines/director/sprite.h b/engines/director/sprite.h new file mode 100644 index 0000000000..c66c66d6e4 --- /dev/null +++ b/engines/director/sprite.h @@ -0,0 +1,137 @@ +/* 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 DIRECTOR_SPRITE_H +#define DIRECTOR_SPRITE_H + +#include "common/rect.h" + +namespace Director { + +enum InkType { + kInkTypeCopy, + kInkTypeTransparent, + kInkTypeReverse, + kInkTypeGhost, + kInkTypeNotCopy, + kInkTypeNotTrans, + kInkTypeNotReverse, + kInkTypeNotGhost, + kInkTypeMatte, + kInkTypeMask, + //10-31 Not used (Lingo in a Nutshell) + kInkTypeBlend = 32, + kInkTypeAddPin, + kInkTypeAdd, + kInkTypeSubPin, + kInkTypeBackgndTrans, + kInkTypeLight, + kInkTypeSub, + kInkTypeDark +}; + +//Director v4 +enum SpriteType { + kInactiveSprite, //turns the sprite off + kBitmapSprite, + kRectangleSprite, + kRoundedRectangleSprite, + kOvalSprite, + kLineTopBottomSprite, //line from top left to bottom right + kLineBottomTopSprite, //line from bottom left to top right + kTextSprite, + kButtonSprite, + kCheckboxSprite, + kRadioButtonSprite, + kUndeterminedSprite = 16 //use castType property to examine the type of cast member associated with sprite +}; + +enum SpritePosition { + kSpritePositionUnk1 = 0, + kSpritePositionEnabled, + kSpritePositionUnk2, + kSpritePositionFlags = 4, + kSpritePositionCastId = 6, + kSpritePositionY = 8, + kSpritePositionX = 10, + kSpritePositionHeight = 12, + kSpritePositionWidth = 14 +}; + +enum MainChannelsPosition { + kScriptIdPosition = 0, + kSoundType1Position, + kTransFlagsPosition, + kTransChunkSizePosition, + kTempoPosition, + kTransTypePosition, + kSound1Position, + kSkipFrameFlagsPosition = 8, + kBlendPosition, + kSound2Position, + kSound2TypePosition = 11, + kPaletePosition = 15 +}; + +class Sprite { +public: + Sprite(); + Sprite(const Sprite &sprite); + ~Sprite(); + bool _enabled; + byte _castId; + InkType _ink; + uint16 _trails; + Cast *_cast; + uint16 _flags; + Common::Point _startPoint; + uint16 _width; + uint16 _height; + //TODO: default constraint = 0, if turned on, sprite is constrainted to the bounding rect + //As i know, constrainted != 0 only if sprite moveable + byte _constraint; + byte _moveable; + byte _backColor; + byte _foreColor; + uint16 _left; + uint16 _right; + uint16 _top; + uint16 _bottom; + byte _blend; + bool _visible; + SpriteType _type; + //Using in digital movie sprites + byte _movieRate; + uint16 _movieTime; + uint16 _startTime; + uint16 _stopTime; + byte _volume; + byte _stretch; + //Using in shape sprites + byte _lineSize; + //Using in text sprites + Common::String _editableText; +}; + +} //End of namespace Director + +#endif diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index b40d61a04f..e3a97bf59a 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -71,18 +71,6 @@ const uint kDubbingFrequency = 22050; DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _rnd("draci") { - - // Put your engine in a sane state, but do nothing big yet; - // in particular, do not load data from files; rather, if you - // need to do such things, do them from init(). - - // Do not initialize graphics here - - // However this is the place to specify all default directories - //const Common::FSNode gameDataDir(ConfMan.get("path")); - //SearchMan.addSubDirectoryMatching(gameDataDir, "sound"); - - // Here is the right place to set up the engine specific debug levels DebugMan.addDebugChannel(kDraciGeneralDebugLevel, "general", "Draci general debug info"); DebugMan.addDebugChannel(kDraciBytecodeDebugLevel, "bytecode", "GPL bytecode instructions"); DebugMan.addDebugChannel(kDraciArchiverDebugLevel, "archiver", "BAR archiver debug info"); diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index 0514c6e889..a10403c0e1 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -46,12 +46,13 @@ DreamWebEngine::DreamWebEngine(OSystem *syst, const DreamWebGameDescription *gam _roomDesc(kNumRoomTexts), _freeDesc(kNumFreeTexts), _personText(kNumPersonTexts) { + DebugMan.addDebugChannel(kDebugAnimation, "Animation", "Animation Debug Flag"); + DebugMan.addDebugChannel(kDebugSaveLoad, "SaveLoad", "Track Save/Load Function"); + _vSyncInterrupt = false; _console = 0; _sound = 0; - DebugMan.addDebugChannel(kDebugAnimation, "Animation", "Animation Debug Flag"); - DebugMan.addDebugChannel(kDebugSaveLoad, "SaveLoad", "Track Save/Load Function"); _speed = 1; _turbo = false; _oldMouseState = 0; diff --git a/engines/fullpipe/mgm.cpp b/engines/fullpipe/anihandler.cpp index ca2ec060e2..71c894b9fe 100644 --- a/engines/fullpipe/mgm.cpp +++ b/engines/fullpipe/anihandler.cpp @@ -29,12 +29,14 @@ namespace Fullpipe { -void MGM::clear() { +void AniHandler::detachAllObjects() { _items.clear(); } -MessageQueue *MGM::genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr) { - int idx = getItemIndexById(ani->_id); +MessageQueue *AniHandler::makeQueue(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr) { + debugC(4, kDebugPathfinding, "AniHandler::makeQueue(*%d, %d, %d, res, point)", ani->_id, staticsIndex, staticsId); + + int idx = getIndex(ani->_id); if (idx == -1) return 0; @@ -60,8 +62,8 @@ MessageQueue *MGM::genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int subidx = startidx + endidx * _items[idx]->statics.size(); if (!_items[idx]->subItems[subidx]->movement) { - clearMovements2(idx); - recalcOffsets(idx, startidx, endidx, 0, 1); + clearVisitsList(idx); + seekWay(idx, startidx, endidx, 0, 1); } if (!_items[idx]->subItems[subidx]->movement) @@ -129,22 +131,26 @@ MGMSubItem::MGMSubItem() { y = 0; } -void MGM::addItem(int objId) { - if (getItemIndexById(objId) == -1) { +void AniHandler::attachObject(int objId) { + debugC(4, kDebugPathfinding, "AniHandler::addItem(%d)", objId); + + if (getIndex(objId) == -1) { MGMItem *item = new MGMItem(); item->objId = objId; _items.push_back(item); } - rebuildTables(objId); + resetData(objId); } -void MGM::rebuildTables(int objId) { - int idx = getItemIndexById(objId); +void AniHandler::resetData(int objId) { + int idx = getIndex(objId); if (idx == -1) return; + debugC(3, kDebugPathfinding, "AniHandler::resetData. (1) movements1 sz: %d movements2 sz: %d", _items[idx]->movements1.size(), _items[idx]->movements2.size()); + _items[idx]->subItems.clear(); _items[idx]->statics.clear(); _items[idx]->movements1.clear(); @@ -155,7 +161,7 @@ void MGM::rebuildTables(int objId) { if (!obj) return; - warning("WWW rebuild. idx: %d, size: %d", idx, obj->_staticsList.size() * obj->_staticsList.size()); + debugC(1, kDebugPathfinding, "WWW rebuild. idx: %d, size: %d", idx, obj->_staticsList.size() * obj->_staticsList.size()); for (uint i = 0; i < obj->_staticsList.size(); i++) { _items[idx]->statics.push_back((Statics *)obj->_staticsList[i]); @@ -163,11 +169,15 @@ void MGM::rebuildTables(int objId) { _items[idx]->subItems.push_back(new MGMSubItem); } - for (uint i = 0; i < obj->_movements.size(); i++) + for (uint i = 0; i < obj->_movements.size(); i++) { _items[idx]->movements1.push_back((Movement *)obj->_movements[i]); + _items[idx]->movements2.push_back(0); + } + + debugC(3, kDebugPathfinding, "AniHandler::resetData. (2) movements1 sz: %d movements2 sz: %d", _items[idx]->movements1.size(), _items[idx]->movements2.size()); } -int MGM::getItemIndexById(int objId) { +int AniHandler::getIndex(int objId) { for (uint i = 0; i < _items.size(); i++) if (_items[i]->objId == objId) return i; @@ -175,57 +185,62 @@ int MGM::getItemIndexById(int objId) { return -1; } -MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { - if (!mgminfo->ani) +MessageQueue *AniHandler::makeRunQueue(MakeQueueStruct *mkQueue) { + debugC(4, kDebugPathfinding, "AniHandler::makeRunQueue(*%d)", mkQueue->ani ? mkQueue->ani->_id : -1); + + if (!mkQueue->ani) return 0; - Movement *mov = mgminfo->ani->_movement; + Movement *mov = mkQueue->ani->_movement; - if (!mov && !mgminfo->ani->_statics) + if (!mov && !mkQueue->ani->_statics) return 0; - if (!(mgminfo->flags & 1)) { + if (!(mkQueue->flags & 1)) { if (mov) - mgminfo->staticsId1 = mov->_staticsObj2->_staticsId; + mkQueue->staticsId1 = mov->_staticsObj2->_staticsId; else - mgminfo->staticsId1 = mgminfo->ani->_statics->_staticsId; + mkQueue->staticsId1 = mkQueue->ani->_statics->_staticsId; } Common::Point point; - if (!(mgminfo->flags & 0x10) || !(mgminfo->flags & 0x20)) { - int nx = mgminfo->ani->_ox; - int ny = mgminfo->ani->_oy; + if (!(mkQueue->flags & 0x10) || !(mkQueue->flags & 0x20)) { + int nx = mkQueue->ani->_ox; + int ny = mkQueue->ani->_oy; - if (mgminfo->ani->_movement) { - mgminfo->ani->calcNextStep(&point); + if (mkQueue->ani->_movement) { + mkQueue->ani->calcNextStep(&point); nx += point.x; ny += point.y; } - if (!(mgminfo->flags & 0x10)) - mgminfo->x2 = nx; + if (!(mkQueue->flags & 0x10)) + mkQueue->x2 = nx; - if (!(mgminfo->flags & 0x20)) - mgminfo->y2 = ny; + if (!(mkQueue->flags & 0x20)) + mkQueue->y2 = ny; } - mov = mgminfo->ani->getMovementById(mgminfo->movementId); + mov = mkQueue->ani->getMovementById(mkQueue->movementId); if (!mov) return 0; - int itemIdx = getItemIndexById(mgminfo->ani->_id); - int subIdx = getStaticsIndexById(itemIdx, mgminfo->staticsId1); + + int itemIdx = getIndex(mkQueue->ani->_id); + int subIdx = getStaticsIndexById(itemIdx, mkQueue->staticsId1); int st2idx = getStaticsIndexById(itemIdx, mov->_staticsObj1->_staticsId); int st1idx = getStaticsIndexById(itemIdx, mov->_staticsObj2->_staticsId); - int subOffset = getStaticsIndexById(itemIdx, mgminfo->staticsId2); + int subOffset = getStaticsIndexById(itemIdx, mkQueue->staticsId2); + + debugC(3, kDebugPathfinding, "AniHandler::genMovement. (1) movements1 sz: %d movements2 sz: %d", _items[itemIdx]->movements1.size(), _items[itemIdx]->movements2.size()); - clearMovements2(itemIdx); - recalcOffsets(itemIdx, subIdx, st2idx, 0, 1); - clearMovements2(itemIdx); - recalcOffsets(itemIdx, st1idx, subOffset, 0, 1); + clearVisitsList(itemIdx); + seekWay(itemIdx, subIdx, st2idx, 0, 1); + clearVisitsList(itemIdx); + seekWay(itemIdx, st1idx, subOffset, 0, 1); MGMSubItem *sub1 = _items[itemIdx]->subItems[subIdx + st2idx * _items[itemIdx]->statics.size()]; MGMSubItem *sub2 = _items[itemIdx]->subItems[st1idx + subOffset * _items[itemIdx]->statics.size()]; @@ -236,8 +251,8 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { if (st1idx != subOffset && !sub2->movement) return 0; - int n1x = mgminfo->x1 - mgminfo->x2 - sub1->x - sub2->x; - int n1y = mgminfo->y1 - mgminfo->y2 - sub1->y - sub2->y; + int n1x = mkQueue->x1 - mkQueue->x2 - sub1->x - sub2->x; + int n1y = mkQueue->y1 - mkQueue->y2 - sub1->y - sub2->y; Common::Point point1; @@ -248,37 +263,37 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { int mult; int len = -1; - if (mgminfo->flags & 0x40) { - mult = mgminfo->field_10; + if (mkQueue->flags & 0x40) { + mult = mkQueue->field_10; len = -1; n2x *= mult; n2y *= mult; } else { - calcLength(&point, mov, n1x, n1y, &mult, &len, 1); + getNumCycles(&point, mov, n1x, n1y, &mult, &len, 1); n2x = point.x; n2y = point.y; } - if (!(mgminfo->flags & 2)) { + if (!(mkQueue->flags & 2)) { len = -1; n2x = mult * point1.x; n1x = mult * point1.x; - mgminfo->x1 = mgminfo->x2 + mult * point1.x + sub1->x + sub2->x; + mkQueue->x1 = mkQueue->x2 + mult * point1.x + sub1->x + sub2->x; } - if (!(mgminfo->flags & 4)) { + if (!(mkQueue->flags & 4)) { n2y = mult * point1.y; n1y = mult * point1.y; len = -1; - mgminfo->y1 = mgminfo->y2 + mult * point1.y + sub1->y + sub2->y; + mkQueue->y1 = mkQueue->y2 + mult * point1.y + sub1->y + sub2->y; } int px = 0; int py = 0; if (sub1->movement) { - px = countPhases(itemIdx, subIdx, st2idx, 1); - py = countPhases(itemIdx, subIdx, st2idx, 2); + px = getFramesCount(itemIdx, subIdx, st2idx, 1); + py = getFramesCount(itemIdx, subIdx, st2idx, 2); } if (mult > 1) { @@ -292,8 +307,8 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { } if (sub2->movement) { - px += countPhases(itemIdx, st1idx, subOffset, 1); - py += countPhases(itemIdx, st1idx, subOffset, 2); + px += getFramesCount(itemIdx, st1idx, subOffset, 1); + py += getFramesCount(itemIdx, st1idx, subOffset, 2); } int dx1 = n1x - n2x; @@ -333,9 +348,9 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { for (int i = subIdx; i != st2idx;) { MGMSubItem *s = _items[itemIdx]->subItems[i + subOffset * _items[itemIdx]->statics.size()]; - ex2 = buildExCommand2(s->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1); + ex2 = createCommand(s->movement, mkQueue->ani->_id, x1, y1, &x2, &y2, -1); ex2->_parId = mq->_id; - ex2->_keyCode = mgminfo->ani->_okeyCode; + ex2->_keyCode = mkQueue->ani->_okeyCode; mq->addExCommandToEnd(ex2); @@ -350,9 +365,9 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { else plen = -1; - ex2 = buildExCommand2(mov, mgminfo->ani->_id, x1, y1, &x2, &y2, plen); + ex2 = createCommand(mov, mkQueue->ani->_id, x1, y1, &x2, &y2, plen); ex2->_parId = mq->_id; - ex2->_keyCode = mgminfo->ani->_okeyCode; + ex2->_keyCode = mkQueue->ani->_okeyCode; mq->addExCommandToEnd(ex2); } @@ -360,28 +375,30 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { for (int j = st1idx; j != subOffset;) { MGMSubItem *s = _items[itemIdx]->subItems[j + subOffset * _items[itemIdx]->statics.size()]; - ex2 = buildExCommand2(s->movement, mgminfo->ani->_id, x1, y1, &x2, &y2, -1); + ex2 = createCommand(s->movement, mkQueue->ani->_id, x1, y1, &x2, &y2, -1); ex2->_parId = mq->_id; - ex2->_keyCode = mgminfo->ani->_okeyCode; + ex2->_keyCode = mkQueue->ani->_okeyCode; mq->addExCommandToEnd(ex2); j = s->staticsIndex; } - ExCommand *ex = new ExCommand(mgminfo->ani->_id, 5, -1, mgminfo->x1, mgminfo->y1, 0, 1, 0, 0, 0); + ExCommand *ex = new ExCommand(mkQueue->ani->_id, 5, -1, mkQueue->x1, mkQueue->y1, 0, 1, 0, 0, 0); - ex->_field_14 = mgminfo->field_1C; - ex->_keyCode = mgminfo->ani->_okeyCode; + ex->_field_14 = mkQueue->field_1C; + ex->_keyCode = mkQueue->ani->_okeyCode; ex->_field_24 = 0; ex->_excFlags |= 3; mq->addExCommandToEnd(ex); + debugC(3, kDebugPathfinding, "AniHandler::genMovement. (2) movements1 sz: %d movements2 sz: %d", _items[itemIdx]->movements1.size(), _items[itemIdx]->movements2.size()); + return mq; } -int MGM::countPhases(int idx, int subIdx, int endIdx, int flag) { +int AniHandler::getFramesCount(int idx, int subIdx, int endIdx, int flag) { int res = 0; if (endIdx < 0) @@ -398,8 +415,10 @@ int MGM::countPhases(int idx, int subIdx, int endIdx, int flag) { return res; } -void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) { - if (getItemIndexById(ani->_id) == -1) +void AniHandler::putObjectToStatics(StaticANIObject *ani, int staticsId) { + debugC(4, kDebugPathfinding, "AniHandler::putObjectToStatics(*%d, %d)", ani->_id, staticsId); + + if (getIndex(ani->_id) == -1) return; if (ani->_movement) { @@ -418,7 +437,7 @@ void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) { if (ani->_statics) { Common::Point point; - getPoint(&point, ani->_id, ani->_statics->_staticsId, staticsId); + getTransitionSize(&point, ani->_id, ani->_statics->_staticsId, staticsId); ani->setOXY(ani->_ox + point.x, ani->_oy + point.y); @@ -426,8 +445,10 @@ void MGM::updateAnimStatics(StaticANIObject *ani, int staticsId) { } } -Common::Point *MGM::getPoint(Common::Point *point, int objectId, int staticsId1, int staticsId2) { - int idx = getItemIndexById(objectId); +Common::Point *AniHandler::getTransitionSize(Common::Point *point, int objectId, int staticsId1, int staticsId2) { + debugC(4, kDebugPathfinding, "AniHandler::getTransitionSize([%d, %d], %d, %d, %d)", point->x, point->y, objectId, staticsId1, staticsId2); + + int idx = getIndex(objectId); if (idx == -1) { point->x = -1; @@ -443,12 +464,12 @@ Common::Point *MGM::getPoint(Common::Point *point, int objectId, int staticsId1, int subidx = st1idx + st2idx * _items[idx]->statics.size(); if (!_items[idx]->subItems[subidx]->movement) { - clearMovements2(idx); - recalcOffsets(idx, st1idx, st2idx, false, true); + clearVisitsList(idx); + seekWay(idx, st1idx, st2idx, false, true); if (!_items[idx]->subItems[subidx]->movement) { - clearMovements2(idx); - recalcOffsets(idx, st1idx, st2idx, true, false); + clearVisitsList(idx); + seekWay(idx, st1idx, st2idx, true, false); } } @@ -467,7 +488,7 @@ Common::Point *MGM::getPoint(Common::Point *point, int objectId, int staticsId1, return point; } -int MGM::getStaticsIndexById(int idx, int16 id) { +int AniHandler::getStaticsIndexById(int idx, int16 id) { if (!_items[idx]->statics.size()) return -1; @@ -479,7 +500,7 @@ int MGM::getStaticsIndexById(int idx, int16 id) { return -1; } -int MGM::getStaticsIndex(int idx, Statics *st) { +int AniHandler::getStaticsIndex(int idx, Statics *st) { if (!_items[idx]->statics.size()) return -1; @@ -491,16 +512,23 @@ int MGM::getStaticsIndex(int idx, Statics *st) { return -1; } -void MGM::clearMovements2(int idx) { - _items[idx]->movements2.clear(); +void AniHandler::clearVisitsList(int idx) { + debugC(2, kDebugPathfinding, "AniHandler::clearVisitsList(%d)", idx); + + for (uint i = 0; i < _items[idx]->movements2.size(); i++) + _items[idx]->movements2[i] = 0; + + debugC(3, kDebugPathfinding, "AniHandler::clearVisitsList. movements1 sz: %d movements2 sz: %d", _items[idx]->movements1.size(), _items[idx]->movements2.size()); } -int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { +int AniHandler::seekWay(int idx, int st1idx, int st2idx, bool flip, bool flop) { MGMItem *item = _items[idx]; int subIdx = st1idx + st2idx * item->statics.size(); + debugC(2, kDebugPathfinding, "AniHandler::seekWay(%d, %d, %d, %d, %d)", idx, st1idx, st2idx, flip, flop); + if (st1idx == st2idx) { - memset(&item->subItems[subIdx], 0, sizeof(item->subItems[subIdx])); + memset(item->subItems[subIdx], 0, sizeof(*(item->subItems[subIdx]))); return 0; } @@ -509,6 +537,8 @@ int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { Common::Point point; + debugC(3, kDebugPathfinding, "AniHandler::seekWay. movements1 sz: %d movements2 sz: %d", item->movements1.size(), item->movements2.size()); + for (uint i = 0; i < item->movements1.size(); i++) { Movement *mov = item->movements1[i]; @@ -519,8 +549,10 @@ int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { item->movements2[i] = 1; int stidx = getStaticsIndex(idx, mov->_staticsObj2); - int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop); + int recalc = seekWay(idx, stidx, st2idx, flip, flop); int sz = mov->_currMovement ? mov->_currMovement->_dynamicPhases.size() : mov->_dynamicPhases.size(); + debugC(1, kDebugPathfinding, "AniHandler::seekWay, want idx: %d, off: %d (%d + %d), sz: %d", idx, stidx + st2idx * _items[idx]->statics.size(), stidx, st2idx, item->subItems.size()); + int newsz = sz + item->subItems[stidx + st2idx * _items[idx]->statics.size()]->field_C; if (recalc < 0) @@ -548,7 +580,7 @@ int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { item->movements2[i] = 1; int stidx = getStaticsIndex(idx, mov->_staticsObj1); - int recalc = recalcOffsets(idx, stidx, st2idx, flip, flop); + int recalc = seekWay(idx, stidx, st2idx, flip, flop); if (recalc < 0) continue; @@ -576,28 +608,30 @@ int MGM::recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop) { return -1; } -int MGM::refreshOffsets(int objectId, int idx1, int idx2) { - int idx = getItemIndexById(objectId); +int AniHandler::getNumMovements(int objectId, int idx1, int idx2) { + debugC(4, kDebugPathfinding, "AniHandler::getNumMovements(%d, %d, %d)", objectId, idx1, idx2); + + int idx = getIndex(objectId); if (idx != -1) { int from = getStaticsIndexById(idx, idx1); int to = getStaticsIndexById(idx, idx2); - warning("WWW 6, want idx: %d, off: %d", idx, from + to * _items[idx]->statics.size()); + debugC(1, kDebugPathfinding, "WWW 6, want idx: %d, off: %d", idx, from + to * _items[idx]->statics.size()); MGMSubItem *sub = _items[idx]->subItems[from + to * _items[idx]->statics.size()]; if (sub->movement) { idx = sub->field_8; } else { - clearMovements2(idx); - idx = recalcOffsets(idx, from, to, 0, 1); + clearVisitsList(idx); + idx = seekWay(idx, from, to, 0, 1); } } return idx; } -Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) { +Common::Point *AniHandler::getNumCycles(Common::Point *pRes, Movement *mov, int x, int y, int *mult, int *len, int flag) { Common::Point point; mov->calcSomeXY(point, 0, -1); @@ -673,7 +707,9 @@ Common::Point *MGM::calcLength(Common::Point *pRes, Movement *mov, int x, int y, return pRes; } -ExCommand2 *MGM::buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len) { +ExCommand2 *AniHandler::createCommand(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len) { + debugC(2, kDebugPathfinding, "AniHandler::createCommand(mov, %d, %d, %d, [%d, %d], [%d, %d], %d)", objId, x1, y1, x2->x, x2->y, y2->x, y2->y, len); + uint cnt; if (mov->_currMovement) diff --git a/engines/fullpipe/mgm.h b/engines/fullpipe/anihandler.h index 13195891da..ae16f91ba8 100644 --- a/engines/fullpipe/mgm.h +++ b/engines/fullpipe/anihandler.h @@ -20,8 +20,8 @@ * */ -#ifndef FULLPIPE_MGM_H -#define FULLPIPE_MGM_H +#ifndef FULLPIPE_ANIHANDLER_H +#define FULLPIPE_ANIHANDLER_H namespace Fullpipe { @@ -50,7 +50,7 @@ struct MGMItem { MGMItem(); }; -struct MGMInfo { +struct MakeQueueStruct { StaticANIObject *ani; int staticsId1; int staticsId2; @@ -63,33 +63,33 @@ struct MGMInfo { int y2; int flags; - MGMInfo() { memset(this, 0, sizeof(MGMInfo)); } + MakeQueueStruct() { memset(this, 0, sizeof(MakeQueueStruct)); } }; -class MGM : public CObject { +class AniHandler : public CObject { public: Common::Array<MGMItem *> _items; public: - void clear(); - void addItem(int objId); - void rebuildTables(int objId); - int getItemIndexById(int objId); + void detachAllObjects(); + void attachObject(int objId); + void resetData(int objId); + int getIndex(int objId); - MessageQueue *genMovement(MGMInfo *mgminfo); - void updateAnimStatics(StaticANIObject *ani, int staticsId); - Common::Point *getPoint(Common::Point *point, int aniId, int staticsId1, int staticsId2); + MessageQueue *makeRunQueue(MakeQueueStruct *mkQueue); + void putObjectToStatics(StaticANIObject *ani, int staticsId); + Common::Point *getTransitionSize(Common::Point *point, int aniId, int staticsId1, int staticsId2); int getStaticsIndexById(int idx, int16 id); int getStaticsIndex(int idx, Statics *st); - void clearMovements2(int idx); - int recalcOffsets(int idx, int st1idx, int st2idx, bool flip, bool flop); - Common::Point *calcLength(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag); - ExCommand2 *buildExCommand2(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len); - MessageQueue *genMQ(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr); - int countPhases(int idx, int subIdx, int subOffset, int flag); - int refreshOffsets(int objectId, int idx1, int idx2); + void clearVisitsList(int idx); + int seekWay(int idx, int st1idx, int st2idx, bool flip, bool flop); + Common::Point *getNumCycles(Common::Point *point, Movement *mov, int x, int y, int *mult, int *len, int flag); + ExCommand2 *createCommand(Movement *mov, int objId, int x1, int y1, Common::Point *x2, Common::Point *y2, int len); + MessageQueue *makeQueue(StaticANIObject *ani, int staticsIndex, int staticsId, int *resStatId, Common::Point **pointArr); + int getFramesCount(int idx, int subIdx, int subOffset, int flag); + int getNumMovements(int objectId, int idx1, int idx2); }; } // End of namespace Fullpipe -#endif /* FULLPIPE_MGM_H */ +#endif /* FULLPIPE_ANIHANDLER_H */ diff --git a/engines/fullpipe/behavior.cpp b/engines/fullpipe/behavior.cpp index c90b2b07da..faef1672ca 100644 --- a/engines/fullpipe/behavior.cpp +++ b/engines/fullpipe/behavior.cpp @@ -83,7 +83,7 @@ void BehaviorManager::updateBehaviors() { if (!_isActive) return; - debug(4, "BehaviorManager::updateBehaviors()"); + debugC(4, kDebugBehavior, "BehaviorManager::updateBehaviors()"); for (uint i = 0; i < _behaviors.size(); i++) { BehaviorInfo *beh = _behaviors[i]; @@ -122,7 +122,7 @@ void BehaviorManager::updateBehaviors() { } void BehaviorManager::updateBehavior(BehaviorInfo *behaviorInfo, BehaviorAnim *entry) { - debug(4, "BehaviorManager::updateBehavior() %d", entry->_movesCount); + debugC(4, kDebugBehavior, "BehaviorManager::updateBehavior() %d", entry->_movesCount); for (int i = 0; i < entry->_movesCount; i++) { BehaviorMove *bhi = entry->_behaviorMoves[i]; if (!(bhi->_flags & 1)) { @@ -144,7 +144,7 @@ void BehaviorManager::updateBehavior(BehaviorInfo *behaviorInfo, BehaviorAnim *e } void BehaviorManager::updateStaticAniBehavior(StaticANIObject *ani, int delay, BehaviorAnim *bhe) { - debug(4, "BehaviorManager::updateStaticAniBehavior(%s)", transCyrillic((byte *)ani->_objectName)); + debugC(4, kDebugBehavior, "BehaviorManager::updateStaticAniBehavior(%s)", transCyrillic((byte *)ani->_objectName)); MessageQueue *mq = 0; @@ -236,7 +236,7 @@ void BehaviorInfo::clear() { } void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) { - debug(4, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName)); + debugC(4, kDebugBehavior, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName)); clear(); _animsCount = 1; @@ -260,7 +260,7 @@ void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) { } void BehaviorInfo::initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani) { - debug(4, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName)); + debugC(4, kDebugBehavior, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName)); clear(); diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index c2aae9ba88..22f2050d16 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -24,6 +24,7 @@ #include "common/archive.h" #include "common/config-manager.h" +#include "common/debug-channels.h" #include "audio/mixer.h" #include "engines/util.h" @@ -47,6 +48,14 @@ FullpipeEngine *g_fp = 0; Vars *g_vars = 0; FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + DebugMan.addDebugChannel(kDebugPathfinding, "path", "Pathfinding"); + DebugMan.addDebugChannel(kDebugDrawing, "drawing", "Drawing"); + DebugMan.addDebugChannel(kDebugLoading, "loading", "Scene loading"); + DebugMan.addDebugChannel(kDebugAnimation, "animation", "Animation"); + DebugMan.addDebugChannel(kDebugBehavior, "behavior", "Behavior"); + DebugMan.addDebugChannel(kDebugMemory, "memory", "Memory management"); + DebugMan.addDebugChannel(kDebugEvents, "events", "Event handling"); + // Setup mixer if (!_mixer->isReady()) { warning("Sound initialization failed."); @@ -131,7 +140,7 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) _scene3 = 0; _movTable = 0; _floaters = 0; - _mgm = 0; + _aniHandler = 0; _globalMessageQueueList = 0; _messageHandlers = 0; @@ -208,7 +217,7 @@ void FullpipeEngine::initialize() { _sceneRect.bottom = 599; _floaters = new Floaters; - _mgm = new MGM; + _aniHandler = new AniHandler; } void FullpipeEngine::restartGame() { @@ -452,7 +461,7 @@ void FullpipeEngine::cleanup() { } void FullpipeEngine::updateScreen() { - debug(4, "FullpipeEngine::updateScreen()"); + debugC(4, kDebugDrawing, "FullpipeEngine::updateScreen()"); _mouseVirtX = _mouseScreenPos.x + _sceneRect.left; _mouseVirtY = _mouseScreenPos.y + _sceneRect.top; diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index fba61aa13b..2012d7a344 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -48,6 +48,16 @@ namespace Fullpipe { enum FullpipeGameFeatures { }; +enum { + kDebugPathfinding = 1 << 0, + kDebugDrawing = 1 << 1, + kDebugLoading = 1 << 2, + kDebugAnimation = 1 << 3, + kDebugMemory = 1 << 4, + kDebugEvents = 1 << 5, + kDebugBehavior = 1 << 6 +}; + class BehaviorManager; class BaseModalObject; class GameLoader; @@ -64,7 +74,7 @@ class GlobalMessageQueueList; struct MessageHandler; class MessageQueue; struct MovTable; -class MGM; +class AniHandler; class NGIArchive; class PictureObject; struct PreloadItem; @@ -200,7 +210,7 @@ public: MovTable *_movTable; Floaters *_floaters; - MGM *_mgm; + AniHandler *_aniHandler; Common::Array<Common::Point *> _arcadeKeys; diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp index 3a0e262f82..1cd51036d0 100644 --- a/engines/fullpipe/gameloader.cpp +++ b/engines/fullpipe/gameloader.cpp @@ -110,10 +110,10 @@ GameLoader::~GameLoader() { } bool GameLoader::load(MfcArchive &file) { - debug(1, "GameLoader::load()"); + debugC(1, kDebugLoading, "GameLoader::load()"); _gameName = file.readPascalString(); - debug(1, "_gameName: %s", _gameName); + debugC(1, kDebugLoading, "_gameName: %s", _gameName); _gameProject = new GameProject(); @@ -126,13 +126,13 @@ bool GameLoader::load(MfcArchive &file) { } _gameName = file.readPascalString(); - debug(1, "_gameName: %s", _gameName); + debugC(1, kDebugLoading, "_gameName: %s", _gameName); _inventory.load(file); _interactionController->load(file); - debug(1, "sceneTag count: %d", _gameProject->_sceneTagList->size()); + debugC(1, kDebugLoading, "sceneTag count: %d", _gameProject->_sceneTagList->size()); _sc2array.resize(_gameProject->_sceneTagList->size()); @@ -142,7 +142,7 @@ bool GameLoader::load(MfcArchive &file) { snprintf(tmp, 11, "%04d.sc2", it->_sceneId); - debug(1, "sc: %s", tmp); + debugC(1, kDebugLoading, "sc: %s", tmp); _sc2array[i].loadFile((const char *)tmp); } @@ -152,7 +152,7 @@ bool GameLoader::load(MfcArchive &file) { _field_FA = file.readUint16LE(); _field_F8 = file.readUint16LE(); - debug(1, "_field_FA: %d\n_field_F8: %d", _field_FA, _field_F8); + debugC(1, kDebugLoading, "_field_FA: %d\n_field_F8: %d", _field_FA, _field_F8); _gameVar = (GameVar *)file.readClass(); @@ -357,7 +357,7 @@ bool preloadCallback(PreloadItem &pre, int flag) { } bool GameLoader::preloadScene(int sceneId, int entranceId) { - debug(0, "preloadScene(%d, %d), ", sceneId, entranceId); + debugC(0, kDebugLoading, "preloadScene(%d, %d), ", sceneId, entranceId); if (_preloadSceneId != sceneId || _preloadEntranceId != entranceId) { _preloadSceneId = sceneId; @@ -455,13 +455,13 @@ void GameLoader::applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAni if (picAniInfoCount <= 0) return; - debug(0, "GameLoader::applyPicAniInfos(sc, ptr, %d)", picAniInfoCount); + debugC(0, kDebugAnimation, "GameLoader::applyPicAniInfos(sc, ptr, %d)", picAniInfoCount); PictureObject *pict; StaticANIObject *ani; for (int i = 0; i < picAniInfoCount; i++) { - debug(7, "PicAniInfo: id: %d type: %d", picAniInfo[i]->objectId, picAniInfo[i]->type); + debugC(7, kDebugAnimation, "PicAniInfo: id: %d type: %d", picAniInfo[i]->objectId, picAniInfo[i]->type); if (picAniInfo[i]->type & 2) { pict = sc->getPictureObjectById(picAniInfo[i]->objectId, picAniInfo[i]->field_8); if (pict) { @@ -551,14 +551,14 @@ Sc2::Sc2() { } bool Sc2::load(MfcArchive &file) { - debug(5, "Sc2::load()"); + debugC(5, kDebugLoading, "Sc2::load()"); _sceneId = file.readUint16LE(); _motionController = (MotionController *)file.readClass(); _count1 = file.readUint32LE(); - debug(4, "count1: %d", _count1); + debugC(4, kDebugLoading, "count1: %d", _count1); if (_count1 > 0) { _data1 = (int32 *)malloc(_count1 * sizeof(int32)); @@ -570,7 +570,7 @@ bool Sc2::load(MfcArchive &file) { } _defPicAniInfosCount = file.readUint32LE(); - debug(4, "defPicAniInfos: %d", _defPicAniInfosCount); + debugC(4, kDebugLoading, "defPicAniInfos: %d", _defPicAniInfosCount); if (_defPicAniInfosCount > 0) { _defPicAniInfos = (PicAniInfo **)malloc(_defPicAniInfosCount * sizeof(PicAniInfo *)); @@ -587,7 +587,7 @@ bool Sc2::load(MfcArchive &file) { _picAniInfosCount = 0; _entranceDataCount = file.readUint32LE(); - debug(4, "_entranceData: %d", _entranceDataCount); + debugC(4, kDebugLoading, "_entranceData: %d", _entranceDataCount); if (_entranceDataCount > 0) { _entranceData = (EntranceInfo **)malloc(_entranceDataCount * sizeof(EntranceInfo *)); @@ -607,7 +607,7 @@ bool Sc2::load(MfcArchive &file) { } bool PreloadItems::load(MfcArchive &file) { - debug(5, "PreloadItems::load()"); + debugC(5, kDebugLoading, "PreloadItems::load()"); int count = file.readCount(); diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index 42846850ca..174f66a3c8 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -58,7 +58,7 @@ Background::~Background() { } bool Background::load(MfcArchive &file) { - debug(5, "Background::load()"); + debugC(5, kDebugLoading, "Background::load()"); _bgname = file.readPascalString(); int count = file.readUint16LE(); @@ -80,7 +80,7 @@ bool Background::load(MfcArchive &file) { _bigPictureArray = (BigPicture ***)calloc(_bigPictureArray1Count, sizeof(BigPicture **)); - debug(6, "bigPictureArray[%d][%d]", _bigPictureArray1Count, _bigPictureArray2Count); + debugC(6, kDebugLoading, "bigPictureArray[%d][%d]", _bigPictureArray1Count, _bigPictureArray2Count); for (int i = 0; i < _bigPictureArray1Count; i++) { _bigPictureArray[i] = (BigPicture **)calloc(_bigPictureArray2Count, sizeof(BigPicture *)); @@ -137,7 +137,7 @@ PictureObject::PictureObject(PictureObject *src) : GameObject(src) { } bool PictureObject::load(MfcArchive &file, bool bigPicture) { - debug(5, "PictureObject::load()"); + debugC(5, kDebugLoading, "PictureObject::load()"); GameObject::load(file); if (bigPicture) @@ -282,7 +282,7 @@ GameObject::~GameObject() { } bool GameObject::load(MfcArchive &file) { - debug(5, "GameObject::load()"); + debugC(5, kDebugLoading, "GameObject::load()"); _okeyCode = 0; _flags = 0; _field_20 = 0; @@ -464,7 +464,7 @@ Picture::~Picture() { } void Picture::freePicture() { - debug(5, "Picture::freePicture(): file: %s", _memfilename); + debugC(5, kDebugMemory, "Picture::freePicture(): file: %s", _memfilename); if (_bitmap) { if (testFlags() && !_field_54) { @@ -492,7 +492,7 @@ void Picture::freePixelData() { } bool Picture::load(MfcArchive &file) { - debug(5, "Picture::load()"); + debugC(5, kDebugLoading, "Picture::load()"); MemoryObject::load(file); _x = file.readUint32LE(); @@ -526,7 +526,7 @@ bool Picture::load(MfcArchive &file) { getData(); - debug(5, "Picture::load: loaded <%s>", _memfilename); + debugC(5, kDebugLoading, "Picture::load: loaded <%s>", _memfilename); return true; } @@ -546,7 +546,7 @@ void Picture::setAOIDs() { } void Picture::init() { - debug(5, "Picture::init(), %s", _memfilename); + debugC(5, kDebugLoading, "Picture::init(), %s", _memfilename); MemoryObject::getData(); @@ -567,7 +567,7 @@ Common::Point *Picture::getDimensions(Common::Point *p) { void Picture::getDibInfo() { int off = _dataSize & ~0xf; - debug(9, "Picture::getDibInfo: _dataSize: %d", _dataSize); + debugC(9, kDebugLoading, "Picture::getDibInfo: _dataSize: %d", _dataSize); if (!_dataSize) { warning("Picture::getDibInfo(): Empty data size"); @@ -605,7 +605,7 @@ void Picture::draw(int x, int y, int style, int angle) { int x1 = x; int y1 = y; - debug(7, "Picture::draw(%d, %d, %d, %d) (%s)", x, y, style, angle, _memfilename); + debugC(7, kDebugDrawing, "Picture::draw(%d, %d, %d, %d) (%s)", x, y, style, angle, _memfilename); if (x != -1) x1 = x; @@ -620,7 +620,7 @@ void Picture::draw(int x, int y, int style, int angle) { return; if ((_alpha & 0xff) < 0xff) { - debug(7, "Picture:draw: alpha = %0x", _alpha); + debugC(7, kDebugDrawing, "Picture:draw: alpha = %0x", _alpha); } byte *pal = _paletteData; @@ -784,7 +784,7 @@ Bitmap::~Bitmap() { } void Bitmap::load(Common::ReadStream *s) { - debug(5, "Bitmap::load()"); + debugC(5, kDebugLoading, "Bitmap::load()"); _x = s->readUint32LE(); _y = s->readUint32LE(); @@ -795,8 +795,8 @@ void Bitmap::load(Common::ReadStream *s) { _dataSize = s->readUint32LE(); _flags = s->readUint32LE(); - debug(8, "Bitmap: x: %d y: %d w: %d h: %d dataSize: 0x%x", _x, _y, _width, _height, _dataSize); - debug(8, "Bitmap: type: %s (0x%04x) flags: 0x%x", Common::tag2string(_type).c_str(), _type, _flags); + debugC(8, kDebugLoading, "Bitmap: x: %d y: %d w: %d h: %d dataSize: 0x%x", _x, _y, _width, _height, _dataSize); + debugC(8, kDebugLoading, "Bitmap: type: %s (0x%04x) flags: 0x%x", Common::tag2string(_type).c_str(), _type, _flags); } bool Bitmap::isPixelHitAtPos(int x, int y) { @@ -806,7 +806,7 @@ bool Bitmap::isPixelHitAtPos(int x, int y) { if (!_surface) return false; - return ((*((int32 *)_surface->getBasePtr(x, y)) & 0xff000000) != 0); + return ((*((int32 *)_surface->getBasePtr(x - _x, y - _y)) & 0xff000000) != 0); } void Bitmap::decode(int32 *palette) { @@ -821,7 +821,7 @@ void Bitmap::decode(int32 *palette) { } void Bitmap::putDib(int x, int y, int32 *palette, int alpha) { - debug(7, "Bitmap::putDib(%d, %d)", x, y); + debugC(7, kDebugDrawing, "Bitmap::putDib(%d, %d)", x, y); int x1 = x - g_fp->_sceneRect.left; int y1 = y - g_fp->_sceneRect.top; @@ -868,11 +868,11 @@ bool Bitmap::putDibRB(int32 *palette) { uint16 *srcPtr; if (!palette) { - debug(2, "Bitmap::putDibRB(): Both global and local palettes are empty"); + debugC(2, kDebugDrawing, "Bitmap::putDibRB(): Both global and local palettes are empty"); return false; } - debug(8, "Bitmap::putDibRB()"); + debugC(8, kDebugDrawing, "Bitmap::putDibRB()"); endy = _height - 1; @@ -1122,18 +1122,20 @@ void Bitmap::copier(uint32 *dest, byte *src, int len, int32 *palette, bool cb05_ } Bitmap *Bitmap::reverseImage(bool flip) { + Bitmap *b = new Bitmap(this); + if (flip) - _flipping = Graphics::FLIP_H; - else - _flipping = Graphics::FLIP_NONE; + b->_flipping ^= Graphics::FLIP_H; - return this; + return b; } Bitmap *Bitmap::flipVertical() { - _flipping = Graphics::FLIP_V; + Bitmap *b = new Bitmap(this); + + b->_flipping ^= Graphics::FLIP_V; - return this; + return b; } void Bitmap::drawShaded(int type, int x, int y, byte *palette, int alpha) { @@ -1149,7 +1151,7 @@ void Bitmap::drawRotated(int x, int y, int angle, byte *palette, int alpha) { } bool BigPicture::load(MfcArchive &file) { - debug(5, "BigPicture::load()"); + debugC(5, kDebugLoading, "BigPicture::load()"); Picture::load(file); return true; @@ -1190,7 +1192,7 @@ Shadows::Shadows() { } bool Shadows::load(MfcArchive &file) { - debug(5, "Shadows::load()"); + debugC(5, kDebugLoading, "Shadows::load()"); _sceneId = file.readUint32LE(); _staticAniObjectId = file.readUint32LE(); _movementId = file.readUint32LE(); diff --git a/engines/fullpipe/interaction.cpp b/engines/fullpipe/interaction.cpp index 4aac3485f4..f0abd0d02c 100644 --- a/engines/fullpipe/interaction.cpp +++ b/engines/fullpipe/interaction.cpp @@ -62,7 +62,7 @@ InteractionController::~InteractionController() { } bool InteractionController::load(MfcArchive &file) { - debug(5, "InteractionController::load()"); + debugC(5, kDebugLoading, "InteractionController::load()"); return _interactions.load(file); } @@ -143,7 +143,8 @@ bool InteractionController::handleInteraction(StaticANIObject *subj, GameObject obj->setPicAniInfo(&aniInfo); if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1) { - mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->doWalkTo(subj, xpos, ypos, 1, cinter->_staticsId2); + debugC(0, kDebugPathfinding, "Calling makeQueue() at [%d, %d]", xpos, ypos); + mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->makeQueue(subj, xpos, ypos, 1, cinter->_staticsId2); if (mq) { dur = mq->calcDuration(subj); delete mq; @@ -304,7 +305,7 @@ LABEL_38: ani->changeStatics2(inter->_staticsId1); } - int xpos = inter->_yOffs + obj->_ox; + int xpos = inter->_xOffs + obj->_ox; int ypos = inter->_yOffs + obj->_oy; obj->setPicAniInfo(&aniInfo); @@ -440,7 +441,7 @@ Interaction::~Interaction() { } bool Interaction::load(MfcArchive &file) { - debug(5, "Interaction::load()"); + debugC(5, kDebugLoading, "Interaction::load()"); _objectId1 = file.readUint16LE(); _objectId2 = file.readUint16LE(); @@ -531,7 +532,7 @@ bool Interaction::isOverlapping(StaticANIObject *subj, GameObject *obj) { } bool EntranceInfo::load(MfcArchive &file) { - debug(5, "EntranceInfo::load()"); + debugC(5, kDebugLoading, "EntranceInfo::load()"); _sceneId = file.readUint32LE(); _field_4 = file.readUint32LE(); diff --git a/engines/fullpipe/inventory.cpp b/engines/fullpipe/inventory.cpp index f9b507c50b..aa229d55d7 100644 --- a/engines/fullpipe/inventory.cpp +++ b/engines/fullpipe/inventory.cpp @@ -35,7 +35,7 @@ Inventory::~Inventory() { } bool Inventory::load(MfcArchive &file) { - debug(5, "Inventory::load()"); + debugC(5, kDebugLoading, "Inventory::load()"); _sceneId = file.readUint16LE(); int numInvs = file.readUint32LE(); diff --git a/engines/fullpipe/lift.cpp b/engines/fullpipe/lift.cpp index d066c89d4a..93bfbaaa24 100644 --- a/engines/fullpipe/lift.cpp +++ b/engines/fullpipe/lift.cpp @@ -392,7 +392,8 @@ void FullpipeEngine::lift_clickButton() { lift_walkAndGo(); } -void FullpipeEngine::lift_goAnimation() { if (_lastLiftButton) { +void FullpipeEngine::lift_goAnimation() { + if (_lastLiftButton) { int parentId = _currentScene->_sceneId; int buttonId = lift_getButtonIdN(_lastLiftButton->_statics->_staticsId); @@ -428,6 +429,8 @@ void FullpipeEngine::lift_goAnimation() { if (_lastLiftButton) { delete mq; _aniMan->_flags |= 1; + + return; } } } diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp index b9c79963f2..c40af3b062 100644 --- a/engines/fullpipe/messagehandlers.cpp +++ b/engines/fullpipe/messagehandlers.cpp @@ -100,7 +100,7 @@ void global_messageHandler_KickMetal() { } int global_messageHandler1(ExCommand *cmd) { - debug(5, "global_messageHandler1: %d %d", cmd->_messageKind, cmd->_messageNum); + debugC(5, kDebugEvents, "global_messageHandler1: %d %d", cmd->_messageKind, cmd->_messageNum); if (cmd->_excFlags & 0x10000) { if (cmd->_messageNum == MV_MAN_TOLADDER) @@ -364,7 +364,7 @@ int global_messageHandler3(ExCommand *cmd) { case 17: switch (cmd->_messageNum) { case 61: - debug(0, "preload: { %d, %d },", cmd->_parentId, cmd->_keyCode); + debugC(0, kDebugEvents, "preload: { %d, %d },", cmd->_parentId, cmd->_keyCode); return g_fp->_gameLoader->preloadScene(cmd->_parentId, cmd->_keyCode); case 62: return g_fp->_gameLoader->gotoScene(cmd->_parentId, cmd->_keyCode); @@ -425,7 +425,7 @@ int global_messageHandler3(ExCommand *cmd) { if (g_fp->_msgX != cmd->_sceneClickX || g_fp->_msgY != cmd->_sceneClickY) { ani = g_fp->_currentScene->getStaticANIObject1ById(g_fp->_gameLoader->_field_FA, -1); if (!ani || (ani->isIdle() && !(ani->_flags & 0x80) && !(ani->_flags & 0x100))) { - warning("WWW 1"); + debugC(0, kDebugPathfinding, "WWW 1"); result = startWalkTo(g_fp->_gameLoader->_field_FA, -1, cmd->_sceneClickX, cmd->_sceneClickY, 0); if (result) { ExCommand *ex = new ExCommand(g_fp->_gameLoader->_field_FA, 17, 64, 0, 0, 0, 1, 0, 0, 0); diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index a7337b98ed..9085e92832 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -57,7 +57,7 @@ ExCommand::ExCommand(int16 parentId, int messageKind, int messageNum, int x, int } bool ExCommand::load(MfcArchive &file) { - debug(5, "ExCommand::load()"); + debugC(5, kDebugLoading, "ExCommand::load()"); _parentId = file.readUint16LE(); _messageKind = file.readUint32LE(); @@ -247,7 +247,7 @@ ObjstateCommand::~ObjstateCommand() { } bool ObjstateCommand::load(MfcArchive &file) { - debug(5, "ObjStateCommand::load()"); + debugC(5, kDebugLoading, "ObjStateCommand::load()"); _objtype = kObjTypeObjstateCommand; @@ -341,7 +341,7 @@ MessageQueue::~MessageQueue() { } bool MessageQueue::load(MfcArchive &file) { - debug(5, "MessageQueue::load()"); + debugC(5, kDebugLoading, "MessageQueue::load()"); _dataId = file.readUint16LE(); @@ -457,7 +457,7 @@ void MessageQueue::deleteExCommandByIndex(uint idx, bool doFree) { _exCommands.erase(it); } -void MessageQueue::transferExCommands(MessageQueue *mq) { +void MessageQueue::mergeQueue(MessageQueue *mq) { // Original belongs to AniHandler while (mq->_exCommands.size()) { _exCommands.push_back(mq->_exCommands.front()); mq->_exCommands.pop_front(); diff --git a/engines/fullpipe/messages.h b/engines/fullpipe/messages.h index e6f7f05150..67fbb2a6cd 100644 --- a/engines/fullpipe/messages.h +++ b/engines/fullpipe/messages.h @@ -142,7 +142,7 @@ class MessageQueue : public CObject { ExCommand *getExCommandByIndex(uint idx); void deleteExCommandByIndex(uint idx, bool doFree); - void transferExCommands(MessageQueue *mq); + void mergeQueue(MessageQueue *mq); void replaceKeyCode(int key1, int key2); diff --git a/engines/fullpipe/module.mk b/engines/fullpipe/module.mk index 96bd91fd39..01aba1bd82 100644 --- a/engines/fullpipe/module.mk +++ b/engines/fullpipe/module.mk @@ -1,6 +1,7 @@ MODULE := engines/fullpipe MODULE_OBJS = \ + anihandler.o \ behavior.o \ console.o \ detection.o \ @@ -15,7 +16,6 @@ MODULE_OBJS = \ lift.o \ messagehandlers.o \ messages.o \ - mgm.o \ modal.o \ motion.o \ ngiarchive.o \ diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index 81424db93a..f0166daee0 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -32,7 +32,7 @@ namespace Fullpipe { bool MotionController::load(MfcArchive &file) { // Is originally empty file.readClass(); - debug(5, "MotionController::load()"); + debugC(5, kDebugLoading, "MotionController::load()"); return true; } @@ -42,6 +42,8 @@ void MotionController::enableLinks(const char *linkName, bool enable) { } MovGraphLink *MotionController::getLinkByName(const char *name) { + debugC(4, kDebugPathfinding, "MotionController::getLinkByName(%s)", name); + if (_objtype == kObjTypeMctlCompound) { MctlCompound *obj = (MctlCompound *)this; @@ -80,23 +82,23 @@ MovGraphLink *MotionController::getLinkByName(const char *name) { } bool MctlCompound::load(MfcArchive &file) { - debug(5, "MctlCompound::load()"); + debugC(5, kDebugLoading, "MctlCompound::load()"); int count = file.readUint32LE(); - debug(6, "MctlCompound::count = %d", count); + debugC(6, kDebugLoading, "MctlCompound::count = %d", count); for (int i = 0; i < count; i++) { - debug(6, "CompoundArray[%d]", i); + debugC(6, kDebugLoading, "CompoundArray[%d]", i); MctlItem *obj = new MctlItem(); obj->_motionControllerObj = (MotionController *)file.readClass(); int count1 = file.readUint32LE(); - debug(6, "ConnectionPoint::count: %d", count1); + debugC(6, kDebugLoading, "ConnectionPoint::count: %d", count1); for (int j = 0; j < count1; j++) { - debug(6, "ConnectionPoint[%d]", j); + debugC(6, kDebugLoading, "ConnectionPoint[%d]", j); MctlConnectionPoint *obj1 = (MctlConnectionPoint *)file.readClass(); obj->_connectionPoints.push_back(obj1); @@ -105,7 +107,7 @@ bool MctlCompound::load(MfcArchive &file) { obj->_field_20 = file.readUint32LE(); obj->_field_24 = file.readUint32LE(); - debug(6, "graphReact"); + debugC(6, kDebugLoading, "graphReact"); obj->_movGraphReactObj = (MovGraphReact *)file.readClass(); _motionControllers.push_back(obj); @@ -115,28 +117,34 @@ bool MctlCompound::load(MfcArchive &file) { } void MctlCompound::attachObject(StaticANIObject *obj) { + debugC(4, kDebugPathfinding, "MctlCompound::attachObject(*%d)", obj->_id); + for (uint i = 0; i < _motionControllers.size(); i++) _motionControllers[i]->_motionControllerObj->attachObject(obj); } int MctlCompound::detachObject(StaticANIObject *obj) { + debugC(4, kDebugPathfinding, "MctlCompound::detachObject(*%d)", obj->_id); + for (uint i = 0; i < _motionControllers.size(); i++) _motionControllers[i]->_motionControllerObj->detachObject(obj); return 1; } -void MctlCompound::initMovGraph2() { +void MctlCompound::initMctlGraph() { if (_objtype != kObjTypeMctlCompound) return; + debugC(4, kDebugPathfinding, "MctlCompound::initMctlGraph()"); + for (uint i = 0; i < _motionControllers.size(); i++) { if (_motionControllers[i]->_motionControllerObj->_objtype != kObjTypeMovGraph) continue; MovGraph *gr = (MovGraph *)_motionControllers[i]->_motionControllerObj; - MovGraph2 *newgr = new MovGraph2(); + MctlGraph *newgr = new MctlGraph(); newgr->_links = gr->_links; newgr->_nodes = gr->_nodes; @@ -151,6 +159,8 @@ void MctlCompound::initMovGraph2() { } void MctlCompound::detachAllObjects() { + debugC(4, kDebugPathfinding, "MctlCompound::detachAllObjects()"); + for (uint i = 0; i < _motionControllers.size(); i++) _motionControllers[i]->_motionControllerObj->detachAllObjects(); } @@ -159,6 +169,8 @@ MessageQueue *MctlCompound::startMove(StaticANIObject *ani, int sourceX, int sou int idx = -1; int sourceIdx = -1; + debugC(4, kDebugPathfinding, "MctlCompound::startMove(*%d, %d, %d, %d, %d)", (ani ? ani->_id : -1), sourceX, sourceY, fuzzyMatch, staticsId); + if (!ani) return 0; @@ -186,7 +198,7 @@ MessageQueue *MctlCompound::startMove(StaticANIObject *ani, int sourceX, int sou if (sourceIdx == -1) return 0; - warning("WWW 2"); + debugC(1, kDebugPathfinding, "WWW 2"); if (idx == sourceIdx) return _motionControllers[idx]->_motionControllerObj->startMove(ani, sourceX, sourceY, fuzzyMatch, staticsId); @@ -196,7 +208,7 @@ MessageQueue *MctlCompound::startMove(StaticANIObject *ani, int sourceX, int sou if (!cp) return 0; - MessageQueue *mq = _motionControllers[idx]->_motionControllerObj->doWalkTo(ani, cp->_connectionX, cp->_connectionY, 1, cp->_mctlmirror); + MessageQueue *mq = _motionControllers[idx]->_motionControllerObj->makeQueue(ani, cp->_connectionX, cp->_connectionY, 1, cp->_mctlmirror); if (!mq) return 0; @@ -225,10 +237,12 @@ MessageQueue *MctlCompound::startMove(StaticANIObject *ani, int sourceX, int sou return mq; } -MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { +MessageQueue *MctlCompound::makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { int match1 = -1; int match2 = -1; + debugC(1, kDebugPathfinding, "MctlCompound::makeQueue(*%d, %d, %d, %d, %d)", (subj ? subj->_id : -1), xpos, ypos, fuzzyMatch, staticsId); + if (!subj) return 0; @@ -257,7 +271,7 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, return 0; if (match1 == match2) - return _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId); + return _motionControllers[match1]->_motionControllerObj->makeQueue(subj, xpos, ypos, fuzzyMatch, staticsId); double dist; MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &dist); @@ -265,7 +279,7 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, if (!closestP) return 0; - MessageQueue *mq = _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, closestP->_connectionX, closestP->_connectionY, 1, closestP->_mctlmirror); + MessageQueue *mq = _motionControllers[match1]->_motionControllerObj->makeQueue(subj, closestP->_connectionX, closestP->_connectionY, 1, closestP->_mctlmirror); ExCommand *ex; @@ -328,11 +342,13 @@ int MctlLadder::collisionDetection(StaticANIObject *man) { } void MctlLadder::attachObject(StaticANIObject *obj) { + debugC(4, kDebugPathfinding, "MctlLadder::attachObject(*%d)", obj->_id); + if (findObjectPos(obj) < 0) { MctlLadderMovement *movement = new MctlLadderMovement; if (initMovement(obj, movement)) { - _mgm.addItem(obj->_id); + _aniHandler.attachObject(obj->_id); _ladmovements.push_back(movement); } else { delete movement; @@ -349,6 +365,8 @@ int MctlLadder::findObjectPos(StaticANIObject *obj) { } bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement) { + debugC(4, kDebugPathfinding, "MctlLadder::initMovement(*%d, ...)", ani->_id); + GameVar *v = g_fp->getGameLoaderGameVar()->getSubVarByName(ani->getName()); if (!v) @@ -393,7 +411,9 @@ bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement } void MctlLadder::detachAllObjects() { - _mgm.clear(); + debugC(4, kDebugPathfinding, "MctlLadder::detachAllObjects()"); + + _aniHandler.detachAllObjects(); for (uint i = 0; i < _ladmovements.size(); i++) { delete _ladmovements[i]->movVars; @@ -404,7 +424,9 @@ void MctlLadder::detachAllObjects() { } MessageQueue *MctlLadder::startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { - MessageQueue *mq = doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId); + debugC(4, kDebugPathfinding, "MctlLadder::startMove(*%d, %d, %d, %d, %d)", (subj ? subj->_id : -1), xpos, ypos, fuzzyMatch, staticsId); + + MessageQueue *mq = makeQueue(subj, xpos, ypos, fuzzyMatch, staticsId); if (mq) { if (mq->chain(subj)) @@ -414,7 +436,9 @@ MessageQueue *MctlLadder::startMove(StaticANIObject *subj, int xpos, int ypos, i return 0; } -MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { +MessageQueue *MctlLadder::makeQueue(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { + debugC(1, kDebugPathfinding, "MctlLadder::makeQueue(*%d, %d, %d, %d, %d)", (ani ? ani->_id : -1), xpos, ypos, fuzzyMatch, staticsId); + int pos = findObjectPos(ani); if (pos < 0) @@ -435,7 +459,7 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int int direction = (normy - ani->_oy) < 0 ? 0 : 1; - MGMInfo mgminfo; + MakeQueueStruct mkQueue; PicAniInfo picinfo; MessageQueue *mq; ExCommand *ex; @@ -452,7 +476,7 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int ani->_movement = 0; ani->setOXY(point.x + ox, point.y + oy); - mq = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId); + mq = makeQueue(ani, normx, normy, fuzzyMatch, staticsId); ani->setPicAniInfo(&picinfo); @@ -460,38 +484,38 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int } if (ani->_statics->_staticsId == _ladmovements[pos]->staticIds[0]) { - mgminfo.ani = ani; + mkQueue.ani = ani; if (staticsId) - mgminfo.staticsId2 = staticsId; + mkQueue.staticsId2 = staticsId; else - mgminfo.staticsId2 = _ladmovements[pos]->staticIds[direction]; + mkQueue.staticsId2 = _ladmovements[pos]->staticIds[direction]; - mgminfo.x1 = normx; - mgminfo.y1 = normy; - mgminfo.field_1C = _ladder_field_14; - mgminfo.flags = 14; - mgminfo.movementId = direction ? _ladmovements[pos]->movVars->varDownGo : _ladmovements[pos]->movVars->varUpGo; + mkQueue.x1 = normx; + mkQueue.y1 = normy; + mkQueue.field_1C = _ladder_field_14; + mkQueue.flags = 14; + mkQueue.movementId = direction ? _ladmovements[pos]->movVars->varDownGo : _ladmovements[pos]->movVars->varUpGo; - return _mgm.genMovement(&mgminfo); + return _aniHandler.makeRunQueue(&mkQueue); } if (ani->_statics->_staticsId == _ladmovements[pos]->staticIds[2]) { if (!direction) { - mgminfo.ani = ani; + mkQueue.ani = ani; if (staticsId) - mgminfo.staticsId2 = staticsId; + mkQueue.staticsId2 = staticsId; else - mgminfo.staticsId2 = _ladmovements[pos]->staticIds[0]; + mkQueue.staticsId2 = _ladmovements[pos]->staticIds[0]; - mgminfo.x1 = normx; - mgminfo.y1 = normy; - mgminfo.field_1C = _ladder_field_14; - mgminfo.flags = 14; - mgminfo.movementId = _ladmovements[pos]->movVars->varUpGo; + mkQueue.x1 = normx; + mkQueue.y1 = normy; + mkQueue.field_1C = _ladder_field_14; + mkQueue.flags = 14; + mkQueue.movementId = _ladmovements[pos]->movVars->varUpGo; - return _mgm.genMovement(&mgminfo); + return _aniHandler.makeRunQueue(&mkQueue); } int ox = ani->_ox; @@ -499,23 +523,23 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int ani->getMovementById(_ladmovements[pos]->movVars->varUpStop)->calcSomeXY(point, 0, -1); - mgminfo.ani = ani; + mkQueue.ani = ani; if (staticsId) - mgminfo.staticsId2 = staticsId; + mkQueue.staticsId2 = staticsId; else - mgminfo.staticsId2 = _ladmovements[pos]->staticIds[1]; + mkQueue.staticsId2 = _ladmovements[pos]->staticIds[1]; - mgminfo.field_1C = _ladder_field_14; - mgminfo.x1 = normx; - mgminfo.y1 = normy; - mgminfo.y2 = point.y + oy; - mgminfo.x2 = point.x + ox; - mgminfo.flags = 63; - mgminfo.staticsId1 = _ladmovements[pos]->staticIds[0]; - mgminfo.movementId = _ladmovements[pos]->movVars->varDownGo; + mkQueue.field_1C = _ladder_field_14; + mkQueue.x1 = normx; + mkQueue.y1 = normy; + mkQueue.y2 = point.y + oy; + mkQueue.x2 = point.x + ox; + mkQueue.flags = 63; + mkQueue.staticsId1 = _ladmovements[pos]->staticIds[0]; + mkQueue.movementId = _ladmovements[pos]->movVars->varDownGo; - mq = _mgm.genMovement(&mgminfo); + mq = _aniHandler.makeRunQueue(&mkQueue); ex = new ExCommand(ani->_id, 1, _ladmovements[pos]->movVars->varUpStop, 0, 0, 0, 1, 0, 0, 0); ex->_keyCode = ani->_okeyCode; @@ -527,7 +551,7 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int } if (ani->_statics->_staticsId != _ladmovements[pos]->staticIds[3]) { - mq = _mgm.genMQ(ani, _ladmovements[pos]->staticIds[0], 0, 0, 0); + mq = _aniHandler.makeQueue(ani, _ladmovements[pos]->staticIds[0], 0, 0, 0); if (!mq) return 0; @@ -535,7 +559,7 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int int nx = ani->_ox; int ny = ani->_oy; - _mgm.getPoint(&point, ani->_id, ani->_statics->_staticsId, _ladmovements[pos]->staticIds[0]); + _aniHandler.getTransitionSize(&point, ani->_id, ani->_statics->_staticsId, _ladmovements[pos]->staticIds[0]); nx += point.x; ny += point.y; @@ -546,9 +570,9 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int ani->_movement = 0; ani->setOXY(nx, ny); - MessageQueue *newmq = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId); + MessageQueue *newmq = makeQueue(ani, normx, normy, fuzzyMatch, staticsId); - mq->transferExCommands(newmq); + mq->mergeQueue(newmq); delete newmq; @@ -566,22 +590,22 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int nx += point.x; ny += point.y; - mgminfo.ani = ani; + mkQueue.ani = ani; if (staticsId) - mgminfo.staticsId2 = staticsId; + mkQueue.staticsId2 = staticsId; else - mgminfo.staticsId2 = _ladmovements[pos]->staticIds[0]; + mkQueue.staticsId2 = _ladmovements[pos]->staticIds[0]; - mgminfo.field_1C = _ladder_field_14; - mgminfo.x1 = normx; - mgminfo.y1 = normy; - mgminfo.y2 = ny; - mgminfo.x2 = nx; - mgminfo.flags = 63; - mgminfo.staticsId1 = _ladmovements[pos]->staticIds[1]; - mgminfo.movementId = _ladmovements[pos]->movVars->varUpGo; + mkQueue.field_1C = _ladder_field_14; + mkQueue.x1 = normx; + mkQueue.y1 = normy; + mkQueue.y2 = ny; + mkQueue.x2 = nx; + mkQueue.flags = 63; + mkQueue.staticsId1 = _ladmovements[pos]->staticIds[1]; + mkQueue.movementId = _ladmovements[pos]->movVars->varUpGo; - mq = _mgm.genMovement(&mgminfo); + mq = _aniHandler.makeRunQueue(&mkQueue); ex = new ExCommand(ani->_id, 1, _ladmovements[pos]->movVars->varDownStop, 0, 0, 0, 1, 0, 0, 0); ex->_keyCode = ani->_okeyCode; @@ -593,24 +617,24 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int } - mgminfo.ani = ani; + mkQueue.ani = ani; if (staticsId) - mgminfo.staticsId2 = staticsId; + mkQueue.staticsId2 = staticsId; else - mgminfo.staticsId2 = _ladmovements[pos]->staticIds[1]; + mkQueue.staticsId2 = _ladmovements[pos]->staticIds[1]; - mgminfo.x1 = normx; - mgminfo.y1 = normy; - mgminfo.field_1C = _ladder_field_14; - mgminfo.flags = 14; - mgminfo.movementId = _ladmovements[pos]->movVars->varDownGo; + mkQueue.x1 = normx; + mkQueue.y1 = normy; + mkQueue.field_1C = _ladder_field_14; + mkQueue.flags = 14; + mkQueue.movementId = _ladmovements[pos]->movVars->varDownGo; - return _mgm.genMovement(&mgminfo); + return _aniHandler.makeRunQueue(&mkQueue); } MessageQueue *MctlLadder::controllerWalkTo(StaticANIObject *ani, int off) { - return doWalkTo(ani, _ladderX + off * _width, _ladderY + off * _height, 1, 0); + return makeQueue(ani, _ladderX + off * _width, _ladderY + off * _height, 1, 0); } MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIdx, double *minDistancePtr) { @@ -681,7 +705,7 @@ MctlConnectionPoint::~MctlConnectionPoint() { delete _messageQueueObj; } -MovInfo1::MovInfo1(MovInfo1 *src) { +MctlMQ::MctlMQ(MctlMQ *src) { index = src->index; pt1 = src->pt1; pt2 = src->pt2; @@ -694,7 +718,7 @@ MovInfo1::MovInfo1(MovInfo1 *src) { flags = src->flags; } -void MovInfo1::clear() { +void MctlMQ::clear() { index = 0; pt1.x = pt1.y = 0; pt2.x = pt2.y = 0; @@ -708,11 +732,11 @@ void MovInfo1::clear() { } bool MctlCompoundArray::load(MfcArchive &file) { - debug(5, "MctlCompoundArray::load()"); + debugC(5, kDebugLoading, "MctlCompoundArray::load()"); int count = file.readUint32LE(); - debug(0, "MctlCompoundArray::count = %d", count); + debugC(0, kDebugLoading, "MctlCompoundArray::count = %d", count); assert(0); @@ -771,7 +795,7 @@ MovGraph::~MovGraph() { } bool MovGraph::load(MfcArchive &file) { - debug(5, "MovGraph::load()"); + debugC(5, kDebugLoading, "MovGraph::load()"); _links.load(file); _nodes.load(file); @@ -780,8 +804,10 @@ bool MovGraph::load(MfcArchive &file) { } void MovGraph::attachObject(StaticANIObject *obj) { - _mgm.clear(); - _mgm.addItem(obj->_id); + debugC(4, kDebugPathfinding, "MovGraph::attachObject(*%d)", obj->_id); + + _aniHandler.detachAllObjects(); + _aniHandler.attachObject(obj->_id); for (uint i = 0; i < _items.size(); i++) if (_items[i]->ani == obj) @@ -793,7 +819,7 @@ void MovGraph::attachObject(StaticANIObject *obj) { _items.push_back(item); - _mgm.addItem(obj->_id); // FIXME: Is it really needed? + _aniHandler.attachObject(obj->_id); // FIXME: Is it really needed? } int MovGraph::detachObject(StaticANIObject *obj) { @@ -803,6 +829,8 @@ int MovGraph::detachObject(StaticANIObject *obj) { } void MovGraph::detachAllObjects() { + debugC(4, kDebugPathfinding, "MovGraph::detachAllObjects()"); + for (uint i = 0; i < _items.size(); i++) { _items[i]->free(); @@ -813,6 +841,8 @@ void MovGraph::detachAllObjects() { } Common::Array<MovItem *> *MovGraph::getPaths(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { + debugC(4, kDebugPathfinding, "MovGraph::getPaths(*%d, %d, %d, %d, &rescount)", (ani ? ani->_id : -1), x, y, flag1); + *rescount = 0; if (_items.size() <= 0) @@ -879,6 +909,8 @@ bool MovGraph::setPosImmediate(StaticANIObject *obj, int x, int y) { } MessageQueue *MovGraph::startMove(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { + debugC(4, kDebugPathfinding, "MovGraph::startMove(*%d, %d, %d, %d, %d)", (ani ? ani->_id : -1), xpos, ypos, fuzzyMatch, staticsId); + if (!ani) { if (!_items.size()) return 0; @@ -956,6 +988,8 @@ void MovGraph::setSelFunc(MovArr *(*callback1)(StaticANIObject *ani, Common::Arr } bool MovGraph::resetPosition(StaticANIObject *ani, int flag) { + debugC(4, kDebugPathfinding, "MovGraph::resetPosition(*%d, %d)", (ani ? ani->_id : -1), flag); + int idx = getObjectIndex(ani); if (idx == -1) @@ -974,8 +1008,8 @@ bool MovGraph::resetPosition(StaticANIObject *ani, int flag) { Statics *st; if (ani->_statics) { - int t = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44]); - if (t > _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44 + 1])) + int t = _aniHandler.getNumMovements(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44]); + if (t > _aniHandler.getNumMovements(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44 + 1])) st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44 + 1]); else st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]); @@ -1017,7 +1051,9 @@ bool MovGraph::canDropInventory(StaticANIObject *ani, int x, int y) { return false; } -MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { +MessageQueue *MovGraph::makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { + debugC(1, kDebugPathfinding, "MovGraph::makeQueue(*%d, %d, %d, %d, %d)", (subj ? subj->_id : -1), xpos, ypos, fuzzyMatch, staticsId); + PicAniInfo picAniInfo; int ss; @@ -1096,6 +1132,8 @@ MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int } MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x1, int y1, int stid2, int flag1) { + debugC(4, kDebugPathfinding, "MovGraph::sub1(*%d, %d, %d, %d, %d, %d, %d, %d)", (ani ? ani->_id : -1), x, y, stid, x1, y1, stid2, flag1); + PicAniInfo picinfo; ani->getPicAniInfo(&picinfo); @@ -1142,6 +1180,8 @@ MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x } MessageQueue *MovGraph::makeWholeQueue(StaticANIObject *ani, MovArr *movarr, int staticsId) { + debugC(4, kDebugPathfinding, "MovGraph::makeWholeQueue(*%d, *, %d)", (ani ? ani->_id : -1), staticsId); + if (!movarr->_movStepCount) return 0; @@ -1190,28 +1230,28 @@ MessageQueue *MovGraph::makeWholeQueue(StaticANIObject *ani, MovArr *movarr, int } } - MGMInfo mgminfo; + MakeQueueStruct mkQueue; - memset(&mgminfo, 0, sizeof(mgminfo)); - mgminfo.ani = ani; - mgminfo.staticsId2 = id2; - mgminfo.staticsId1 = id1; - mgminfo.x1 = nx; - mgminfo.x2 = ox; - mgminfo.y2 = oy; - mgminfo.y1 = ny; - mgminfo.field_1C = nd; - mgminfo.movementId = st->link->_dwordArray1[_field_44 + st->sfield_0]; + memset(&mkQueue, 0, sizeof(mkQueue)); + mkQueue.ani = ani; + mkQueue.staticsId2 = id2; + mkQueue.staticsId1 = id1; + mkQueue.x1 = nx; + mkQueue.x2 = ox; + mkQueue.y2 = oy; + mkQueue.y1 = ny; + mkQueue.field_1C = nd; + mkQueue.movementId = st->link->_dwordArray1[_field_44 + st->sfield_0]; - mgminfo.flags = 0xe; + mkQueue.flags = 0xe; if (mq) - mgminfo.flags |= 0x31; + mkQueue.flags |= 0x31; - MessageQueue *newmq = _mgm.genMovement(&mgminfo); + MessageQueue *newmq = _aniHandler.makeRunQueue(&mkQueue); if (mq) { if (newmq) { - mq->transferExCommands(newmq); + mq->mergeQueue(newmq); delete newmq; } @@ -1228,6 +1268,8 @@ MessageQueue *MovGraph::makeWholeQueue(StaticANIObject *ani, MovArr *movarr, int } MessageQueue *MovGraph::method50(StaticANIObject *ani, MovArr *movarr, int staticsId) { + debugC(4, kDebugPathfinding, "MovGraph::method50(*%d, *, %d)", (ani ? ani->_id : -1), staticsId); + if (_items.size() == 0) return 0; @@ -1321,6 +1363,8 @@ double MovGraph::putToLink(Common::Point *point, MovGraphLink *link, int fuzzyMa } void MovGraph::recalcLinkParams() { + debugC(4, kDebugPathfinding, "MovGraph::recalcLinkParams()"); + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { assert(((CObject *)*i)->_objtype == kObjTypeMovGraphLink); @@ -1333,6 +1377,8 @@ void MovGraph::recalcLinkParams() { } bool MovGraph::getNearestPoint(int unusedArg, Common::Point *p, MovArr *movarr) { + debugC(4, kDebugPathfinding, "MovGraph::getNearestPoint(...)"); + MovGraphLink *link = 0; double mindist = 1.0e20; int resx = 0, resy = 0; @@ -1396,6 +1442,8 @@ int MovGraph::getObjectIndex(StaticANIObject *ani) { } Common::Array<MovArr *> *MovGraph::getHitPoints(int x, int y, int *arrSize, int flag1, int flag2) { + debugC(4, kDebugPathfinding, "MovGraph::getHitPoints(...)"); + if (!_links.size()) { *arrSize = 0; @@ -1466,6 +1514,8 @@ Common::Array<MovArr *> *MovGraph::getHitPoints(int x, int y, int *arrSize, int } void MovGraph::findAllPaths(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &allPaths) { + debugC(4, kDebugPathfinding, "MovGraph::findAllPaths(...)"); + if (lnk == lnk2) { for (uint i = 0; i < tempObList1.size(); i++) allPaths.push_back(tempObList1[i]); @@ -1496,6 +1546,8 @@ void MovGraph::findAllPaths(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array // Returns a list of possible paths two points in graph space Common::Array<MovItem *> *MovGraph::getPaths(MovArr *currPos, MovArr *destPos, int *pathCount) { + debugC(4, kDebugPathfinding, "MovGraph::getPaths(...)"); + Common::Array<MovGraphLink *> tempObList1; Common::Array<MovGraphLink *> allPaths; @@ -1556,14 +1608,14 @@ bool MovGraph::getHitPoint(int idx, int x, int y, MovArr *arr, int a6) { int offmin = 100; for (int i = 0; i < arrSize; i++) { - int off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44]); + int off = _aniHandler.getNumMovements(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44]); if (off < offmin) { offmin = off; idxmin = i; } - off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44 + 1]); + off = _aniHandler.getNumMovements(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44 + 1]); if (off < offmin) { offmin = off; idxmin = i; @@ -1582,6 +1634,8 @@ bool MovGraph::getHitPoint(int idx, int x, int y, MovArr *arr, int a6) { } void MovGraph::setEnds(MovStep *step1, MovStep *step2) { + debugC(4, kDebugPathfinding, "MovGraph::setEnds(...)"); + if (step1->link->_graphSrc == step2->link->_graphDst) { step1->sfield_0 = 1; step2->sfield_0 = 1; @@ -1603,7 +1657,7 @@ void MovGraph::setEnds(MovStep *step1, MovStep *step2) { } } -int MovGraph2::getItemIndexByGameObjectId(int objectId) { +int MctlGraph::getObjIndex(int objectId) { for (uint i = 0; i < _items2.size(); i++) if (_items2[i]->_objectId == objectId) return i; @@ -1611,7 +1665,7 @@ int MovGraph2::getItemIndexByGameObjectId(int objectId) { return -1; } -int MovGraph2::getItemSubIndexByStaticsId(int idx, int staticsId) { +int MctlGraph::getDirByStatics(int idx, int staticsId) { for (int i = 0; i < 4; i++) if (_items2[idx]->_subItems[i]._staticsId1 == staticsId || _items2[idx]->_subItems[i]._staticsId2 == staticsId) return i; @@ -1619,7 +1673,7 @@ int MovGraph2::getItemSubIndexByStaticsId(int idx, int staticsId) { return -1; } -int MovGraph2::getItemSubIndexByMovementId(int idx, int movId) { +int MctlGraph::getDirByMovement(int idx, int movId) { for (int i = 0; i < 4; i++) if (_items2[idx]->_subItems[i]._walk[0]._movementId == movId || _items2[idx]->_subItems[i]._turn[0]._movementId == movId || _items2[idx]->_subItems[i]._turnS[0]._movementId == movId) @@ -1628,14 +1682,14 @@ int MovGraph2::getItemSubIndexByMovementId(int idx, int movId) { return -1; } -int MovGraph2::getItemSubIndexByMGM(int index, StaticANIObject *ani) { - if (findNode(ani->_ox, ani->_oy, 0) || findLink1(ani->_ox, ani->_oy, -1, 0) || findLink2(ani->_ox, ani->_oy)) { +int MctlGraph::getDirByPoint(int index, StaticANIObject *ani) { + if (getHitNode(ani->_ox, ani->_oy, 0) || getHitLink(ani->_ox, ani->_oy, -1, 0) || getNearestLink(ani->_ox, ani->_oy)) { int minidx = -1; int min = 0; for (int i = 0; i < 4; i++) { - warning("WWW 5"); - int tmp = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, _items2[index]->_subItems[i]._staticsId1); + debugC(1, kDebugPathfinding, "WWW 5"); + int tmp = _aniHandler.getNumMovements(ani->_id, ani->_statics->_staticsId, _items2[index]->_subItems[i]._staticsId1); if (tmp >= 0 && (minidx == -1 || tmp < min)) { minidx = i; @@ -1649,7 +1703,9 @@ int MovGraph2::getItemSubIndexByMGM(int index, StaticANIObject *ani) { return -1; } -bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) { +bool MctlGraph::fillData(StaticANIObject *obj, MctlAni *item) { + debugC(4, kDebugPathfinding, "MovGraph::fillData(%d, ...)", obj->_id); + item->_obj = obj; item->_objectId = obj->_id; @@ -1778,17 +1834,19 @@ bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) { return true; } -void MovGraph2::attachObject(StaticANIObject *obj) { +void MctlGraph::attachObject(StaticANIObject *obj) { + debugC(4, kDebugPathfinding, "MctlGraph::attachObject(*%d)", obj->_id); + MovGraph::attachObject(obj); - int id = getItemIndexByGameObjectId(obj->_id); + int id = getObjIndex(obj->_id); if (id >= 0) { _items2[id]->_obj = obj; } else { - MovGraph2Item *item = new MovGraph2Item; + MctlAni *item = new MctlAni; - if (initDirections(obj, item)) { + if (fillData(obj, item)) { _items2.push_back(item); } else { delete item; @@ -1796,8 +1854,10 @@ void MovGraph2::attachObject(StaticANIObject *obj) { } } -void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphLink *> *linkList, LinkInfo *lnkSrc, LinkInfo *lnkDst) { - MovInfo1Sub *elem; +void MctlGraph::generateList(MctlMQ *movinfo, Common::Array<MovGraphLink *> *linkList, LinkInfo *lnkSrc, LinkInfo *lnkDst) { + debugC(4, kDebugPathfinding, "MctlGraph::generateList(...)"); + + MctlMQSub *elem; Common::Point point; Common::Rect rect; @@ -1805,7 +1865,7 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL movinfo->items.clear(); - elem = new MovInfo1Sub; + elem = new MctlMQSub; elem->subIndex = subIndex; elem->x = movinfo->pt1.x; elem->y = movinfo->pt1.y; @@ -1820,9 +1880,9 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL if (linkList->size() <= 1) { if (linkList->size() == 1) - idx1 = getShortSide((*linkList)[0], movinfo->pt2.x - movinfo->pt1.x, movinfo->pt2.y - movinfo->pt1.y); + idx1 = getDirBySize((*linkList)[0], movinfo->pt2.x - movinfo->pt1.x, movinfo->pt2.y - movinfo->pt1.y); else - idx1 = getShortSide(0, movinfo->pt2.x - movinfo->pt1.x, movinfo->pt2.y - movinfo->pt1.y); + idx1 = getDirBySize(0, movinfo->pt2.x - movinfo->pt1.x, movinfo->pt2.y - movinfo->pt1.y); point.y = -1; rect.bottom = -1; @@ -1830,14 +1890,14 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL rect.top = -1; rect.left = -1; } else { - idx1 = findLink(linkList, i, &rect, &point); + idx1 = getLinkDir(linkList, i, &rect, &point); } if (idx1 != prevSubIndex) { prevSubIndex = idx1; subIndex = idx1; - elem = new MovInfo1Sub; + elem = new MctlMQSub; elem->subIndex = subIndex; elem->x = rect.left; elem->y = rect.top; @@ -1849,9 +1909,9 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL if (i != linkList->size() - 1) { while (1) { i++; - if (findLink(linkList, i, &rect, 0) != prevSubIndex) { + if (getLinkDir(linkList, i, &rect, 0) != prevSubIndex) { i--; - findLink(linkList, i, &rect, &point); + getLinkDir(linkList, i, &rect, &point); break; } @@ -1864,7 +1924,7 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL if (movinfo->items.back()->subIndex != 10) { subIndex = prevSubIndex; - elem = new MovInfo1Sub; + elem = new MctlMQSub; elem->subIndex = 10; elem->x = -1; elem->y = -1; @@ -1872,8 +1932,8 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL movinfo->items.push_back(elem); - if (i == linkList->size()) { - elem = new MovInfo1Sub; + if (i == linkList->size() - 1) { + elem = new MctlMQSub; elem->subIndex = prevSubIndex; elem->x = movinfo->pt2.x; elem->y = movinfo->pt2.y; @@ -1881,7 +1941,7 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL movinfo->items.push_back(elem); } else { - elem = new MovInfo1Sub; + elem = new MctlMQSub; elem->subIndex = prevSubIndex; elem->x = rect.right; elem->y = rect.bottom; @@ -1893,7 +1953,7 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL } if (subIndex != movinfo->item1Index) { - elem = new MovInfo1Sub; + elem = new MctlMQSub; elem->subIndex = movinfo->item1Index; elem->x = movinfo->pt2.x; elem->y = movinfo->pt2.y; @@ -1905,38 +1965,40 @@ void MovGraph2::buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphL movinfo->itemsCount = movinfo->items.size(); } -MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) { - MovInfo1 movinfo(movInfo); +MessageQueue *MctlGraph::makeWholeQueue(MctlMQ *mctlMQ) { + debugC(4, kDebugPathfinding, "MctlGraph::makeWholeQueue(...)"); + + MctlMQ movinfo(mctlMQ); - int curX = movInfo->pt1.x; - int curY = movInfo->pt1.y; - int curDistance = movInfo->distance1; + int curX = mctlMQ->pt1.x; + int curY = mctlMQ->pt1.y; + int curDistance = mctlMQ->distance1; MessageQueue *mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); - for (int i = 0; i < movInfo->itemsCount - 1; i++) { - if (movInfo->items[i + 1]->subIndex != 10) { + for (int i = 0; i < mctlMQ->itemsCount - 1; i++) { + if (mctlMQ->items[i + 1]->subIndex != 10) { MG2I *mg2i; - if (i >= movInfo->itemsCount - 2 || movInfo->items[i + 2]->subIndex != 10) { + if (i >= mctlMQ->itemsCount - 2 || mctlMQ->items[i + 2]->subIndex != 10) { movinfo.flags = 0; - mg2i = &_items2[movInfo->index]->_subItems[movInfo->items[i]->subIndex]._turnS[movInfo->items[i + 1]->subIndex]; + mg2i = &_items2[mctlMQ->index]->_subItems[mctlMQ->items[i]->subIndex]._turnS[mctlMQ->items[i + 1]->subIndex]; } else { movinfo.flags = 2; - mg2i = &_items2[movInfo->index]->_subItems[movInfo->items[i]->subIndex]._turn[movInfo->items[i + 1]->subIndex]; + mg2i = &_items2[mctlMQ->index]->_subItems[mctlMQ->items[i]->subIndex]._turn[mctlMQ->items[i + 1]->subIndex]; } - if (i < movInfo->itemsCount - 2 - || (movInfo->items[i]->x == movInfo->items[i + 1]->x - && movInfo->items[i]->y == movInfo->items[i + 1]->y) - || movInfo->items[i]->x == -1 - || movInfo->items[i]->y == -1 - || movInfo->items[i + 1]->x == -1 - || movInfo->items[i + 1]->y == -1) { + if (i < mctlMQ->itemsCount - 2 + || (mctlMQ->items[i]->x == mctlMQ->items[i + 1]->x + && mctlMQ->items[i]->y == mctlMQ->items[i + 1]->y) + || mctlMQ->items[i]->x == -1 + || mctlMQ->items[i]->y == -1 + || mctlMQ->items[i + 1]->x == -1 + || mctlMQ->items[i + 1]->y == -1) { - ExCommand *ex = new ExCommand(_items2[movInfo->index]->_objectId, 1, mg2i->_movementId, 0, 0, 0, 1, 0, 0, 0); + ExCommand *ex = new ExCommand(_items2[mctlMQ->index]->_objectId, 1, mg2i->_movementId, 0, 0, 0, 1, 0, 0, 0); ex->_excFlags |= 2; - ex->_keyCode = _items2[movInfo->index]->_obj->_okeyCode; + ex->_keyCode = _items2[mctlMQ->index]->_obj->_okeyCode; ex->_field_24 = 1; ex->_field_14 = -1; mq->addExCommandToEnd(ex); @@ -1944,60 +2006,49 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) { curX += mg2i->_mx; curY += mg2i->_my; } else { - MGMInfo mgminfo; + MakeQueueStruct mkQueue; - memset(&mgminfo, 0, sizeof(mgminfo)); + memset(&mkQueue, 0, sizeof(mkQueue)); - mgminfo.ani = _items2[movInfo->index]->_obj; - mgminfo.staticsId2 = mg2i->_mov->_staticsObj2->_staticsId; - mgminfo.x1 = movInfo->items[i + 1]->x; - mgminfo.y1 = movInfo->items[i + 1]->y; - mgminfo.field_1C = movInfo->items[i + 1]->distance; - mgminfo.staticsId1 = mg2i->_mov->_staticsObj1->_staticsId; + mkQueue.ani = _items2[mctlMQ->index]->_obj; + mkQueue.staticsId2 = mg2i->_mov->_staticsObj2->_staticsId; + mkQueue.x1 = mctlMQ->items[i + 1]->x; + mkQueue.y1 = mctlMQ->items[i + 1]->y; + mkQueue.field_1C = mctlMQ->items[i + 1]->distance; + mkQueue.staticsId1 = mg2i->_mov->_staticsObj1->_staticsId; - mgminfo.x2 = movInfo->items[i]->x; - mgminfo.y2 = movInfo->items[i]->y; - mgminfo.field_10 = 1; - mgminfo.flags = 0x7f; - mgminfo.movementId = mg2i->_movementId; + mkQueue.x2 = mctlMQ->items[i]->x; + mkQueue.y2 = mctlMQ->items[i]->y; + mkQueue.field_10 = 1; + mkQueue.flags = 0x7f; + mkQueue.movementId = mg2i->_movementId; - MessageQueue *mq2 = _mgm.genMovement(&mgminfo); - mq->transferExCommands(mq2); + MessageQueue *mq2 = _aniHandler.makeRunQueue(&mkQueue); + mq->mergeQueue(mq2); delete mq2; - curX = movInfo->items[i + 1]->x; - curY = movInfo->items[i + 1]->y; + curX = mctlMQ->items[i + 1]->x; + curY = mctlMQ->items[i + 1]->y; } } else { - movinfo.item1Index = movInfo->items[i]->subIndex; + movinfo.item1Index = mctlMQ->items[i]->subIndex; movinfo.subIndex = movinfo.item1Index; movinfo.pt1.y = curY; movinfo.pt1.x = curX; movinfo.distance1 = curDistance; - movinfo.pt2.x = movInfo->items[i + 2]->x; - movinfo.pt2.y = movInfo->items[i + 2]->y; - movinfo.distance2 = movInfo->items[i + 2]->distance; - - if (i >= movInfo->itemsCount - 4 - || movInfo->items[i + 2]->subIndex == 10 - || movInfo->items[i + 3]->subIndex == 10 - || movInfo->items[i + 2]->subIndex == movInfo->items[i + 3]->subIndex - || movInfo->items[i + 4]->subIndex != 10) { - if (i >= movInfo->itemsCount - 3 - || movInfo->items[i + 2]->subIndex == 10 - || movInfo->items[i + 3]->subIndex == 10 - || movInfo->items[i + 2]->subIndex == movInfo->items[i + 3]->subIndex) { - movinfo.flags &= 3; - } else { - MG2I *m = &_items2[movInfo->index]->_subItems[movInfo->items[i + 2]->subIndex]._turnS[movInfo->items[i + 3]->subIndex]; - movinfo.pt2.x -= m->_mx; - movinfo.pt2.y -= m->_my; - movinfo.flags &= 3; - } - } else { - MG2I *m = &_items2[movInfo->index]->_subItems[movInfo->items[i + 2]->subIndex]._turn[movInfo->items[i + 3]->subIndex]; + movinfo.pt2.x = mctlMQ->items[i + 2]->x; + movinfo.pt2.y = mctlMQ->items[i + 2]->y; + movinfo.distance2 = mctlMQ->items[i + 2]->distance; + + if (i < mctlMQ->itemsCount - 4 + && mctlMQ->items[i + 2]->subIndex != 10 + && mctlMQ->items[i + 3]->subIndex != 10 + && mctlMQ->items[i + 2]->subIndex != mctlMQ->items[i + 3]->subIndex + && mctlMQ->items[i + 4]->subIndex == 10) { + + MG2I *m = &_items2[mctlMQ->index]->_subItems[mctlMQ->items[i + 2]->subIndex]._turn[mctlMQ->items[i + 3]->subIndex]; if (movinfo.item1Index && movinfo.item1Index != 1) { movinfo.pt2.y -= m->_my; @@ -2006,17 +2057,31 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) { movinfo.pt2.x -= m->_mx; movinfo.flags = (movinfo.flags & 2) | 1; } + + } else if (i < mctlMQ->itemsCount - 3 + && mctlMQ->items[i + 2]->subIndex != 10 + && mctlMQ->items[i + 3]->subIndex != 10 + && mctlMQ->items[i + 2]->subIndex != mctlMQ->items[i + 3]->subIndex) { + + MG2I *m = &_items2[mctlMQ->index]->_subItems[mctlMQ->items[i + 2]->subIndex]._turnS[mctlMQ->items[i + 3]->subIndex]; + movinfo.pt2.x -= m->_mx; + movinfo.pt2.y -= m->_my; + movinfo.flags = (movinfo.flags & 2) | (mctlMQ->flags & 1); + + } else { + movinfo.flags = (movinfo.flags & 2) | (mctlMQ->flags & 1); } + i++; // intentional - MessageQueue *mq2 = genMovement(&movinfo); + MessageQueue *mq2 = makeLineQueue(&movinfo); if (!mq2) { delete mq; return 0; } - mq->transferExCommands(mq2); + mq->mergeQueue(mq2); delete mq2; @@ -2026,34 +2091,38 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) { } } - movInfo->pt2.x = movinfo.pt2.x; - movInfo->pt2.y = movinfo.pt2.y; + mctlMQ->pt2.x = movinfo.pt2.x; + mctlMQ->pt2.y = movinfo.pt2.y; return mq; } -int MovGraph2::detachObject(StaticANIObject *obj) { - warning("STUB: MovGraph2::detachObject()"); +int MctlGraph::detachObject(StaticANIObject *obj) { + warning("STUB: MctlGraph::detachObject()"); return 0; } -void MovGraph2::detachAllObjects() { +void MctlGraph::detachAllObjects() { + debugC(4, kDebugPathfinding, "MctlGraph::detachAllObjects()"); + for (uint i = 0; i < _items2.size(); i++) delete _items2[i]; _items2.clear(); } -MessageQueue *MovGraph2::startMove(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { +MessageQueue *MctlGraph::startMove(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { + debugC(4, kDebugPathfinding, "MctlGraph::startMove(*%d, %d, %d, %d, %d)", ani->_id, xpos, ypos, fuzzyMatch, staticsId); + if (!ani->isIdle()) return 0; if (ani->_flags & 0x100) return 0; - warning("WWW 3"); - MessageQueue *mq = doWalkTo(ani, xpos, ypos, fuzzyMatch, staticsId); + debugC(1, kDebugPathfinding, "WWW 3"); + MessageQueue *mq = makeQueue(ani, xpos, ypos, fuzzyMatch, staticsId); if (!mq) return 0; @@ -2064,7 +2133,7 @@ MessageQueue *MovGraph2::startMove(StaticANIObject *ani, int xpos, int ypos, int ani->getPicAniInfo(&picAniInfo); ani->updateStepPos(); - MessageQueue *mq1 = doWalkTo(ani, xpos, ypos, fuzzyMatch, staticsId); + MessageQueue *mq1 = makeQueue(ani, xpos, ypos, fuzzyMatch, staticsId); ani->setPicAniInfo(&picAniInfo); @@ -2087,16 +2156,16 @@ MessageQueue *MovGraph2::startMove(StaticANIObject *ani, int xpos, int ypos, int return mq; } -MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int fuzzyMatch, int staticsId) { +MessageQueue *MctlGraph::makeQueue(StaticANIObject *obj, int xpos, int ypos, int fuzzyMatch, int staticsId) { LinkInfo linkInfoDest; LinkInfo linkInfoSource; - MovInfo1 movInfo1; + MctlMQ mctlMQ1; PicAniInfo picAniInfo; Common::Point point; - debug(0, "MovGraph2::doWalkTo(%d, %d, %d, %d, %d)", obj->_id, xpos, ypos, fuzzyMatch, staticsId); + debugC(1, kDebugPathfinding, "MctlGraph::makeQueue(%d, %d, %d, %d, %d)", obj->_id, xpos, ypos, fuzzyMatch, staticsId); - int idx = getItemIndexByGameObjectId(obj->_id); + int idx = getObjIndex(obj->_id); if (idx < 0) return 0; @@ -2114,15 +2183,15 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int int idxsub; if (obj->_movement) - idxsub = getItemSubIndexByMovementId(idx, obj->_movement->_id); + idxsub = getDirByMovement(idx, obj->_movement->_id); else - idxsub = getItemSubIndexByStaticsId(idx, obj->_statics->_staticsId); + idxsub = getDirByStatics(idx, obj->_statics->_staticsId); bool subMgm = false; if (idxsub == -1) { - warning("WWW 4"); - idxsub = getItemSubIndexByMGM(idx, obj); + debugC(1, kDebugPathfinding, "WWW 4"); + idxsub = getDirByPoint(idx, obj); subMgm = true; if (idxsub == -1) @@ -2160,7 +2229,7 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int MessageQueue *mq = new MessageQueue(); if (staticsId && obj->_statics->_staticsId != staticsId) { - int idxwalk = getItemSubIndexByStaticsId(idx, staticsId); + int idxwalk = getDirByStatics(idx, staticsId); if (idxwalk == -1) { obj->setPicAniInfo(&picAniInfo); @@ -2196,13 +2265,13 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int return mq; } - linkInfoSource.node = findNode(obj->_ox, obj->_oy, 0); + linkInfoSource.node = getHitNode(obj->_ox, obj->_oy, 0); if (!linkInfoSource.node) { - linkInfoSource.link = findLink1(obj->_ox, obj->_oy, idxsub, 0); + linkInfoSource.link = getHitLink(obj->_ox, obj->_oy, idxsub, 0); if (!linkInfoSource.link) { - linkInfoSource.link = findLink2(obj->_ox, obj->_oy); + linkInfoSource.link = getNearestLink(obj->_ox, obj->_oy); if (!linkInfoSource.link) { obj->setPicAniInfo(&picAniInfo); @@ -2212,10 +2281,10 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int } } - linkInfoDest.node = findNode(xpos, ypos, fuzzyMatch); + linkInfoDest.node = getHitNode(xpos, ypos, fuzzyMatch); if (!linkInfoDest.node) { - linkInfoDest.link = findLink1(xpos, ypos, idxsub, fuzzyMatch); + linkInfoDest.link = getHitLink(xpos, ypos, idxsub, fuzzyMatch); if (!linkInfoDest.link) { obj->setPicAniInfo(&picAniInfo); @@ -2225,78 +2294,78 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int } Common::Array<MovGraphLink *> tempLinkList; - double minPath = findMinPath(&linkInfoSource, &linkInfoDest, &tempLinkList); + double minPath = iterate(&linkInfoSource, &linkInfoDest, &tempLinkList); - debug(0, "MovGraph2::doWalkTo(): path: %g parts: %d", minPath, tempLinkList.size()); + debugC(0, kDebugPathfinding, "MctlGraph::makeQueue(): path: %g parts: %d", minPath, tempLinkList.size()); if (minPath < 0.0 || ((linkInfoSource.node != linkInfoDest.node || !linkInfoSource.node) && !tempLinkList.size())) return 0; - movInfo1.clear(); + mctlMQ1.clear(); - movInfo1.subIndex = idxsub; - movInfo1.pt1.x = obj->_ox; - movInfo1.pt1.y = obj->_oy; + mctlMQ1.subIndex = idxsub; + mctlMQ1.pt1.x = obj->_ox; + mctlMQ1.pt1.y = obj->_oy; int dx1 = obj->_ox; int dy1 = obj->_oy; int dx2, dy2; if (linkInfoSource.node) - movInfo1.distance1 = linkInfoSource.node->_z; + mctlMQ1.distance1 = linkInfoSource.node->_z; else - movInfo1.distance1 = linkInfoSource.link->_graphSrc->_z; + mctlMQ1.distance1 = linkInfoSource.link->_graphSrc->_z; if (linkInfoDest.node) { dx2 = linkInfoDest.node->_x; dy2 = linkInfoDest.node->_y; - movInfo1.pt2.x = linkInfoDest.node->_x; - movInfo1.pt2.y = linkInfoDest.node->_y; + mctlMQ1.pt2.x = linkInfoDest.node->_x; + mctlMQ1.pt2.y = linkInfoDest.node->_y; - movInfo1.distance2 = linkInfoDest.node->_z; + mctlMQ1.distance2 = linkInfoDest.node->_z; } else { - movInfo1.pt2.x = xpos; - movInfo1.pt2.y = ypos; + mctlMQ1.pt2.x = xpos; + mctlMQ1.pt2.y = ypos; MovGraphNode *nod = linkInfoDest.link->_graphSrc; double dst1 = sqrt((double)((ypos - nod->_y) * (ypos - nod->_y) + (xpos - nod->_x) * (xpos - nod->_x))); int dst = linkInfoDest.link->_graphDst->_z - nod->_z; - movInfo1.distance2 = (int)(nod->_z + (dst1 * (double)dst / linkInfoDest.link->_length)); + mctlMQ1.distance2 = (int)(nod->_z + (dst1 * (double)dst / linkInfoDest.link->_length)); - putToLink(&movInfo1.pt2, linkInfoDest.link, 1); + putToLink(&mctlMQ1.pt2, linkInfoDest.link, 1); - dx1 = movInfo1.pt1.x; - dy1 = movInfo1.pt1.y; - dx2 = movInfo1.pt2.x; - dy2 = movInfo1.pt2.y; + dx1 = mctlMQ1.pt1.x; + dy1 = mctlMQ1.pt1.y; + dx2 = mctlMQ1.pt2.x; + dy2 = mctlMQ1.pt2.y; } if (staticsId) { - movInfo1.item1Index = getItemSubIndexByStaticsId(idx, staticsId); + mctlMQ1.item1Index = getDirByStatics(idx, staticsId); } else if (tempLinkList.size() <= 1) { if (tempLinkList.size() == 1) - movInfo1.item1Index = getShortSide(tempLinkList[0], dx2 - dx1, dy2 - dy1); + mctlMQ1.item1Index = getDirBySize(tempLinkList[0], dx2 - dx1, dy2 - dy1); else - movInfo1.item1Index = getShortSide(0, dx2 - dx1, dy2 - dy1); + mctlMQ1.item1Index = getDirBySize(0, dx2 - dx1, dy2 - dy1); } else { - movInfo1.item1Index = findLink(&tempLinkList, tempLinkList.size() - 1, 0, 0); + mctlMQ1.item1Index = getLinkDir(&tempLinkList, tempLinkList.size() - 1, 0, 0); } - movInfo1.flags = fuzzyMatch != 0; + mctlMQ1.flags = fuzzyMatch != 0; if (_items2[idx]->_subItems[idxsub]._staticsId1 != obj->_statics->_staticsId) - movInfo1.flags |= 2; + mctlMQ1.flags |= 2; - buildMovInfo1SubItems(&movInfo1, &tempLinkList, &linkInfoSource, &linkInfoDest); + generateList(&mctlMQ1, &tempLinkList, &linkInfoSource, &linkInfoDest); - MessageQueue *mq = buildMovInfo1MessageQueue(&movInfo1); + MessageQueue *mq = makeWholeQueue(&mctlMQ1); - linkInfoDest.node = findNode(movInfo1.pt2.x, movInfo1.pt2.y, fuzzyMatch); + linkInfoDest.node = getHitNode(mctlMQ1.pt2.x, mctlMQ1.pt2.y, fuzzyMatch); if (!linkInfoDest.node) - linkInfoDest.link = findLink1(movInfo1.pt2.x, movInfo1.pt2.y, movInfo1.item1Index, fuzzyMatch); + linkInfoDest.link = getHitLink(mctlMQ1.pt2.x, mctlMQ1.pt2.y, mctlMQ1.item1Index, fuzzyMatch); if (fuzzyMatch || linkInfoDest.link || linkInfoDest.node) { if (mq && mq->getCount() > 0 && picAniInfo.movementId) { @@ -2331,13 +2400,13 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int return mq; } -MovGraphNode *MovGraph2::findNode(int x, int y, int fuzzyMatch) { +MovGraphNode *MctlGraph::getHitNode(int x, int y, int strictMatch) { for (ObList::iterator i = _nodes.begin(); i != _nodes.end(); ++i) { assert(((CObject *)*i)->_objtype == kObjTypeMovGraphNode); MovGraphNode *node = (MovGraphNode *)*i; - if (fuzzyMatch) { + if (!strictMatch) { if (abs(node->_x - x) < 15 && abs(node->_y - y) < 15) return node; } else { @@ -2349,7 +2418,7 @@ MovGraphNode *MovGraph2::findNode(int x, int y, int fuzzyMatch) { return 0; } -int MovGraph2::getShortSide(MovGraphLink *lnk, int x, int y) { +int MctlGraph::getDirBySize(MovGraphLink *lnk, int x, int y) { bool cond; if (lnk) @@ -2363,7 +2432,9 @@ int MovGraph2::getShortSide(MovGraphLink *lnk, int x, int y) { return ((y > 0) + 2); } -int MovGraph2::findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common::Rect *rect, Common::Point *point) { +int MctlGraph::getLinkDir(Common::Array<MovGraphLink *> *linkList, int idx, Common::Rect *rect, Common::Point *point) { + debugC(4, kDebugPathfinding, "MctlGraph::getLinkDir(...)"); + MovGraphNode *node1 = (*linkList)[idx]->_graphSrc; MovGraphNode *node2 = (*linkList)[idx]->_graphDst; MovGraphNode *node3 = node1; @@ -2405,12 +2476,14 @@ int MovGraph2::findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common } if (abs(node3->_x - node2->_x) <= abs(node3->_y - node2->_y)) - return (node3->_y < node2->_x) + 2; + return (node3->_y < node2->_y) + 2; else return node3->_x >= node2->_x; } -MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { +MessageQueue *MctlGraph::makeLineQueue(MctlMQ *info) { + debugC(4, kDebugPathfinding, "MctlGraph::makeLineQueue(...)"); + int mx1 = 0; int my1 = 0; @@ -2434,7 +2507,7 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { int a2 = 0; int mgmLen; - _mgm.calcLength(&point, _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov, x, y, &mgmLen, &a2, info->flags & 1); + _aniHandler.getNumCycles(&point, _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov, x, y, &mgmLen, &a2, info->flags & 1); int x1 = point.x; int y1 = point.y; @@ -2549,7 +2622,7 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { ex->_excFlags |= 2; mq->addExCommandToEnd(ex); - ex = _mgm.buildExCommand2( + ex = _aniHandler.createCommand( _items2[info->index]->_subItems[info->subIndex]._walk[0]._mov, _items2[info->index]->_objectId, x1, @@ -2571,7 +2644,7 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { else par = -1; - ex = _mgm.buildExCommand2( + ex = _aniHandler.createCommand( _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov, _items2[info->index]->_objectId, x1, @@ -2585,7 +2658,7 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { } if (!(info->flags & 4)) { - ex = _mgm.buildExCommand2( + ex = _aniHandler.createCommand( _items2[info->index]->_subItems[info->subIndex]._walk[2]._mov, _items2[info->index]->_objectId, x1, @@ -2611,7 +2684,9 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { return mq; } -MovGraphLink *MovGraph2::findLink1(int x, int y, int idx, int fuzzyMatch) { +MovGraphLink *MctlGraph::getHitLink(int x, int y, int idx, int fuzzyMatch) { + debugC(4, kDebugPathfinding, "MctlGraph::getHitLink(...)"); + Common::Point point; MovGraphLink *res = 0; @@ -2645,7 +2720,9 @@ MovGraphLink *MovGraph2::findLink1(int x, int y, int idx, int fuzzyMatch) { return res; } -MovGraphLink *MovGraph2::findLink2(int x, int y) { +MovGraphLink *MctlGraph::getNearestLink(int x, int y) { + debugC(4, kDebugPathfinding, "MctlGraph::getNearestLink(...)"); + double mindist = 1.0e20; MovGraphLink *res = 0; @@ -2687,7 +2764,9 @@ MovGraphLink *MovGraph2::findLink2(int x, int y) { return 0; } -double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> *listObj) { +double MctlGraph::iterate(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> *listObj) { + debugC(4, kDebugPathfinding, "MctlGraph::iterate(...)"); + LinkInfo linkInfoWorkSource; if (linkInfoSource->link != linkInfoDest->link || linkInfoSource->node != linkInfoDest->node) { @@ -2705,7 +2784,7 @@ double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, lnk->_flags |= 0x80000000; - double newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList); + double newDistance = iterate(&linkInfoWorkSource, linkInfoDest, &tmpList); if (newDistance >= 0.0 && (minDistance < 0.0 || newDistance + lnk->_length < minDistance)) { listObj->clear(); @@ -2723,7 +2802,7 @@ double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> tmpList; - double newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList); + double newDistance = iterate(&linkInfoWorkSource, linkInfoDest, &tmpList); if (newDistance >= 0.0) { listObj->clear(); @@ -2739,9 +2818,11 @@ double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, tmpList.clear(); - newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList); + newDistance = iterate(&linkInfoWorkSource, linkInfoDest, &tmpList); if (newDistance >= 0 && (minDistance < 0.0 || newDistance < minDistance)) { + listObj->clear(); + listObj->push_back(linkInfoSource->link); listObj->push_back(tmpList); @@ -2800,22 +2881,22 @@ MovGraphLink::~MovGraphLink() { bool MovGraphLink::load(MfcArchive &file) { - debug(5, "MovGraphLink::load()"); + debugC(5, kDebugLoading, "MovGraphLink::load()"); _dwordArray1.load(file); _dwordArray2.load(file); _flags = file.readUint32LE(); - debug(8, "GraphNode1"); + debugC(8, kDebugLoading, "GraphNode1"); _graphSrc = (MovGraphNode *)file.readClass(); - debug(8, "GraphNode2"); + debugC(8, kDebugLoading, "GraphNode2"); _graphDst = (MovGraphNode *)file.readClass(); _length = file.readDouble(); _angle = file.readDouble(); - debug(8, "length: %g, angle: %g", _length, _angle); + debugC(8, kDebugLoading, "length: %g, angle: %g", _length, _angle); _movGraphReact = (MovGraphReact *)file.readClass(); _name = file.readPascalString(); @@ -2829,12 +2910,12 @@ void MovGraphLink::recalcLength() { double dy = _graphDst->_y - _graphSrc->_y; _length = sqrt(dy * dy + dx * dx); - _angle = atan2(dx, dy); + _angle = atan2(dy, dx); } } bool MovGraphNode::load(MfcArchive &file) { - debug(5, "MovGraphNode::load()"); + debugC(5, kDebugLoading, "MovGraphNode::load()"); _field_14 = file.readUint32LE(); _x = file.readUint32LE(); @@ -2854,7 +2935,7 @@ ReactParallel::ReactParallel() { } bool ReactParallel::load(MfcArchive &file) { - debug(5, "ReactParallel::load()"); + debugC(5, kDebugLoading, "ReactParallel::load()"); _x1 = file.readUint32LE(); _y1 = file.readUint32LE(); @@ -2874,7 +2955,7 @@ void ReactParallel::createRegion() { for (int i = 0; i < 4; i++) _points[i] = new Common::Point; - double at = atan2((double)(_x1 - _x2), (double)(_y1 - _y2)) + 1.570796; // pi/2 + double at = atan2((double)(_y1 - _y2), (double)(_x1 - _x2)) + 1.570796; // pi/2 double sn = sin(at); double cs = cos(at); @@ -2912,7 +2993,7 @@ ReactPolygonal::~ReactPolygonal() { } bool ReactPolygonal::load(MfcArchive &file) { - debug(5, "ReactPolygonal::load()"); + debugC(5, kDebugLoading, "ReactPolygonal::load()"); _centerX = file.readUint32LE(); _centerY = file.readUint32LE(); diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index 41860e32d0..93b57c7aaa 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -23,7 +23,7 @@ #ifndef FULLPIPE_MOTION_H #define FULLPIPE_MOTION_H -#include "fullpipe/mgm.h" +#include "fullpipe/anihandler.h" namespace Fullpipe { @@ -62,7 +62,7 @@ public: virtual int method40() { return 0; } virtual bool canDropInventory(StaticANIObject *ani, int x, int y) { return false; } virtual int method48() { return -1; } - virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; } + virtual MessageQueue *makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; } void enableLinks(const char *linkName, bool enable); MovGraphLink *getLinkByName(const char *name); @@ -113,9 +113,9 @@ public: virtual int detachObject(StaticANIObject *obj); virtual void detachAllObjects(); virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); + virtual MessageQueue *makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - void initMovGraph2(); + void initMctlGraph(); MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, double *minDistancePtr); void replaceNodeX(int from, int to); @@ -149,7 +149,7 @@ public: int _ladder_field_20; int _ladder_field_24; Common::Array<MctlLadderMovement *> _ladmovements; - MGM _mgm; + AniHandler _aniHandler; public: MctlLadder(); @@ -160,7 +160,7 @@ public: virtual int detachObject(StaticANIObject *obj) { return 1; } virtual void detachAllObjects(); virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); + virtual MessageQueue *makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); MessageQueue *controllerWalkTo(StaticANIObject *ani, int off); @@ -282,7 +282,7 @@ public: int _field_44; Common::Array<MovGraphItem *> _items; MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter); - MGM _mgm; + AniHandler _aniHandler; public: MovGraph(); @@ -299,7 +299,7 @@ public: virtual void setSelFunc(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)); virtual bool resetPosition(StaticANIObject *ani, int flag); virtual bool canDropInventory(StaticANIObject *ani, int x, int y); - virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); + virtual MessageQueue *makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); virtual MessageQueue *method50(StaticANIObject *ani, MovArr *movarr, int staticsId); double putToLink(Common::Point *point, MovGraphLink *link, int fuzzyMatch); @@ -326,7 +326,7 @@ struct MG2I { int _my; }; -struct MovGraph2ItemSub { +struct MctlAniSub { int _staticsId2; int _staticsId1; MG2I _walk[3]; @@ -339,14 +339,14 @@ struct LinkInfo { MovGraphNode *node; }; -struct MovInfo1Sub { +struct MctlMQSub { int subIndex; int x; int y; int distance; }; -struct MovInfo1 { +struct MctlMQ { int index; Common::Point pt1; Common::Point pt2; @@ -354,50 +354,50 @@ struct MovInfo1 { int distance2; int subIndex; int item1Index; - Common::Array<MovInfo1Sub *> items; + Common::Array<MctlMQSub *> items; int itemsCount; int flags; - MovInfo1() { clear(); } - MovInfo1(MovInfo1 *src); + MctlMQ() { clear(); } + MctlMQ(MctlMQ *src); void clear(); }; -struct MovGraph2Item { // 744 +struct MctlAni { // 744 int _objectId; StaticANIObject *_obj; - MovGraph2ItemSub _subItems[4]; // 184 + MctlAniSub _subItems[4]; // 184 }; -class MovGraph2 : public MovGraph { +class MctlGraph : public MovGraph { public: - Common::Array<MovGraph2Item *> _items2; + Common::Array<MctlAni *> _items2; public: virtual void attachObject(StaticANIObject *obj); virtual int detachObject(StaticANIObject *obj); virtual void detachAllObjects(); virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); + virtual MessageQueue *makeQueue(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - int getItemIndexByGameObjectId(int objectId); - int getItemSubIndexByStaticsId(int index, int staticsId); - int getItemSubIndexByMovementId(int index, int movId); - int getItemSubIndexByMGM(int idx, StaticANIObject *ani); + int getObjIndex(int objectId); + int getDirByStatics(int index, int staticsId); + int getDirByMovement(int index, int movId); + int getDirByPoint(int idx, StaticANIObject *ani); - int getShortSide(MovGraphLink *lnk, int x, int y); - int findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common::Rect *a3, Common::Point *a4); + int getDirBySize(MovGraphLink *lnk, int x, int y); + int getLinkDir(Common::Array<MovGraphLink *> *linkList, int idx, Common::Rect *a3, Common::Point *a4); - bool initDirections(StaticANIObject *obj, MovGraph2Item *item); - void buildMovInfo1SubItems(MovInfo1 *movinfo, Common::Array<MovGraphLink *> *linkList, LinkInfo *lnkSrc, LinkInfo *lnkDst); - MessageQueue *buildMovInfo1MessageQueue(MovInfo1 *movInfo); + bool fillData(StaticANIObject *obj, MctlAni *item); + void generateList(MctlMQ *movinfo, Common::Array<MovGraphLink *> *linkList, LinkInfo *lnkSrc, LinkInfo *lnkDst); + MessageQueue *makeWholeQueue(MctlMQ *mctlMQ); - MovGraphNode *findNode(int x, int y, int fuzzyMatch); - MovGraphLink *findLink1(int x, int y, int idx, int fuzzyMatch); - MovGraphLink *findLink2(int x, int y); - double findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> *listObj); + MovGraphNode *getHitNode(int x, int y, int strictMatch); + MovGraphLink *getHitLink(int x, int y, int idx, int fuzzyMatch); + MovGraphLink *getNearestLink(int x, int y); + double iterate(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest, Common::Array<MovGraphLink *> *listObj); - MessageQueue *genMovement(MovInfo1 *movinfo); + MessageQueue *makeLineQueue(MctlMQ *movinfo); }; class MctlConnectionPoint : public CObject { diff --git a/engines/fullpipe/ngiarchive.cpp b/engines/fullpipe/ngiarchive.cpp index 132f4758d3..7d75dc2e78 100644 --- a/engines/fullpipe/ngiarchive.cpp +++ b/engines/fullpipe/ngiarchive.cpp @@ -93,11 +93,11 @@ NGIArchive::NGIArchive(const Common::String &filename) : _ngiFilename(filename) g_fp->_currArchive = this; - debug(0, "NGIArchive::NGIArchive(%s): Located %d files", filename.c_str(), _headers.size()); + debugC(0, kDebugLoading, "NGIArchive::NGIArchive(%s): Located %d files", filename.c_str(), _headers.size()); } NGIArchive::~NGIArchive() { - debug(0, "NGIArchive Destructor Called"); + debugC(0, kDebugLoading, "NGIArchive Destructor Called"); NgiHeadersMap::iterator it = _headers.begin(); for ( ; it != _headers.end(); ++it) { delete it->_value; diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp index 5a3fbe34b6..b47988d768 100644 --- a/engines/fullpipe/scene.cpp +++ b/engines/fullpipe/scene.cpp @@ -55,7 +55,7 @@ Scene *FullpipeEngine::accessScene(int sceneId) { } bool SceneTagList::load(MfcArchive &file) { - debug(5, "SceneTagList::load()"); + debugC(5, kDebugLoading, "SceneTagList::load()"); int numEntries = file.readUint16LE(); @@ -76,7 +76,7 @@ SceneTag::SceneTag() { } bool SceneTag::load(MfcArchive &file) { - debug(5, "SceneTag::load()"); + debugC(5, kDebugLoading, "SceneTag::load()"); _field_4 = 0; _scene = 0; @@ -85,7 +85,7 @@ bool SceneTag::load(MfcArchive &file) { _tag = file.readPascalString(); - debug(6, "sceneId: %d tag: %s", _sceneId, _tag); + debugC(6, kDebugLoading, "sceneId: %d tag: %s", _sceneId, _tag); return true; } @@ -157,7 +157,7 @@ Scene::~Scene() { } bool Scene::load(MfcArchive &file) { - debug(5, "Scene::load()"); + debugC(5, kDebugLoading, "Scene::load()"); Background::load(file); @@ -167,7 +167,7 @@ bool Scene::load(MfcArchive &file) { debug(0, "scene: <%s> %d", transCyrillic((byte *)_sceneName), _sceneId); int count = file.readUint16LE(); - debug(7, "scene.ani: %d", count); + debugC(7, kDebugLoading, "scene.ani: %d", count); for (int i = 0; i < count; i++) { int aniNum = file.readUint16LE(); @@ -189,7 +189,7 @@ bool Scene::load(MfcArchive &file) { } count = file.readUint16LE(); - debug(7, "scene.mq: %d", count); + debugC(7, kDebugLoading, "scene.mq: %d", count); for (int i = 0; i < count; i++) { int qNum = file.readUint16LE(); @@ -211,7 +211,7 @@ bool Scene::load(MfcArchive &file) { } count = file.readUint16LE(); - debug(7, "scene.fa: %d", count); + debugC(7, kDebugLoading, "scene.fa: %d", count); for (int i = 0; i < count; i++) { // There are no .FA files @@ -497,7 +497,7 @@ void Scene::objectList_sortByPriority(Common::Array<PictureObject *> &list, bool } void Scene::draw() { - debug(6, ">>>>> Scene::draw()"); + debugC(6, kDebugDrawing, ">>>>> Scene::draw()"); updateScrolling(); // Clean previous stuff @@ -640,7 +640,7 @@ int Scene::getPictureObjectIdAtPos(int x, int y) { } void Scene::update(int counterdiff) { - debug(6, "Scene::update(%d)", counterdiff); + debugC(6, kDebugDrawing, "Scene::update(%d)", counterdiff); for (uint i = 0; i < _staticANIObjectList2.size(); i++) _staticANIObjectList2[i]->update(counterdiff); @@ -654,7 +654,7 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) { g_fp->_globalPalette = _palette->_data; } - debug(1, "Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg); + debugC(1, kDebugDrawing, "Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg); if (_picObjList.size() > 2) { // We need to z-sort them objectList_sortByPriority(_picObjList, true); @@ -666,11 +666,11 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) { if (maxPri == -1) maxPri = 60000; - debug(1, "-> Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg); + debugC(1, kDebugDrawing, "-> Scene::drawContent(>%d, <%d, %d)", minPri, maxPri, drawBg); Common::Point point; - debug(1, "_bigPict: %d objlist: %d", _bigPictureArray1Count, _picObjList.size()); + debugC(1, kDebugDrawing, "_bigPict: %d objlist: %d", _bigPictureArray1Count, _picObjList.size()); if (drawBg && _bigPictureArray1Count && _picObjList.size()) { @@ -679,11 +679,11 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) { int width = point.x; int height = point.y; - debug(8, "w: %d h:%d", width, height); + debugC(8, kDebugDrawing, "w: %d h:%d", width, height); ((PictureObject *)_picObjList[0])->getDimensions(&point); - debug(8, "w2: %d h2:%d", point.x, point.y); + debugC(8, kDebugDrawing, "w2: %d h2:%d", point.x, point.y); int bgStX = g_fp->_sceneRect.left % point.x; @@ -744,7 +744,7 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) { int objX = obj->_ox; int objY = obj->_oy; - debug(8, "obj: %d %d", objX, objY); + debugC(8, kDebugDrawing, "obj: %d %d", objX, objY); obj->getDimensions(&point); diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index 32aa955a61..cb9f8c4c01 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -582,7 +582,7 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { _aniMan2 = _aniMan; MctlCompound *cmp = getSc2MctlCompoundBySceneId(entrance->_sceneId); - cmp->initMovGraph2(); + cmp->initMctlGraph(); cmp->attachObject(_aniMan); cmp->activate(); getGameLoaderInteractionController()->enableFlag24(); diff --git a/engines/fullpipe/scenes.h b/engines/fullpipe/scenes.h index 17ef5c3140..fd90b5f972 100644 --- a/engines/fullpipe/scenes.h +++ b/engines/fullpipe/scenes.h @@ -28,7 +28,7 @@ namespace Fullpipe { struct Bat; struct BehaviorMove; struct Hanger; -class MGM; +class AniHandler; class MctlLadder; struct Ring; class StaticANIObject; @@ -396,7 +396,7 @@ public: StaticANIObject *scene11_boots; StaticANIObject *scene11_dudeOnSwing; PictureObject *scene11_hint; - MGM scene11_mgm; + AniHandler scene11_aniHandler; bool scene11_arcadeIsOn; bool scene11_scrollIsEnabled; bool scene11_scrollIsMaximized; @@ -612,7 +612,7 @@ public: Common::Array<WalkingBearder *> scene29_bearders; int scene29_manX; int scene29_manY; - MGM scene29_mgm; + AniHandler scene29_aniHandler; StaticANIObject *scene30_leg; int scene30_liftFlag; diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp index 6c361d6f1a..d901d74289 100644 --- a/engines/fullpipe/scenes/scene04.cpp +++ b/engines/fullpipe/scenes/scene04.cpp @@ -395,21 +395,21 @@ void sceneHandler04_jumpOnLadder() { g_fp->_aniMan->_flags |= 1; - MGM mgm; - MGMInfo mgminfo; + AniHandler aniHandler; + MakeQueueStruct mkQueue; - mgm.addItem(ANI_MAN); + aniHandler.attachObject(ANI_MAN); - mgminfo.ani = g_fp->_aniMan; - mgminfo.staticsId2 = ST_MAN_ONPLANK; - mgminfo.x1 = 938; - mgminfo.y1 = 442; - mgminfo.field_1C = 10; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_MAN_JUMPONPLANK; + mkQueue.ani = g_fp->_aniMan; + mkQueue.staticsId2 = ST_MAN_ONPLANK; + mkQueue.x1 = 938; + mkQueue.y1 = 442; + mkQueue.field_1C = 10; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_MAN_JUMPONPLANK; - MessageQueue *mq = mgm.genMovement(&mgminfo); + MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue); if (mq) { mq->_flags |= 1; @@ -460,21 +460,21 @@ void sceneHandler04_dropBottle() { } void sceneHandler04_gotoLadder(ExCommand *ex) { - MGM mgm; - MGMInfo mgminfo; + AniHandler aniHandler; + MakeQueueStruct mkQueue; - mgm.addItem(ANI_MAN); + aniHandler.attachObject(ANI_MAN); - mgminfo.ani = g_fp->_aniMan; - mgminfo.staticsId2 = ST_MAN_UP; - mgminfo.x1 = 1095; - mgminfo.y1 = 434; - mgminfo.field_1C = 12; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_MAN_PLANKTOLADDER; + mkQueue.ani = g_fp->_aniMan; + mkQueue.staticsId2 = ST_MAN_UP; + mkQueue.x1 = 1095; + mkQueue.y1 = 434; + mkQueue.field_1C = 12; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_MAN_PLANKTOLADDER; - MessageQueue *mq = mgm.genMovement(&mgminfo); + MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue); if (mq) { mq->deleteExCommandByIndex(mq->getCount() - 1, 1); @@ -550,21 +550,21 @@ void sceneHandler04_raisePlank() { } MessageQueue *sceneHandler04_kozFly3(StaticANIObject *ani, double phase) { - MGM mgm; - MGMInfo mgminfo; + AniHandler aniHandler; + MakeQueueStruct mkQueue; - mgm.addItem(ANI_KOZAWKA); + aniHandler.attachObject(ANI_KOZAWKA); - mgminfo.ani = ani; - mgminfo.staticsId2 = ST_KZW_SIT; - mgminfo.x1 = (int)(723.0 - phase * 185.0); - mgminfo.y1 = 486; - mgminfo.field_1C = 10; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_KZW_JUMP; + mkQueue.ani = ani; + mkQueue.staticsId2 = ST_KZW_SIT; + mkQueue.x1 = (int)(723.0 - phase * 185.0); + mkQueue.y1 = 486; + mkQueue.field_1C = 10; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_KZW_JUMP; - MessageQueue *mq = mgm.genMovement(&mgminfo); + MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue); if (mq) { ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0); @@ -599,35 +599,35 @@ MessageQueue *sceneHandler04_kozFly3(StaticANIObject *ani, double phase) { } MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) { - MGM mgm; - MGMInfo mgminfo; - - mgm.addItem(ANI_KOZAWKA); - - mgminfo.ani = ani; - mgminfo.staticsId2 = ST_KZW_JUMPOUT; - mgminfo.x1 = 525; - mgminfo.y1 = (int)(344.0 - (double)(320 - g_vars->scene04_bottle->_oy) * phase); - mgminfo.field_1C = 10; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_KZW_JUMPHIT; - - MessageQueue *mq1 = mgm.genMovement(&mgminfo); - - memset(&mgminfo, 0, sizeof(mgminfo)); - mgminfo.ani = ani; - mgminfo.staticsId1 = ST_KZW_JUMPOUT; - mgminfo.staticsId2 = ST_KZW_SIT; - mgminfo.x2 = 525; - mgminfo.y2 = (int)(344.0 - (double)(320 - g_vars->scene04_bottle->_oy) * phase); - mgminfo.y1 = 486; - mgminfo.field_1C = 10; - mgminfo.field_10 = 1; - mgminfo.flags = 117; - mgminfo.movementId = MV_KZW_JUMPOUT; - - MessageQueue *mq2 = mgm.genMovement(&mgminfo); + AniHandler aniHandler; + MakeQueueStruct mkQueue; + + aniHandler.attachObject(ANI_KOZAWKA); + + mkQueue.ani = ani; + mkQueue.staticsId2 = ST_KZW_JUMPOUT; + mkQueue.x1 = 525; + mkQueue.y1 = (int)(344.0 - (double)(320 - g_vars->scene04_bottle->_oy) * phase); + mkQueue.field_1C = 10; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_KZW_JUMPHIT; + + MessageQueue *mq1 = aniHandler.makeRunQueue(&mkQueue); + + memset(&mkQueue, 0, sizeof(mkQueue)); + mkQueue.ani = ani; + mkQueue.staticsId1 = ST_KZW_JUMPOUT; + mkQueue.staticsId2 = ST_KZW_SIT; + mkQueue.x2 = 525; + mkQueue.y2 = (int)(344.0 - (double)(320 - g_vars->scene04_bottle->_oy) * phase); + mkQueue.y1 = 486; + mkQueue.field_1C = 10; + mkQueue.field_10 = 1; + mkQueue.flags = 117; + mkQueue.movementId = MV_KZW_JUMPOUT; + + MessageQueue *mq2 = aniHandler.makeRunQueue(&mkQueue); if (mq1 && mq2) { mq1->addExCommandToEnd(mq2->getExCommandByIndex(0)->createClone()); @@ -670,21 +670,21 @@ MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) { } MessageQueue *sceneHandler04_kozFly6(StaticANIObject *ani) { - MGM mgm; - MGMInfo mgminfo; + AniHandler aniHandler; + MakeQueueStruct mkQueue; - mgm.addItem(ANI_KOZAWKA); + aniHandler.attachObject(ANI_KOZAWKA); - mgminfo.ani = ani; - mgminfo.staticsId2 = ST_KZW_SIT; - mgminfo.x1 = 397 - 4 * g_fp->_rnd->getRandomNumber(1); - mgminfo.field_1C = ani->_priority; - mgminfo.y1 = g_vars->scene04_bottle->_oy - 4 * g_fp->_rnd->getRandomNumber(1) + 109; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_KZW_JUMPROTATE; + mkQueue.ani = ani; + mkQueue.staticsId2 = ST_KZW_SIT; + mkQueue.x1 = 397 - 4 * g_fp->_rnd->getRandomNumber(1); + mkQueue.field_1C = ani->_priority; + mkQueue.y1 = g_vars->scene04_bottle->_oy - 4 * g_fp->_rnd->getRandomNumber(1) + 109; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_KZW_JUMPROTATE; - MessageQueue *mq = mgm.genMovement(&mgminfo); + MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue); if (mq) { mq->deleteExCommandByIndex(mq->getCount() - 1, 1); @@ -728,21 +728,21 @@ void sceneHandler04_kozMove(Movement *mov, int from, int to, Common::Point *poin } MessageQueue *sceneHandler04_kozFly7(StaticANIObject *ani, double phase) { - MGM mgm; - MGMInfo mgminfo; + AniHandler aniHandler; + MakeQueueStruct mkQueue; - mgm.addItem(ANI_KOZAWKA); + aniHandler.attachObject(ANI_KOZAWKA); - mgminfo.ani = ani; - mgminfo.staticsId2 = 560; - mgminfo.x1 = (int)(250.0 - phase * 100.0); - mgminfo.y1 = 455; - mgminfo.field_1C = 10; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_KZW_JUMPROTATE; + mkQueue.ani = ani; + mkQueue.staticsId2 = 560; + mkQueue.x1 = (int)(250.0 - phase * 100.0); + mkQueue.y1 = 455; + mkQueue.field_1C = 10; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_KZW_JUMPROTATE; - MessageQueue *mq = mgm.genMovement(&mgminfo); + MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue); if (mq) { sceneHandler04_kozMove(ani->getMovementById(MV_KZW_JUMPROTATE), 1, 9, g_vars->scene04_jumpRotateKozyawki, phase * 0.5 + 1.5); diff --git a/engines/fullpipe/scenes/scene11.cpp b/engines/fullpipe/scenes/scene11.cpp index 1fa5cabc15..1a8fa8ed67 100644 --- a/engines/fullpipe/scenes/scene11.cpp +++ b/engines/fullpipe/scenes/scene11.cpp @@ -96,7 +96,7 @@ void scene11_setupMusic() { void scene11_initScene(Scene *sc) { g_vars->scene11_swingie = sc->getStaticANIObject1ById(ANI_SWINGER, -1); g_vars->scene11_boots = sc->getStaticANIObject1ById(ANI_BOOTS_11, -1); - g_vars->scene11_mgm.clear(); + g_vars->scene11_aniHandler.detachAllObjects(); g_vars->scene11_dudeOnSwing = sc->getStaticANIObject1ById(ANI_MAN11, -1); g_vars->scene11_dudeOnSwing->_callback2 = scene11_dudeSwingCallback; g_vars->scene11_dudeOnSwing = sc->getStaticANIObject1ById(ANI_KACHELI, -1); @@ -251,7 +251,7 @@ void sceneHandler11_manToSwing() { g_vars->scene11_dudeOnSwing->startAnim(MV_MAN11_SWING_0, 0, -1); g_vars->scene11_dudeOnSwing->_movement->setDynamicPhaseIndex(45); - g_vars->scene11_mgm.addItem(g_fp->_aniMan->_id); + g_vars->scene11_aniHandler.attachObject(g_fp->_aniMan->_id); g_fp->_currentScene->_x = 1400 - g_fp->_sceneRect.right; @@ -385,7 +385,7 @@ void sceneHandler11_emptySwing() { } void sceneHandler11_jumpHitAndWin() { - MGMInfo mgminfo; + MakeQueueStruct mkQueue; sceneHandler11_emptySwing(); @@ -393,16 +393,16 @@ void sceneHandler11_jumpHitAndWin() { MV_MAN11_JUMPHIT, 0); g_fp->_aniMan->_priority = 10; - mgminfo.field_1C = 10; - mgminfo.ani = g_fp->_aniMan; - mgminfo.staticsId2 = ST_MAN_1PIX; - mgminfo.x1 = 1400; - mgminfo.y1 = 0; - mgminfo.field_10 = 1; - mgminfo.flags = 66; - mgminfo.movementId = MV_MAN11_JUMPHIT; + mkQueue.field_1C = 10; + mkQueue.ani = g_fp->_aniMan; + mkQueue.staticsId2 = ST_MAN_1PIX; + mkQueue.x1 = 1400; + mkQueue.y1 = 0; + mkQueue.field_10 = 1; + mkQueue.flags = 66; + mkQueue.movementId = MV_MAN11_JUMPHIT; - MessageQueue *mq = g_vars->scene11_mgm.genMovement(&mgminfo); + MessageQueue *mq = g_vars->scene11_aniHandler.makeRunQueue(&mkQueue); if (mq) { g_vars->scene11_crySound = SND_11_024; @@ -430,7 +430,7 @@ void sceneHandler11_jumpHitAndWin() { } void sceneHandler11_jumpOver(double angle) { - MGMInfo mgminfo; + MakeQueueStruct mkQueue; sceneHandler11_emptySwing(); @@ -438,16 +438,16 @@ void sceneHandler11_jumpOver(double angle) { MV_MAN11_JUMPOVER, 0); g_fp->_aniMan->_priority = 0; - mgminfo.staticsId2 = ST_MAN_1PIX; - mgminfo.ani = g_fp->_aniMan; - mgminfo.x1 = 1163; - mgminfo.y1 = 837 - (int)(angle * 153.0); - mgminfo.field_1C = 0; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_MAN11_JUMPOVER; + mkQueue.staticsId2 = ST_MAN_1PIX; + mkQueue.ani = g_fp->_aniMan; + mkQueue.x1 = 1163; + mkQueue.y1 = 837 - (int)(angle * 153.0); + mkQueue.field_1C = 0; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_MAN11_JUMPOVER; - MessageQueue *mq = g_vars->scene11_mgm.genMovement(&mgminfo); + MessageQueue *mq = g_vars->scene11_aniHandler.makeRunQueue(&mkQueue); if (mq) { g_vars->scene11_crySound = SND_11_022; @@ -463,7 +463,7 @@ void sceneHandler11_jumpOver(double angle) { } void sceneHandler11_jumpHit(double angle) { - MGMInfo mgminfo; + MakeQueueStruct mkQueue; sceneHandler11_emptySwing(); @@ -478,16 +478,16 @@ void sceneHandler11_jumpHit(double angle) { MV_MAN11_JUMPOVER, 0); g_fp->_aniMan->_priority = 0; - mgminfo.staticsId2 = ST_MAN_1PIX; - mgminfo.ani = g_fp->_aniMan; - mgminfo.x1 = 1017 - (int)(angle * -214.0); - mgminfo.y1 = 700; - mgminfo.field_1C = 0; - mgminfo.field_10 = 1; - mgminfo.flags = 78; - mgminfo.movementId = MV_MAN11_JUMPHIT; + mkQueue.staticsId2 = ST_MAN_1PIX; + mkQueue.ani = g_fp->_aniMan; + mkQueue.x1 = 1017 - (int)(angle * -214.0); + mkQueue.y1 = 700; + mkQueue.field_1C = 0; + mkQueue.field_10 = 1; + mkQueue.flags = 78; + mkQueue.movementId = MV_MAN11_JUMPHIT; - MessageQueue *mq = g_vars->scene11_mgm.genMovement(&mgminfo); + MessageQueue *mq = g_vars->scene11_aniHandler.makeRunQueue(&mkQueue); if (mq) { g_vars->scene11_crySound = SND_11_022; diff --git a/engines/fullpipe/scenes/scene22.cpp b/engines/fullpipe/scenes/scene22.cpp index f51469da69..84cd5f9a9a 100644 --- a/engines/fullpipe/scenes/scene22.cpp +++ b/engines/fullpipe/scenes/scene22.cpp @@ -239,23 +239,23 @@ void sceneHandler22_stoolLogic(ExCommand *cmd) { goto LABEL_31; } - MGM mgm; - MGMInfo mgminfo; - - mgm.addItem(ANI_MAN); - mgminfo.ani = g_fp->_aniMan; - mgminfo.staticsId2 = ST_MAN_RIGHT; - mgminfo.x1 = 934; - mgminfo.y1 = 391; - mgminfo.field_1C = 10; - mgminfo.staticsId1 = 0x4145; - mgminfo.x2 = 981; - mgminfo.y2 = 390; - mgminfo.field_10 = 1; - mgminfo.flags = 127; - mgminfo.movementId = rMV_MAN_TURN_SRL; - - mq = mgm.genMovement(&mgminfo); + AniHandler mgm; + MakeQueueStruct mkQueue; + + mgm.attachObject(ANI_MAN); + mkQueue.ani = g_fp->_aniMan; + mkQueue.staticsId2 = ST_MAN_RIGHT; + mkQueue.x1 = 934; + mkQueue.y1 = 391; + mkQueue.field_1C = 10; + mkQueue.staticsId1 = 0x4145; + mkQueue.x2 = 981; + mkQueue.y2 = 390; + mkQueue.field_10 = 1; + mkQueue.flags = 127; + mkQueue.movementId = rMV_MAN_TURN_SRL; + + mq = mgm.makeRunQueue(&mkQueue); ExCommand *ex = mq->getExCommandByIndex(0); diff --git a/engines/fullpipe/scenes/scene27.cpp b/engines/fullpipe/scenes/scene27.cpp index 9570d30913..b23f29ad4c 100644 --- a/engines/fullpipe/scenes/scene27.cpp +++ b/engines/fullpipe/scenes/scene27.cpp @@ -331,7 +331,7 @@ void sceneHandler27_aimDude() { void sceneHandler27_wipeDo() { for (uint i = 0; i < g_vars->scene27_bats.size(); i++) { if (g_vars->scene27_bats[i]->currX < 800.0) { - g_vars->scene27_bats[i]->field_10 = atan2(800.0 - g_vars->scene27_bats[i]->currX, 520.0 - g_vars->scene27_bats[i]->currY); + g_vars->scene27_bats[i]->field_10 = atan2(520.0 - g_vars->scene27_bats[i]->currY, 800.0 - g_vars->scene27_bats[i]->currX); g_vars->scene27_bats[i]->power += 1.0; } } @@ -360,7 +360,7 @@ bool sceneHandler27_batFallLogic(uint batn) { } bool sceneHandler27_batCalcDistance(int bat1, int bat2) { - double at = atan2(g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX, g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY); + double at = atan2(g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY, g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX); double dy = g_vars->scene27_bats[bat1]->currY - g_vars->scene27_bats[bat2]->currY; double dx = g_vars->scene27_bats[bat1]->currX - g_vars->scene27_bats[bat2]->currX; double ay = cos(at); @@ -375,7 +375,7 @@ void sceneHandler27_knockBats(int bat1n, int bat2n) { if (0.0 != bat1->power) { double rndF = (double)g_fp->_rnd->getRandomNumber(32767) * 0.0000009155552842799158 - 0.015 - + atan2(bat2->currX - bat1->currX, bat2->currY - bat1->currY); + + atan2(bat2->currY - bat1->currY, bat2->currX - bat1->currX); double rndCos = cos(rndF); double rndSin = sin(rndF); @@ -386,7 +386,7 @@ void sceneHandler27_knockBats(int bat1n, int bat2n) { bat1->powerSin -= pow1y * 1.1; rndF = ((double)g_fp->_rnd->getRandomNumber(32767) * 0.0000009155552842799158 - 0.015 - + atan2(bat1->currX - bat2->currX, bat1->currY - bat2->currY)); + + atan2(bat1->currY - bat2->currY, bat1->currX - bat2->currX)); double pow2x = cos(bat2->field_10 - rndF) * (double)((int)(bat1->currX - bat2->currX) >= 0 ? 1 : -1) * bat2->power; double pow2y = sin(bat2->field_10 - rndF) * (double)((int)(bat1->currY - bat2->currY) >= 0 ? 1 : -1) * bat2->power; @@ -405,7 +405,7 @@ void sceneHandler27_knockBats(int bat1n, int bat2n) { else bat1->powerSin += pow2y * 0.64; - bat1->field_10 = atan2(bat1->powerCos, bat1->powerSin); + bat1->field_10 = atan2(bat1->powerSin, bat1->powerCos); bat1->power = sqrt(bat1->powerCos * bat1->powerCos + bat1->powerSin * bat1->powerSin); bat2->powerCos += pow1x * 0.64; @@ -414,7 +414,7 @@ void sceneHandler27_knockBats(int bat1n, int bat2n) { else bat2->powerSin += pow1y * 0.64; - bat2->field_10 = atan2(bat2->powerCos, bat2->powerSin); + bat2->field_10 = atan2(bat2->powerSin, bat2->powerCos); bat2->power = sqrt(bat2->powerCos * bat2->powerCos + bat2->powerSin * bat2->powerSin); g_fp->playSound(SND_27_026, 0); diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp index a03671a4d0..28d06964a9 100644 --- a/engines/fullpipe/scenes/scene29.cpp +++ b/engines/fullpipe/scenes/scene29.cpp @@ -487,23 +487,23 @@ bool sceneHandler29_checkGreenBallHit(StaticANIObject *ani, int maxx) { } void sceneHandler29_manHit() { - MGMInfo mgminfo; + MakeQueueStruct mkQueue; g_vars->scene29_manIsHit = true; g_fp->_aniMan->changeStatics2(ST_MAN29_RUNR); g_fp->_aniMan->setOXY(g_vars->scene29_manX, g_vars->scene29_manY); - mgminfo.ani = g_fp->_aniMan; - mgminfo.staticsId2 = ST_MAN29_SITR; - mgminfo.y1 = 463; - mgminfo.x1 = g_vars->scene29_manX <= 638 ? 351 : 0; - mgminfo.field_1C = 10; - mgminfo.field_10 = 1; - mgminfo.flags = (g_vars->scene29_manX <= 638 ? 2 : 0) | 0x44; - mgminfo.movementId = MV_MAN29_HIT; + mkQueue.ani = g_fp->_aniMan; + mkQueue.staticsId2 = ST_MAN29_SITR; + mkQueue.y1 = 463; + mkQueue.x1 = g_vars->scene29_manX <= 638 ? 351 : 0; + mkQueue.field_1C = 10; + mkQueue.field_10 = 1; + mkQueue.flags = (g_vars->scene29_manX <= 638 ? 2 : 0) | 0x44; + mkQueue.movementId = MV_MAN29_HIT; - MessageQueue *mq = g_vars->scene29_mgm.genMovement(&mgminfo); + MessageQueue *mq = g_vars->scene29_aniHandler.makeRunQueue(&mkQueue); ExCommand *ex; if (mq) { @@ -728,7 +728,7 @@ void sceneHandler29_manToL() { g_vars->scene29_arcadeIsOn = true; - g_vars->scene29_mgm.addItem(g_fp->_aniMan->_id); + g_vars->scene29_aniHandler.attachObject(g_fp->_aniMan->_id); g_fp->_updateScreenCallback = sceneHandler29_updateScreenCallback; diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp index c82c2c414c..398e28d11b 100644 --- a/engines/fullpipe/sound.cpp +++ b/engines/fullpipe/sound.cpp @@ -44,7 +44,7 @@ SoundList::SoundList() { } bool SoundList::load(MfcArchive &file, char *fname) { - debug(5, "SoundList::load()"); + debugC(5, kDebugLoading, "SoundList::load()"); _soundItemsCount = file.readUint32LE(); _soundItems = (Sound **)calloc(_soundItemsCount, sizeof(Sound *)); @@ -107,7 +107,7 @@ Sound::~Sound() { } bool Sound::load(MfcArchive &file, NGIArchive *archive) { - debug(5, "Sound::load()"); + debugC(5, kDebugLoading, "Sound::load()"); MemoryObject::load(file); @@ -132,7 +132,7 @@ bool Sound::load(MfcArchive &file, NGIArchive *archive) { } void Sound::updateVolume() { - debug(3, "STUB Sound::updateVolume()"); + debug(9, "STUB Sound::updateVolume()"); } void Sound::setPanAndVolumeByStaticAni() { diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp index 141196c7d7..c95f6c67f3 100644 --- a/engines/fullpipe/stateloader.cpp +++ b/engines/fullpipe/stateloader.cpp @@ -112,7 +112,7 @@ GameProject::GameProject() { } bool GameProject::load(MfcArchive &file) { - debug(5, "GameProject::load()"); + debugC(5, kDebugLoading, "GameProject::load()"); _field_4 = 0; _headerFilename = 0; @@ -124,10 +124,10 @@ bool GameProject::load(MfcArchive &file) { _headerFilename = file.readPascalString(); - debug(1, "_gameProjectVersion = %d", g_fp->_gameProjectVersion); - debug(1, "_pictureScale = %d", g_fp->_pictureScale); - debug(1, "_scrollSpeed = %d", g_fp->_scrollSpeed); - debug(1, "_headerFilename = %s", _headerFilename); + debugC(1, kDebugLoading, "_gameProjectVersion = %d", g_fp->_gameProjectVersion); + debugC(1, kDebugLoading, "_pictureScale = %d", g_fp->_pictureScale); + debugC(1, kDebugLoading, "_scrollSpeed = %d", g_fp->_scrollSpeed); + debugC(1, kDebugLoading, "_headerFilename = %s", _headerFilename); _sceneTagList = new SceneTagList(); @@ -205,24 +205,24 @@ bool GameVar::load(MfcArchive &file) { _varName = file.readPascalString(); _varType = file.readUint32LE(); - debugN(6, "[%03d] ", file.getLevel()); + debugCN(6, kDebugLoading, "[%03d] ", file.getLevel()); for (int i = 0; i < file.getLevel(); i++) - debugN(6, " "); + debugCN(6, kDebugLoading, " "); - debugN(6, "<%s>: ", transCyrillic((byte *)_varName)); + debugCN(6, kDebugLoading, "<%s>: ", transCyrillic((byte *)_varName)); switch (_varType) { case 0: _value.intValue = file.readUint32LE(); - debug(6, "d --> %d", _value.intValue); + debugC(6, kDebugLoading, "d --> %d", _value.intValue); break; case 1: _value.intValue = file.readUint32LE(); // FIXME - debug(6, "f --> %f", _value.floatValue); + debugC(6, kDebugLoading, "f --> %f", _value.floatValue); break; case 2: _value.stringValue = file.readPascalString(); - debug(6, "s --> %s", _value.stringValue); + debugC(6, kDebugLoading, "s --> %s", _value.stringValue); break; default: error("Unknown var type: %d (0x%x)", _varType, _varType); @@ -342,7 +342,7 @@ GameVar *GameVar::getSubVarByIndex(int idx) { } bool PicAniInfo::load(MfcArchive &file) { - debug(5, "PicAniInfo::load()"); + debugC(5, kDebugLoading, "PicAniInfo::load()"); type = file.readUint32LE(); objectId = file.readUint16LE(); diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 059fd82e79..e0fc1f6b04 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -69,7 +69,8 @@ Common::Point *StepArray::getCurrPoint(Common::Point *point) { point->x = 0; point->y = 0; } else { - point = _points[_currPointIndex]; + point->x = _points[_currPointIndex]->x; + point->y = _points[_currPointIndex]->y; } return point; } @@ -96,7 +97,7 @@ Common::Point *StepArray::getPoint(Common::Point *point, int index, int offset) } bool StepArray::gotoNextPoint() { - if (_currPointIndex < _maxPointIndex) { + if (_currPointIndex < _maxPointIndex - 1) { _currPointIndex++; return true; } else { @@ -107,20 +108,22 @@ bool StepArray::gotoNextPoint() { void StepArray::insertPoints(Common::Point **points, int pointsCount) { if (_currPointIndex + pointsCount >= _pointsCount) { - _points = (Common::Point **)realloc(_points, sizeof(Common::Point *) * (_currPointIndex + pointsCount)); + _points = (Common::Point **)realloc(_points, sizeof(Common::Point *) * (_pointsCount + pointsCount)); if (!_points) { error("Out of memory at StepArray::insertPoints()"); } + + for(int i = 0; i < pointsCount; i++) + _points[_pointsCount + i] = new Common::Point; + + _pointsCount += pointsCount; } _maxPointIndex = _currPointIndex + pointsCount; - for (int i = 0; i < pointsCount; i++) { - _points[_currPointIndex + i] = new Common::Point; - + for (int i = 0; i < pointsCount; i++) *_points[_currPointIndex + i] = *points[i]; - } } StaticANIObject::StaticANIObject() { @@ -156,7 +159,7 @@ StaticANIObject::~StaticANIObject() { _movements.clear(); - g_fp->_mgm->clear(); + g_fp->_aniHandler->detachAllObjects(); } StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) { @@ -201,7 +204,7 @@ StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) { } bool StaticANIObject::load(MfcArchive &file) { - debug(5, "StaticANIObject::load()"); + debugC(5, kDebugLoading, "StaticANIObject::load()"); GameObject::load(file); @@ -215,7 +218,7 @@ bool StaticANIObject::load(MfcArchive &file) { } count = file.readUint16LE(); - debug(7, "Movements: %d", count); + debugC(7, kDebugLoading, "Movements: %d", count); for (int i = 0; i < count; i++) { int movNum = file.readUint16LE(); @@ -512,7 +515,7 @@ bool StaticANIObject::getPixelAtPos(int x, int y, int *pixel) { } void Movement::draw(bool flipFlag, int angle) { - debug(3, "Movement::draw(%d, %d)", flipFlag, angle); + debugC(3, kDebugDrawing, "Movement::draw(%d, %d)", flipFlag, angle); Common::Point point; @@ -594,7 +597,7 @@ void StaticANIObject::draw() { Common::Point point; Common::Rect rect; - debug(6, "StaticANIObject::draw() (%s) [%d] [%d, %d]", transCyrillic((byte *)_objectName), _id, _ox, _oy); + debugC(6, kDebugDrawing, "StaticANIObject::draw() (%s) [%d] [%d, %d]", transCyrillic((byte *)_objectName), _id, _ox, _oy); if (_shadowsOn && g_fp->_currentScene && g_fp->_currentScene->_shadows && (getCurrDimensions(point)->x != 1 || getCurrDimensions(point)->y != 1)) { @@ -654,7 +657,7 @@ void StaticANIObject::draw() { } void StaticANIObject::draw2() { - debug(6, "StatciANIObject::draw2(): id: (%s) %d [%d, %d]", transCyrillic((byte *)_objectName), _id, _ox, _oy); + debugC(6, kDebugDrawing, "StatciANIObject::draw2(): id: (%s) %d [%d, %d]", transCyrillic((byte *)_objectName), _id, _ox, _oy); if ((_flags & 4) && (_flags & 0x10)) { if (_movement) { @@ -779,7 +782,7 @@ Common::Point *StaticANIObject::getSomeXY(Common::Point &p) { void StaticANIObject::update(int counterdiff) { int mqid; - debug(6, "StaticANIObject::update() (%s) [%d] [%d, %d] fl: %x", transCyrillic((byte *)_objectName), _id, _ox, _oy, _flags); + debugC(6, kDebugAnimation, "StaticANIObject::update() (%s) [%d] [%d, %d] fl: %x", transCyrillic((byte *)_objectName), _id, _ox, _oy, _flags); if (_flags & 2) { _messageNum--; @@ -951,7 +954,7 @@ Common::Point *StaticANIObject::calcNextStep(Common::Point *pRes) { } void StaticANIObject::stopAnim_maybe() { - debug(6, "StaticANIObject::stopAnim_maybe()"); + debugC(2, kDebugAnimation, "StaticANIObject::stopAnim_maybe()"); if (!(_flags & 1)) return; @@ -966,7 +969,10 @@ void StaticANIObject::stopAnim_maybe() { setOXY(_movement->_ox, _movement->_oy); if (_flags & 0x40) { - if (!_movement->_currMovement && !_movement->_currDynamicPhaseIndex) { + if (!_movement->_currMovement) { + if (_movement->_currDynamicPhaseIndex) + goto L11; +L8: _statics = _movement->_staticsObj1; _movement->getCurrDynamicPhaseXY(point); _ox -= point.x; @@ -984,13 +990,14 @@ void StaticANIObject::stopAnim_maybe() { _ox += point.x; _oy += point.y; } - } else { - _statics = _movement->_staticsObj2; + goto L12; } - } else { - _statics = _movement->_staticsObj2; + if (!_movement->_currDynamicPhaseIndex) + goto L8; } - +L11: + _statics = _movement->_staticsObj2; +L12: _statics->getSomeXY(point); _statics->_x = _ox - point.x; @@ -1040,9 +1047,9 @@ void StaticANIObject::adjustSomeXY() { } MessageQueue *StaticANIObject::changeStatics1(int msgNum) { - g_fp->_mgm->addItem(_id); + g_fp->_aniHandler->attachObject(_id); - MessageQueue *mq = g_fp->_mgm->genMQ(this, msgNum, 0, 0, 0); + MessageQueue *mq = g_fp->_aniHandler->makeQueue(this, msgNum, 0, 0, 0); if (!mq) return 0; @@ -1071,8 +1078,8 @@ void StaticANIObject::changeStatics2(int objId) { deleteFromGlobalMessageQueue(); if (_movement || _statics) { - g_fp->_mgm->addItem(_id); - g_fp->_mgm->updateAnimStatics(this, objId); + g_fp->_aniHandler->attachObject(_id); + g_fp->_aniHandler->putObjectToStatics(this, objId); } else { _statics = getStaticsById(objId); } @@ -1093,7 +1100,7 @@ void StaticANIObject::hide() { } void StaticANIObject::show1(int x, int y, int movId, int mqId) { - debug(6, "StaticANIObject::show1(%d, %d, %d, %d)", x, y, movId, mqId); + debugC(6, kDebugAnimation, "StaticANIObject::show1(%d, %d, %d, %d)", x, y, movId, mqId); if (_messageQueueId) return; @@ -1285,7 +1292,7 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase if (_flags & 0x80) return false; - debug(4, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy); + debugC(4, kDebugAnimation, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy); if (_messageQueueId) { updateGlobalMessageQueue(messageQueueId, _id); @@ -1444,14 +1451,14 @@ Statics::Statics(Statics *src, bool reverse) : DynamicPhase(src, reverse) { } bool Statics::load(MfcArchive &file) { - debug(5, "Statics::load()"); + debugC(5, kDebugLoading, "Statics::load()"); DynamicPhase::load(file); _staticsId = file.readUint16LE(); _staticsName = file.readPascalString(); - debug(7, "statics: <%s> id: %d (%x)", transCyrillic((byte *)_staticsName), _staticsId, _staticsId); + debugC(7, kDebugLoading, "statics: <%s> id: %d (%x)", transCyrillic((byte *)_staticsName), _staticsId, _staticsId); _picture = new Picture(); _picture->load(file); @@ -1670,7 +1677,7 @@ bool Movement::load(MfcArchive &file, StaticANIObject *ani) { int dynCount = file.readUint16LE(); - debug(7, "dynCount: %d _id: %d", dynCount, _id); + debugC(7, kDebugLoading, "dynCount: %d _id: %d", dynCount, _id); if (dynCount != 0xffff || _id == MV_MAN_TURN_LU) { _framePosOffsets = (Common::Point **)calloc(dynCount + 2, sizeof(Common::Point *)); @@ -1826,7 +1833,7 @@ void Movement::initStatics(StaticANIObject *ani) { if (!_currMovement) return; - debug(7, "Movement::initStatics()"); + debugC(7, kDebugAnimation, "Movement::initStatics()"); _staticsObj2 = ani->addReverseStatics(_currMovement->_staticsObj2); _staticsObj1 = ani->addReverseStatics(_currMovement->_staticsObj1); @@ -1853,7 +1860,7 @@ void Movement::initStatics(StaticANIObject *ani) { } void Movement::updateCurrDynamicPhase() { - debug(7, "Movement::updateCurrDynamicPhase()"); + debugC(7, kDebugAnimation, "Movement::updateCurrDynamicPhase()"); if (_currMovement) { if (_currMovement->_dynamicPhases.size() == 0 || (uint)_currDynamicPhaseIndex >= _currMovement->_dynamicPhases.size()) @@ -1905,7 +1912,7 @@ int Movement::countPhasesWithFlag(int maxidx, int flag) { } void Movement::setDynamicPhaseIndex(int index) { - debug(7, "Movement::setDynamicPhaseIndex(%d)", index); + debugC(7, kDebugAnimation, "Movement::setDynamicPhaseIndex(%d)", index); while (_currDynamicPhaseIndex < index) gotoNextFrame(0, 0); @@ -1914,7 +1921,7 @@ void Movement::setDynamicPhaseIndex(int index) { } DynamicPhase *Movement::getDynamicPhaseByIndex(int idx) { - debug(7, "Movement::updateCurrDynamicPhase()"); + debugC(7, kDebugAnimation, "Movement::updateCurrDynamicPhase()"); if (_currMovement) { if (_currMovement->_dynamicPhases.size() == 0 || (uint)idx >= _currMovement->_dynamicPhases.size()) @@ -1973,7 +1980,7 @@ void Movement::removeFirstPhase() { } bool Movement::gotoNextFrame(void (*callback1)(int, Common::Point *point, int, int), void (*callback2)(int *)) { - debug(8, "Movement::gotoNextFrame()"); + debugC(8, kDebugAnimation, "Movement::gotoNextFrame()"); if (!callback2) { if (_currMovement) { @@ -2094,7 +2101,7 @@ bool Movement::gotoNextFrame(void (*callback1)(int, Common::Point *point, int, i } bool Movement::gotoPrevFrame() { - debug(8, "Movement::gotoPrevFrame()"); + debugC(8, kDebugAnimation, "Movement::gotoPrevFrame()"); if (!_currDynamicPhaseIndex) { gotoLastFrame(); @@ -2147,11 +2154,17 @@ void Movement::gotoFirstFrame() { void Movement::gotoLastFrame() { if (_currMovement) { - while ((uint)_currDynamicPhaseIndex != _currMovement->_dynamicPhases.size() - 1) - gotoNextFrame(0, 0); + if ((uint)_currDynamicPhaseIndex != _currMovement->_dynamicPhases.size() - 1) { + do { + gotoNextFrame(0, 0); + } while ((uint)_currDynamicPhaseIndex != _currMovement->_dynamicPhases.size() - 1); + } } else { - while ((uint)_currDynamicPhaseIndex != _dynamicPhases.size() - 1) - gotoNextFrame(0, 0); + if ((uint)_currDynamicPhaseIndex != _dynamicPhases.size() - 1) { + do { + gotoNextFrame(0, 0); + } while ((uint)_currDynamicPhaseIndex != _dynamicPhases.size() - 1); + } } } @@ -2192,7 +2205,7 @@ DynamicPhase::DynamicPhase(DynamicPhase *src, bool reverse) { _field_7E = 0; _rect = new Common::Rect(); - debug(1, "DynamicPhase::DynamicPhase(src, %d)", reverse); + debugC(1, kDebugAnimation, "DynamicPhase::DynamicPhase(src, %d)", reverse); if (reverse) { if (!src->_bitmap) @@ -2254,7 +2267,7 @@ DynamicPhase::DynamicPhase(DynamicPhase *src, bool reverse) { } bool DynamicPhase::load(MfcArchive &file) { - debug(5, "DynamicPhase::load()"); + debugC(5, kDebugLoading, "DynamicPhase::load()"); StaticPhase::load(file); @@ -2290,7 +2303,7 @@ StaticPhase::~StaticPhase() { } bool StaticPhase::load(MfcArchive &file) { - debug(5, "StaticPhase::load()"); + debugC(5, kDebugLoading, "StaticPhase::load()"); Picture::load(file); diff --git a/engines/fullpipe/utils.cpp b/engines/fullpipe/utils.cpp index a7dee2e59c..a8e00468b5 100644 --- a/engines/fullpipe/utils.cpp +++ b/engines/fullpipe/utils.cpp @@ -45,13 +45,13 @@ bool CObject::loadFile(const char *fname) { } bool ObList::load(MfcArchive &file) { - debug(5, "ObList::load()"); + debugC(5, kDebugLoading, "ObList::load()"); int count = file.readCount(); - debug(9, "ObList::count: %d:", count); + debugC(9, kDebugLoading, "ObList::count: %d:", count); for (int i = 0; i < count; i++) { - debug(9, "ObList::[%d]", i); + debugC(9, kDebugLoading, "ObList::[%d]", i); CObject *t = file.readClass(); push_back(t); @@ -61,7 +61,7 @@ bool ObList::load(MfcArchive &file) { } bool ObArray::load(MfcArchive &file) { - debug(5, "ObArray::load()"); + debugC(5, kDebugLoading, "ObArray::load()"); int count = file.readCount(); resize(count); @@ -76,10 +76,10 @@ bool ObArray::load(MfcArchive &file) { } bool DWordArray::load(MfcArchive &file) { - debug(5, "DWordArray::load()"); + debugC(5, kDebugLoading, "DWordArray::load()"); int count = file.readCount(); - debug(9, "DWordArray::count: %d", count); + debugC(9, kDebugLoading, "DWordArray::count: %d", count); resize(count); @@ -104,7 +104,7 @@ char *MfcArchive::readPascalString(bool twoByte) { tmp = (char *)calloc(len + 1, 1); read(tmp, len); - debug(9, "readPascalString: %d <%s>", len, transCyrillic((byte *)tmp)); + debugC(9, kDebugLoading, "readPascalString: %d <%s>", len, transCyrillic((byte *)tmp)); return tmp; } @@ -128,7 +128,7 @@ MemoryObject::~MemoryObject() { } bool MemoryObject::load(MfcArchive &file) { - debug(5, "MemoryObject::load()"); + debugC(5, kDebugLoading, "MemoryObject::load()"); _memfilename = file.readPascalString(); if (char *p = strchr(_memfilename, '\\')) { @@ -147,7 +147,7 @@ bool MemoryObject::load(MfcArchive &file) { } void MemoryObject::loadFile(char *filename) { - debug(5, "MemoryObject::loadFile(<%s>)", filename); + debugC(5, kDebugLoading, "MemoryObject::loadFile(<%s>)", filename); if (!*filename) return; @@ -165,7 +165,7 @@ void MemoryObject::loadFile(char *filename) { _dataSize = s->size(); - debug(5, "Loading %s (%d bytes)", filename, _dataSize); + debugC(5, kDebugLoading, "Loading %s (%d bytes)", filename, _dataSize); _data = (byte *)calloc(_dataSize, 1); s->read(_data, _dataSize); @@ -194,7 +194,7 @@ byte *MemoryObject::loadData() { } void MemoryObject::freeData() { - debug(8, "MemoryObject::freeData(): file: %s", _memfilename); + debugC(8, kDebugMemory, "MemoryObject::freeData(): file: %s", _memfilename); if (_data) free(_data); @@ -222,12 +222,12 @@ MemoryObject2::~MemoryObject2() { } bool MemoryObject2::load(MfcArchive &file) { - debug(5, "MemoryObject2::load()"); + debugC(5, kDebugLoading, "MemoryObject2::load()"); MemoryObject::load(file); _mflags |= 1; - debug(5, "MemoryObject2::load: <%s>", _memfilename); + debugC(5, kDebugLoading, "MemoryObject2::load: <%s>", _memfilename); if (_memfilename && *_memfilename) { MemoryObject::loadFile(_memfilename); @@ -377,15 +377,15 @@ CObject *MfcArchive::parseClass(bool *isCopyReturned) { uint obTag = readUint16LE(); - debug(7, "parseClass::obTag = %d (%04x) at 0x%08x", obTag, obTag, pos() - 2); + debugC(7, kDebugLoading, "parseClass::obTag = %d (%04x) at 0x%08x", obTag, obTag, pos() - 2); if (obTag == 0xffff) { int schema = readUint16LE(); - debug(7, "parseClass::schema = %d", schema); + debugC(7, kDebugLoading, "parseClass::schema = %d", schema); name = readPascalString(true); - debug(7, "parseClass::class <%s>", name); + debugC(7, kDebugLoading, "parseClass::class <%s>", name); if (!_classMap.contains(name)) { error("Unknown class in MfcArchive: <%s>", name); @@ -393,7 +393,7 @@ CObject *MfcArchive::parseClass(bool *isCopyReturned) { objectId = _classMap[name]; - debug(7, "tag: %d 0x%x (%x)", _objectMap.size() - 1, _objectMap.size() - 1, objectId); + debugC(7, kDebugLoading, "tag: %d 0x%x (%x)", _objectMap.size() - 1, _objectMap.size() - 1, objectId); res = createObject(objectId); _objectMap.push_back(res); @@ -407,7 +407,7 @@ CObject *MfcArchive::parseClass(bool *isCopyReturned) { if (_objectMap.size() < obTag) { error("Object index too big: %d at 0x%08x", obTag, pos() - 2); } - debug(7, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag])); + debugC(7, kDebugLoading, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag])); res = _objectMap[obTag]; @@ -420,7 +420,7 @@ CObject *MfcArchive::parseClass(bool *isCopyReturned) { error("Object index too big: %d at 0x%08x", obTag, pos() - 2); } - debug(7, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag])); + debugC(7, kDebugLoading, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag])); objectId = _objectIdMap[obTag]; @@ -443,7 +443,7 @@ char *genFileName(int superId, int sceneId, const char *ext) { snprintf(s, 255, "%04d.%s", sceneId, ext); } - debug(7, "genFileName: %s", s); + debugC(7, kDebugLoading, "genFileName: %s", s); return s; } diff --git a/engines/gnap/gnap.cpp b/engines/gnap/gnap.cpp index 6a03bf8eb0..809e711e4f 100644 --- a/engines/gnap/gnap.cpp +++ b/engines/gnap/gnap.cpp @@ -91,9 +91,10 @@ static const char *kSceneNames[] = { GnapEngine::GnapEngine(OSystem *syst, const ADGameDescription *gd) : Engine(syst), _gameDescription(gd) { - _random = new Common::RandomSource("gnap"); DebugMan.addDebugChannel(kDebugBasic, "basic", "Basic debug level"); + _random = new Common::RandomSource("gnap"); + Engine::syncSoundSettings(); _exe = nullptr; diff --git a/engines/gnap/scenes/group4.cpp b/engines/gnap/scenes/group4.cpp index f37be2c25d..814588d9ba 100644 --- a/engines/gnap/scenes/group4.cpp +++ b/engines/gnap/scenes/group4.cpp @@ -2691,7 +2691,7 @@ void Scene46::run() { case kHS46WalkArea1: if (gnap._actionStatus < 0) gnap.walkTo(Common::Point(-1, -1), -1, -1, 1); - break; + break; } } diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index dfbff33c63..605f1ed5b9 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -115,6 +115,19 @@ void PauseDialog::handleKeyDown(Common::KeyState state) { GobEngine::GobEngine(OSystem *syst) : Engine(syst), _rnd("gob") { + DebugMan.addDebugChannel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level"); + DebugMan.addDebugChannel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level"); + DebugMan.addDebugChannel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level"); + DebugMan.addDebugChannel(kDebugSound, "Sound", "Sound output debug level"); + DebugMan.addDebugChannel(kDebugExpression, "Expression", "Expression parser debug level"); + DebugMan.addDebugChannel(kDebugGameFlow, "Gameflow", "Gameflow debug level"); + DebugMan.addDebugChannel(kDebugFileIO, "FileIO", "File Input/Output debug level"); + DebugMan.addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); + DebugMan.addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level"); + DebugMan.addDebugChannel(kDebugVideo, "Video", "IMD/VMD video debug level"); + DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Hotspots debug level"); + DebugMan.addDebugChannel(kDebugDemo, "Demo", "Demo script debug level"); + _sound = 0; _mult = 0; _game = 0; _global = 0; _dataIO = 0; _goblin = 0; _vidPlayer = 0; _init = 0; _inter = 0; @@ -136,19 +149,6 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst), _rnd("gob") { _copyProtection = ConfMan.getBool("copy_protection"); _console = new GobConsole(this); - - DebugMan.addDebugChannel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level"); - DebugMan.addDebugChannel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level"); - DebugMan.addDebugChannel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level"); - DebugMan.addDebugChannel(kDebugSound, "Sound", "Sound output debug level"); - DebugMan.addDebugChannel(kDebugExpression, "Expression", "Expression parser debug level"); - DebugMan.addDebugChannel(kDebugGameFlow, "Gameflow", "Gameflow debug level"); - DebugMan.addDebugChannel(kDebugFileIO, "FileIO", "File Input/Output debug level"); - DebugMan.addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); - DebugMan.addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level"); - DebugMan.addDebugChannel(kDebugVideo, "Video", "IMD/VMD video debug level"); - DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Hotspots debug level"); - DebugMan.addDebugChannel(kDebugDemo, "Demo", "Demo script debug level"); } GobEngine::~GobEngine() { diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index ac77ec3099..2ba4ed18ab 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -53,17 +53,6 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) : _graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false), _font(NULL), _spookyMode(false) { - // Adding the default directories - const Common::FSNode gameDataDir(ConfMan.get("path")); - SearchMan.addSubDirectoryMatching(gameDataDir, "groovie"); - SearchMan.addSubDirectoryMatching(gameDataDir, "media"); - SearchMan.addSubDirectoryMatching(gameDataDir, "system"); - SearchMan.addSubDirectoryMatching(gameDataDir, "MIDI"); - - _modeSpeed = kGroovieSpeedNormal; - if (ConfMan.hasKey("fast_movie_speed") && ConfMan.getBool("fast_movie_speed")) - _modeSpeed = kGroovieSpeedFast; - // Initialize the custom debug levels DebugMan.addDebugChannel(kDebugVideo, "Video", "Debug video and audio playback"); DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resource management"); @@ -75,6 +64,17 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) : DebugMan.addDebugChannel(kDebugScriptvars, "Scriptvars", "Print out any change to script variables"); DebugMan.addDebugChannel(kDebugCell, "Cell", "Debug the cell game (in the microscope)"); DebugMan.addDebugChannel(kDebugFast, "Fast", "Play videos quickly, with no sound (unstable)"); + + // Adding the default directories + const Common::FSNode gameDataDir(ConfMan.get("path")); + SearchMan.addSubDirectoryMatching(gameDataDir, "groovie"); + SearchMan.addSubDirectoryMatching(gameDataDir, "media"); + SearchMan.addSubDirectoryMatching(gameDataDir, "system"); + SearchMan.addSubDirectoryMatching(gameDataDir, "MIDI"); + + _modeSpeed = kGroovieSpeedNormal; + if (ConfMan.hasKey("fast_movie_speed") && ConfMan.getBool("fast_movie_speed")) + _modeSpeed = kGroovieSpeedFast; } GroovieEngine::~GroovieEngine() { diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index e99321ddcb..65f31985d6 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -39,7 +39,7 @@ namespace Kyra { -#define RESFILE_VERSION 88 +#define RESFILE_VERSION 89 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 5776d813cf..414473bb82 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -38,6 +38,11 @@ namespace MADS { MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) : _gameDescription(gameDesc), Engine(syst), _randomSource("MADS") { + // Set up debug channels + DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); + DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); + // Initialize game/engine options _easyMouse = true; _invObjectsAnimated = true; @@ -78,11 +83,6 @@ MADSEngine::~MADSEngine() { } void MADSEngine::initialize() { - // Set up debug channels - DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); - DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); - DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); - // Initial sub-system engine references MSurface::setVm(this); MSprite::setVm(this); diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index b17b6e93b8..79d5256c1c 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -671,7 +671,7 @@ void Screen::transition(ScreenTransition transitionType, bool surfaceFlag) { void Screen::panTransition(MSurface &newScreen, byte *palData, int entrySide, const Common::Point &srcPos, const Common::Point &destPos, - ThroughBlack throughBlack, bool setPalette, int numTicks) { + ThroughBlack throughBlack, bool setPalette_, int numTicks) { EventsManager &events = *_vm->_events; Palette &palette = *_vm->_palette; Common::Point size; @@ -693,7 +693,7 @@ void Screen::panTransition(MSurface &newScreen, byte *palData, int entrySide, startX = size.x - 1; deltaX = startX ? -1 : 1; - if (setPalette & !throughBlack) + if (setPalette_ & !throughBlack) palette.setFullPalette(palData); // TODO: Original uses a different frequency ticks counter. Need to @@ -731,7 +731,7 @@ void Screen::panTransition(MSurface &newScreen, byte *palData, int entrySide, g_system->delayMillis(1); } - if ((setPalette && !loop) || throughBlack == THROUGH_BLACK2) + if ((setPalette_ && !loop) || throughBlack == THROUGH_BLACK2) palette.setFullPalette(palData); } diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index fd79e53b07..f08eee9677 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -42,6 +42,7 @@ #ifdef ENABLE_RIVEN #include "mohawk/riven.h" #include "mohawk/riven_external.h" +#include "mohawk/riven_sound.h" #endif namespace Mohawk { diff --git a/engines/mohawk/cstime.cpp b/engines/mohawk/cstime.cpp index 3b26378819..b2889be714 100644 --- a/engines/mohawk/cstime.cpp +++ b/engines/mohawk/cstime.cpp @@ -54,6 +54,7 @@ MohawkEngine_CSTime::MohawkEngine_CSTime(OSystem *syst, const MohawkGameDescript _console = 0; _gfx = 0; + _sound = 0; _cursor = 0; _interface = 0; _view = 0; @@ -66,6 +67,7 @@ MohawkEngine_CSTime::~MohawkEngine_CSTime() { delete _interface; delete _view; delete _console; + delete _sound; delete _gfx; delete _rnd; } @@ -75,6 +77,7 @@ Common::Error MohawkEngine_CSTime::run() { _console = new CSTimeConsole(this); _gfx = new CSTimeGraphics(this); + _sound = new Sound(this); _cursor = new DefaultCursorManager(this, ID_CURS); _interface = new CSTimeInterface(this); diff --git a/engines/mohawk/cstime.h b/engines/mohawk/cstime.h index bfb7daf945..393032aaa9 100644 --- a/engines/mohawk/cstime.h +++ b/engines/mohawk/cstime.h @@ -136,6 +136,7 @@ public: Common::RandomSource *_rnd; + Sound *_sound; CSTimeGraphics *_gfx; bool _needsUpdate; diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp index 8c11e3a5e9..38be98dfec 100644 --- a/engines/mohawk/dialogs.cpp +++ b/engines/mohawk/dialogs.cpp @@ -92,7 +92,7 @@ enum { MohawkOptionsDialog::MohawkOptionsDialog(MohawkEngine *vm) : GUI::Dialog(0, 0, 360, 200), - _vm(vm) { + _vm(vm), _loadSlot(-1) { _loadButton = new GUI::ButtonWidget(this, 245, 25, 100, 25, _("~L~oad"), 0, kLoadCmd); _saveButton = new GUI::ButtonWidget(this, 245, 60, 100, 25, _("~S~ave"), 0, kSaveCmd); new GUI::ButtonWidget(this, 245, 95, 100, 25, _("~Q~uit"), 0, kQuitCmd); @@ -112,6 +112,7 @@ MohawkOptionsDialog::~MohawkOptionsDialog() { void MohawkOptionsDialog::open() { GUI::Dialog::open(); + _loadSlot = -1; _loadButton->setEnabled(_vm->canLoadGameStateCurrently()); _saveButton->setEnabled(_vm->canSaveGameStateCurrently()); } @@ -133,12 +134,14 @@ void MohawkOptionsDialog::save() { } void MohawkOptionsDialog::load() { - int slot = _loadDialog->runModalWithCurrentTarget(); + // Do not load the game state from insite the dialog loop to + // avoid mouse cursor glitches (see bug #7164). Instead store + // the slot to load and let the code exectuting the dialog do + // the load after the dialog finished running. + _loadSlot = _loadDialog->runModalWithCurrentTarget(); - if (slot >= 0) { - _vm->loadGameState(slot); + if (_loadSlot >= 0) close(); - } } void MohawkOptionsDialog::reflowLayout() { diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h index 3cfb628f9d..99db641948 100644 --- a/engines/mohawk/dialogs.h +++ b/engines/mohawk/dialogs.h @@ -81,6 +81,8 @@ public: virtual void open() override; virtual void reflowLayout() override; virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override; + + int getLoadSlot() const {return _loadSlot;} private: MohawkEngine *_vm; @@ -90,6 +92,8 @@ private: GUI::SaveLoadChooser *_loadDialog; GUI::SaveLoadChooser *_saveDialog; + + int _loadSlot; void save(); void load(); diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp index 5af8fac901..579e3792b3 100644 --- a/engines/mohawk/livingbooks.cpp +++ b/engines/mohawk/livingbooks.cpp @@ -144,6 +144,7 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa _rnd = new Common::RandomSource("livingbooks"); + _sound = NULL; _page = NULL; const Common::FSNode gameDataDir(ConfMan.get("path")); @@ -158,6 +159,7 @@ MohawkEngine_LivingBooks::~MohawkEngine_LivingBooks() { destroyPage(); delete _console; + delete _sound; delete _gfx; delete _rnd; _bookInfoFile.clear(); @@ -182,6 +184,7 @@ Common::Error MohawkEngine_LivingBooks::run() { error("Could not find xRes/yRes variables"); _gfx = new LBGraphics(this, _screenWidth, _screenHeight); + _sound = new Sound(this); if (getGameType() != GType_LIVINGBOOKSV1) _cursor = new LivingBooksCursorManager_v2(); diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h index 1a265a1a02..cf67c1ee8e 100644 --- a/engines/mohawk/livingbooks.h +++ b/engines/mohawk/livingbooks.h @@ -714,6 +714,7 @@ public: Common::RandomSource *_rnd; + Sound *_sound; LBGraphics *_gfx; bool _needsRedraw, _needsUpdate; diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk index 83e541e3e4..3fc118d2b6 100644 --- a/engines/mohawk/module.mk +++ b/engines/mohawk/module.mk @@ -57,6 +57,7 @@ MODULE_OBJS += \ riven_graphics.o \ riven_saveload.o \ riven_scripts.o \ + riven_sound.o \ riven_vars.o endif diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp index d740d9479a..b38409f9f1 100644 --- a/engines/mohawk/mohawk.cpp +++ b/engines/mohawk/mohawk.cpp @@ -40,14 +40,12 @@ MohawkEngine::MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc) // Setup mixer syncSoundSettings(); - _sound = 0; _video = 0; _pauseDialog = 0; _cursor = 0; } MohawkEngine::~MohawkEngine() { - delete _sound; delete _video; delete _pauseDialog; delete _cursor; @@ -58,7 +56,6 @@ MohawkEngine::~MohawkEngine() { } Common::Error MohawkEngine::run() { - _sound = new Sound(this); _video = new VideoManager(this); _pauseDialog = new PauseDialog(this, "The game is paused. Press any key to continue."); @@ -66,14 +63,12 @@ Common::Error MohawkEngine::run() { } void MohawkEngine::pauseEngineIntern(bool pause) { + Engine::pauseEngineIntern(pause); + if (pause) { _video->pauseVideos(); - _sound->pauseSound(); - _sound->pauseSLST(); } else { _video->resumeVideos(); - _sound->resumeSound(); - _sound->resumeSLST(); _system->updateScreen(); } } diff --git a/engines/mohawk/mohawk.h b/engines/mohawk/mohawk.h index ac91dca971..bc0d642bce 100644 --- a/engines/mohawk/mohawk.h +++ b/engines/mohawk/mohawk.h @@ -100,7 +100,6 @@ public: bool hasFeature(EngineFeature f) const; - Sound *_sound; VideoManager *_video; CursorManager *_cursor; diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp index 633b67f7e9..3c00c1e11b 100644 --- a/engines/mohawk/myst.cpp +++ b/engines/mohawk/myst.cpp @@ -75,6 +75,7 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription _curResource = -1; _hoverResource = nullptr; + _sound = nullptr; _gfx = nullptr; _console = nullptr; _scriptParser = nullptr; @@ -88,6 +89,7 @@ MohawkEngine_Myst::~MohawkEngine_Myst() { DebugMan.clearAllDebugChannels(); delete _gfx; + delete _sound; delete _console; delete _scriptParser; delete _gameState; @@ -220,6 +222,7 @@ Common::Error MohawkEngine_Myst::run() { MohawkEngine::run(); _gfx = new MystGraphics(this); + _sound = new Sound(this); _console = new MystConsole(this); _gameState = new MystGameState(this, _saveFileMan); _optionsDialog = new MystOptionsDialog(this); @@ -309,6 +312,8 @@ Common::Error MohawkEngine_Myst::run() { _canSafelySaveLoad = true; runDialog(*_optionsDialog); + if (_optionsDialog->getLoadSlot() >= 0) + loadGameState(_optionsDialog->getLoadSlot()); _canSafelySaveLoad = false; if (_needsPageDrop) { diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h index 0b249e5499..0491e853b6 100644 --- a/engines/mohawk/myst.h +++ b/engines/mohawk/myst.h @@ -200,6 +200,7 @@ public: bool _showResourceRects; + Sound *_sound; MystGraphics *_gfx; MystGameState *_gameState; MystScriptParser *_scriptParser; diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index aa168a38d8..b7c83c0ff8 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -34,8 +34,8 @@ #include "mohawk/riven_external.h" #include "mohawk/riven_graphics.h" #include "mohawk/riven_saveload.h" +#include "mohawk/riven_sound.h" #include "mohawk/dialogs.h" -#include "mohawk/sound.h" #include "mohawk/video.h" #include "mohawk/console.h" @@ -59,6 +59,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _curStack = kStackUnknown; _hotspots = nullptr; _gfx = nullptr; + _sound = nullptr; _externalScriptHandler = nullptr; _rnd = nullptr; _scriptMan = nullptr; @@ -92,6 +93,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio } MohawkEngine_Riven::~MohawkEngine_Riven() { + delete _sound; delete _gfx; delete _console; delete _externalScriptHandler; @@ -123,6 +125,7 @@ Common::Error MohawkEngine_Riven::run() { SearchMan.add("arcriven.z", &_installerArchive, 0, false); _gfx = new RivenGraphics(this); + _sound = new RivenSoundManager(this); _console = new RivenConsole(this); _saveLoad = new RivenSaveLoad(this, _saveFileMan); _externalScriptHandler = new RivenExternal(this); @@ -199,6 +202,7 @@ Common::Error MohawkEngine_Riven::run() { void MohawkEngine_Riven::handleEvents() { // Update background running things checkTimer(); + _sound->updateSLST(); bool needsUpdate = _gfx->runScheduledWaterEffects(); needsUpdate |= _video->updateMovies(); @@ -258,6 +262,8 @@ void MohawkEngine_Riven::handleEvents() { break; case Common::KEYCODE_F5: runDialog(*_optionsDialog); + if (_optionsDialog->getLoadSlot() >= 0) + loadGameState(_optionsDialog->getLoadSlot()); updateZipMode(); break; case Common::KEYCODE_r: @@ -708,6 +714,7 @@ void MohawkEngine_Riven::delayAndUpdate(uint32 ms) { uint32 startTime = _system->getMillis(); while (_system->getMillis() < startTime + ms && !shouldQuit()) { + _sound->updateSLST(); bool needsUpdate = _gfx->runScheduledWaterEffects(); needsUpdate |= _video->updateMovies(); diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 3ea50bb38d..ce819ac970 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -41,6 +41,7 @@ class RivenExternal; class RivenConsole; class RivenSaveLoad; class RivenOptionsDialog; +class RivenSoundManager; // Riven Stack Types enum { @@ -121,6 +122,7 @@ public: MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc); virtual ~MohawkEngine_Riven(); + RivenSoundManager *_sound; RivenGraphics *_gfx; RivenExternal *_externalScriptHandler; Common::RandomSource *_rnd; diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 00075039fe..125630445e 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -24,7 +24,7 @@ #include "mohawk/riven.h" #include "mohawk/riven_external.h" #include "mohawk/riven_graphics.h" -#include "mohawk/sound.h" +#include "mohawk/riven_sound.h" #include "mohawk/video.h" #include "gui/message.h" @@ -2429,7 +2429,7 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) { // Play the sound of not being able to move _vm->_cursor->setCursor(kRivenHideCursor); _vm->_system->updateScreen(); - _vm->_sound->playSoundBlocking(13); + _vm->_sound->playSound(13); } } else { // We're not at the bottom, and we can move down again @@ -2463,7 +2463,7 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) { // Play the sound of not being able to move _vm->_cursor->setCursor(kRivenHideCursor); _vm->_system->updateScreen(); - _vm->_sound->playSoundBlocking(13); + _vm->_sound->playSound(13); return; } diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp index db22dde22d..b583bc9710 100644 --- a/engines/mohawk/riven_graphics.cpp +++ b/engines/mohawk/riven_graphics.cpp @@ -23,6 +23,7 @@ #include "mohawk/resource.h" #include "mohawk/riven.h" #include "mohawk/riven_graphics.h" +#include "mohawk/riven_sound.h" #include "common/system.h" #include "engines/util.h" @@ -111,6 +112,7 @@ void RivenGraphics::drawPLST(uint16 x) { void RivenGraphics::updateScreen(Common::Rect updateRect) { if (_updatesEnabled) { _vm->runUpdateScreenScript(); + _vm->_sound->triggerDrawSound(); if (_dirtyScreen) { _activatedPLSTs.clear(); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index caa235ec8b..3655452603 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -25,7 +25,7 @@ #include "mohawk/riven_external.h" #include "mohawk/riven_graphics.h" #include "mohawk/riven_scripts.h" -#include "mohawk/sound.h" +#include "mohawk/riven_sound.h" #include "mohawk/video.h" #include "common/memstream.h" @@ -309,54 +309,44 @@ void RivenScript::switchCard(uint16 op, uint16 argc, uint16 *argv) { // Command 3: play an SLST from the script void RivenScript::playScriptSLST(uint16 op, uint16 argc, uint16 *argv) { - SLSTRecord slstRecord; int offset = 0, j = 0; + uint16 soundCount = argv[offset++]; + SLSTRecord slstRecord; slstRecord.index = 0; // not set by the scripts, so we set it to 0 - slstRecord.sound_count = argv[0]; - slstRecord.sound_ids = new uint16[slstRecord.sound_count]; - - offset = slstRecord.sound_count; + slstRecord.soundIds.resize(soundCount); - for (j = 0; j < slstRecord.sound_count; j++) - slstRecord.sound_ids[j] = argv[offset++]; - slstRecord.fade_flags = argv[offset++]; + for (j = 0; j < soundCount; j++) + slstRecord.soundIds[j] = argv[offset++]; + slstRecord.fadeFlags = argv[offset++]; slstRecord.loop = argv[offset++]; - slstRecord.global_volume = argv[offset++]; + slstRecord.globalVolume = argv[offset++]; slstRecord.u0 = argv[offset++]; - slstRecord.u1 = argv[offset++]; + slstRecord.suspend = argv[offset++]; - slstRecord.volumes = new uint16[slstRecord.sound_count]; - slstRecord.balances = new int16[slstRecord.sound_count]; - slstRecord.u2 = new uint16[slstRecord.sound_count]; + slstRecord.volumes.resize(soundCount); + slstRecord.balances.resize(soundCount); + slstRecord.u2.resize(soundCount); - for (j = 0; j < slstRecord.sound_count; j++) + for (j = 0; j < soundCount; j++) slstRecord.volumes[j] = argv[offset++]; - for (j = 0; j < slstRecord.sound_count; j++) + for (j = 0; j < soundCount; j++) slstRecord.balances[j] = argv[offset++]; // negative = left, 0 = center, positive = right - for (j = 0; j < slstRecord.sound_count; j++) + for (j = 0; j < soundCount; j++) slstRecord.u2[j] = argv[offset++]; // Unknown // Play the requested sound list _vm->_sound->playSLST(slstRecord); - _vm->_activatedSLST = true; - - delete[] slstRecord.sound_ids; - delete[] slstRecord.volumes; - delete[] slstRecord.balances; - delete[] slstRecord.u2; } // Command 4: play local tWAV resource (twav_id, volume, block) void RivenScript::playSound(uint16 op, uint16 argc, uint16 *argv) { - byte volume = Sound::convertRivenVolume(argv[1]); + uint16 volume = argv[1]; + bool playOnDraw = argv[2] == 1; - if (argv[2] == 1) - _vm->_sound->playSoundBlocking(argv[0], volume); - else - _vm->_sound->playSound(argv[0], volume); + _vm->_sound->playSound(argv[0], volume, playOnDraw); } // Command 7: set variable value (variable, value) diff --git a/engines/mohawk/riven_sound.cpp b/engines/mohawk/riven_sound.cpp new file mode 100644 index 0000000000..10a23a0719 --- /dev/null +++ b/engines/mohawk/riven_sound.cpp @@ -0,0 +1,459 @@ +/* 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/debug.h" +#include "common/system.h" + +#include "audio/audiostream.h" + +#include "mohawk/riven_sound.h" +#include "mohawk/sound.h" + +namespace Mohawk { + +RivenSoundManager::RivenSoundManager(MohawkEngine *vm) : + _vm(vm), + _effect(nullptr), + _mainAmbientSoundId(-1), + _effectPlayOnDraw(false), + _nextFadeUpdate(0) { + +} + +RivenSoundManager::~RivenSoundManager() { + stopSound(); + stopAllSLST(false); +} + +Audio::RewindableAudioStream *RivenSoundManager::makeAudioStream(uint16 id) { + return makeMohawkWaveStream(_vm->getResource(ID_TWAV, id)); +} + +void RivenSoundManager::playSound(uint16 id, uint16 volume, bool playOnDraw) { + debug (0, "Playing sound %d", id); + + stopSound(); + + Audio::RewindableAudioStream *rewindStream = makeAudioStream(id); + if (!rewindStream) { + warning("Unable to play sound with id %d", id); + return; + } + + _effect = new RivenSound(_vm, rewindStream); + _effect->setVolume(volume); + + _effectPlayOnDraw = playOnDraw; + if (!playOnDraw) { + _effect->play(); + } +} + +void RivenSoundManager::playSLST(uint16 index, uint16 card) { + Common::SeekableReadStream *slstStream = _vm->getResource(ID_SLST, card); + + uint16 recordCount = slstStream->readUint16BE(); + + for (uint16 i = 0; i < recordCount; i++) { + SLSTRecord slstRecord; + slstRecord.index = slstStream->readUint16BE(); + + uint16 soundCount = slstStream->readUint16BE(); + slstRecord.soundIds.resize(soundCount); + + for (uint16 j = 0; j < soundCount; j++) + slstRecord.soundIds[j] = slstStream->readUint16BE(); + + slstRecord.fadeFlags = slstStream->readUint16BE(); + slstRecord.loop = slstStream->readUint16BE(); + slstRecord.globalVolume = slstStream->readUint16BE(); + slstRecord.u0 = slstStream->readUint16BE(); // Unknown + + if (slstRecord.u0 > 1) + warning("slstRecord.u0: %d non-boolean", slstRecord.u0); + + slstRecord.suspend = slstStream->readUint16BE(); + + if (slstRecord.suspend != 0) + warning("slstRecord.u1: %d non-zero", slstRecord.suspend); + + slstRecord.volumes.resize(soundCount); + slstRecord.balances.resize(soundCount); + slstRecord.u2.resize(soundCount); + + for (uint16 j = 0; j < soundCount; j++) + slstRecord.volumes[j] = slstStream->readUint16BE(); + + for (uint16 j = 0; j < soundCount; j++) + slstRecord.balances[j] = slstStream->readSint16BE(); // negative = left, 0 = center, positive = right + + for (uint16 j = 0; j < soundCount; j++) { + slstRecord.u2[j] = slstStream->readUint16BE(); // Unknown + + if (slstRecord.u2[j] != 255 && slstRecord.u2[j] != 256) + warning("slstRecord.u2[%d]: %d not 255 or 256", j, slstRecord.u2[j]); + } + + if (slstRecord.index == index) { + playSLST(slstRecord); + delete slstStream; + return; + } + } + + delete slstStream; + + // If we have no matching entries, we do nothing and just let + // the previous ambient sounds continue. +} + +void RivenSoundManager::playSLST(const SLSTRecord &slstRecord) { + if (slstRecord.soundIds.empty()) { + return; + } + + if (slstRecord.soundIds[0] == _mainAmbientSoundId) { + if (slstRecord.soundIds.size() > _ambientSounds.sounds.size()) { + addAmbientSounds(slstRecord); + } + setAmbientLooping(slstRecord.loop); + setTargetVolumes(slstRecord); + _ambientSounds.suspend = slstRecord.suspend; + if (slstRecord.suspend) { + freePreviousAmbientSounds(); + pauseAmbientSounds(); + applyTargetVolumes(); + } else { + playAmbientSounds(); + } + } else { + _mainAmbientSoundId = slstRecord.soundIds[0]; + freePreviousAmbientSounds(); + moveAmbientSoundsToPreviousSounds(); + addAmbientSounds(slstRecord); + setAmbientLooping(slstRecord.loop); + setTargetVolumes(slstRecord); + _ambientSounds.suspend = slstRecord.suspend; + if (slstRecord.suspend) { + freePreviousAmbientSounds(); + applyTargetVolumes(); + } else { + startFadingAmbientSounds(slstRecord.fadeFlags); + } + } +} + +void RivenSoundManager::stopAllSLST(bool fade) { + _mainAmbientSoundId = -1; + freePreviousAmbientSounds(); + moveAmbientSoundsToPreviousSounds(); + startFadingAmbientSounds(fade ? kFadeOutPreviousSounds : 0); +} + +void RivenSoundManager::stopSound() { + if (_effect) { + delete _effect; + } + _effect = nullptr; + _effectPlayOnDraw = false; +} + +void RivenSoundManager::addAmbientSounds(const SLSTRecord &record) { + if (record.soundIds.size() > _ambientSounds.sounds.size()) { + uint oldSize = _ambientSounds.sounds.size(); + + // Resize the list to the new size + _ambientSounds.sounds.resize(record.soundIds.size()); + + // Add new elements to the list + for (uint i = oldSize; i < _ambientSounds.sounds.size(); i++) { + Audio::RewindableAudioStream *stream = makeAudioStream(record.soundIds[i]); + + RivenSound *sound = new RivenSound(_vm, stream); + sound->setVolume(record.volumes[i]); + sound->setBalance(record.balances[i]); + + _ambientSounds.sounds[i].sound = sound; + _ambientSounds.sounds[i].targetVolume = record.volumes[i]; + _ambientSounds.sounds[i].targetBalance = record.balances[i]; + } + } +} + +void RivenSoundManager::setTargetVolumes(const SLSTRecord &record) { + for (uint i = 0; i < record.volumes.size(); i++) { + _ambientSounds.sounds[i].targetVolume = record.volumes[i] * record.globalVolume / 256; + _ambientSounds.sounds[i].targetBalance = record.balances[i]; + } + _ambientSounds.fading = true; +} + +void RivenSoundManager::freePreviousAmbientSounds() { + for (uint i = 0; i < _previousAmbientSounds.sounds.size(); i++) { + delete _previousAmbientSounds.sounds[i].sound; + } + _previousAmbientSounds = AmbientSoundList(); +} + +void RivenSoundManager::moveAmbientSoundsToPreviousSounds() { + _previousAmbientSounds = _ambientSounds; + _ambientSounds = AmbientSoundList(); +} + +void RivenSoundManager::applyTargetVolumes() { + for (uint i = 0; i < _ambientSounds.sounds.size(); i++) { + AmbientSound &ambientSound = _ambientSounds.sounds[i]; + RivenSound *sound = ambientSound.sound; + sound->setVolume(ambientSound.targetVolume); + sound->setBalance(ambientSound.targetBalance); + } + _ambientSounds.fading = false; +} + +void RivenSoundManager::startFadingAmbientSounds(uint16 flags) { + for (uint i = 0; i < _ambientSounds.sounds.size(); i++) { + AmbientSound &ambientSound = _ambientSounds.sounds[i]; + uint16 volume; + if (flags & kFadeInNewSounds) { + volume = 0; + } else { + volume = ambientSound.targetVolume; + } + ambientSound.sound->setVolume(volume); + } + _ambientSounds.fading = true; + playAmbientSounds(); + + if (!_previousAmbientSounds.sounds.empty()) { + if (flags) { + _previousAmbientSounds.fading = true; + } else { + freePreviousAmbientSounds(); + } + + for (uint i = 0; i < _previousAmbientSounds.sounds.size(); i++) { + AmbientSound &ambientSound = _previousAmbientSounds.sounds[i]; + if (flags & kFadeOutPreviousSounds) { + ambientSound.targetVolume = 0; + } else { + ambientSound.sound->setVolume(ambientSound.targetVolume); + } + } + } +} + +void RivenSoundManager::playAmbientSounds() { + for (uint i = 0; i < _ambientSounds.sounds.size(); i++) { + _ambientSounds.sounds[i].sound->play(); + } +} + +void RivenSoundManager::setAmbientLooping(bool loop) { + for (uint i = 0; i < _ambientSounds.sounds.size(); i++) { + _ambientSounds.sounds[i].sound->setLooping(loop); + } +} + +void RivenSoundManager::triggerDrawSound() { + if (_effectPlayOnDraw && _effect) { + _effect->play(); + } + _effectPlayOnDraw = false; +} + +void RivenSoundManager::pauseAmbientSounds() { + for (uint i = 0; i < _ambientSounds.sounds.size(); i++) { + _ambientSounds.sounds[i].sound->pause(); + } +} + +void RivenSoundManager::updateSLST() { + uint32 time = _vm->_system->getMillis(); + int32 delta = CLIP<int32>(time - _nextFadeUpdate, -50, 50); + if (_nextFadeUpdate == 0 || delta > 0) { + _nextFadeUpdate = time + 50 - delta; + + if (_ambientSounds.fading) { + fadeAmbientSoundList(_ambientSounds); + } + + if (_previousAmbientSounds.fading) { + fadeAmbientSoundList(_previousAmbientSounds); + } + + if (!_previousAmbientSounds.sounds.empty() && !_ambientSounds.fading && !_previousAmbientSounds.fading) { + freePreviousAmbientSounds(); + } + } +} + +void RivenSoundManager::fadeAmbientSoundList(AmbientSoundList &list) { + list.fading = false; + + for (uint i = 0; i < list.sounds.size(); i++) { + AmbientSound &ambientSound = list.sounds[i]; + list.fading |= fadeVolume(ambientSound); + list.fading |= fadeBalance(ambientSound); + } +} + +bool RivenSoundManager::fadeVolume(AmbientSound &ambientSound) { + uint16 volume = ambientSound.sound->getVolume(); + float delta = (ambientSound.targetVolume - volume) / 30.0f; + + if (ABS<float>(delta) < 0.01f) { + ambientSound.sound->setVolume(ambientSound.targetVolume); + return false; + } else { + // Make sure the increment is not zero once converted to an integer + if (delta > 0 && delta < 1) { + delta = 1; + } else if (delta < 0 && delta > -1) { + delta = -1; + } + + ambientSound.sound->setVolume(volume + delta); + return true; + } +} + +bool RivenSoundManager::fadeBalance(RivenSoundManager::AmbientSound &ambientSound) { + int16 balance = ambientSound.sound->getBalance(); + float delta = (ambientSound.targetBalance - balance) / 10.0f; + + if (ABS<float>(delta) < 0.01) { + ambientSound.sound->setBalance(ambientSound.targetBalance); + return false; + } else { + // Make sure the increment is not zero once converted to an integer + if (delta > 0 && delta < 1) { + delta = 1; + } else if (delta < 0 && delta > -1) { + delta = -1; + } + + ambientSound.sound->setBalance(balance + delta); + return true; + } +} + +RivenSound::RivenSound(MohawkEngine *vm, Audio::RewindableAudioStream *rewindStream) : + _vm(vm), + _volume(Audio::Mixer::kMaxChannelVolume), + _balance(0), + _looping(false), + _stream(rewindStream) { + +} + +bool RivenSound::isPlaying() const { + return _vm->_mixer->isSoundHandleActive(_handle); +} + +void RivenSound::pause() { + _vm->_mixer->pauseHandle(_handle, true); +} + +void RivenSound::setVolume(uint16 volume) { + _volume = volume; + if (isPlaying()) { + byte mixerVolume = convertVolume(volume); + _vm->_mixer->setChannelVolume(_handle, mixerVolume); + } +} + +void RivenSound::setBalance(int16 balance) { + _balance = balance; + if (isPlaying()) { + int8 mixerBalance = convertBalance(balance); + _vm->_mixer->setChannelBalance(_handle, mixerBalance); + } +} + +void RivenSound::setLooping(bool loop) { + if (isPlaying() && _looping != loop) { + warning("Changing loop state while a sound is playing is not implemented."); + } + _looping = loop; +} + +void RivenSound::play() { + if (isPlaying()) { + // If the sound is already playing, make sure it is not paused + _vm->_mixer->pauseHandle(_handle, false); + return; + } + + if (!_stream) { + warning("Trying to play a sound without a stream"); + return; + } + + Audio::AudioStream *playStream; + if (_looping) { + playStream = new Audio::LoopingAudioStream(_stream, 0); + } else { + playStream = _stream; + } + + int8 mixerBalance = convertBalance(_balance); + byte mixerVolume = convertVolume(_volume); + _vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, playStream, -1, mixerVolume, mixerBalance); + _stream = nullptr; +} + +byte RivenSound::convertVolume(uint16 volume) { + // The volume is a fixed point value in the Mohawk part of the original engine. + // It's not clear what happens when it is higher than one. + return (volume > 255) ? 255 : volume; +} + +int8 RivenSound::convertBalance(int16 balance) { + return (int8)(balance >> 8); +} + +RivenSound::~RivenSound() { + _vm->_mixer->stopHandle(_handle); + delete _stream; +} + +int16 RivenSound::getBalance() const { + return _balance; +} + +uint16 RivenSound::getVolume() const { + return _volume; +} + +RivenSoundManager::AmbientSound::AmbientSound() : + sound(nullptr), + targetVolume(0), + targetBalance(0) { + +} + +RivenSoundManager::AmbientSoundList::AmbientSoundList() : + fading(false), + suspend(false) { +} + +} // End of namespace Mohawk diff --git a/engines/mohawk/riven_sound.h b/engines/mohawk/riven_sound.h new file mode 100644 index 0000000000..f673d1ee3f --- /dev/null +++ b/engines/mohawk/riven_sound.h @@ -0,0 +1,197 @@ +/* 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 MOHAWK_RIVEN_SOUND_H +#define MOHAWK_RIVEN_SOUND_H + +#include "common/array.h" +#include "common/str.h" + +#include "audio/mixer.h" + +namespace Audio { +class RewindableAudioStream; +} + +namespace Mohawk { + +class MohawkEngine; +class RivenSound; + +/** + * Ambient sound list + */ +struct SLSTRecord { + uint16 index; + Common::Array<uint16> soundIds; + uint16 fadeFlags; + uint16 loop; + uint16 globalVolume; + uint16 u0; + uint16 suspend; + Common::Array<uint16> volumes; + Common::Array<int16> balances; + Common::Array<uint16> u2; +}; + +/** + * Sound manager for Riven + * + * The sound manager can play simulteaneously: + * - An effect sound + * - A list of ambient sounds + * + * The list of ambient sounds can be cross faded + * with the previously running ambient sounds. + */ +class RivenSoundManager { +public: + RivenSoundManager(MohawkEngine *vm); + ~RivenSoundManager(); + + /** + * Play an effect sound + * + * @param id Sound ID in the stack + * @param volume Playback volume, between 0 and 255 + * @param playOnDraw Start playing when the current card is drawn instead of immediatly + */ + void playSound(uint16 id, uint16 volume = 255, bool playOnDraw = false); + + /** Start playing the scheduled on-draw effect sound, if any. Called by the GraphicsManager. */ + void triggerDrawSound(); + + /** Stop playing the current effect sound, if any */ + void stopSound(); + + /** Start playing an ambient sound list */ + void playSLST(const SLSTRecord &slstRecord); + + /** Start playing an ambient sound list from a resource */ + void playSLST(uint16 index, uint16 card); + + /** Stop playing the current ambient sounds */ + void stopAllSLST(bool fade = false); + + /** Update the ambient sounds for fading. Called once per frame. */ + void updateSLST(); + +private: + struct AmbientSound { + RivenSound *sound; + uint16 targetVolume; + int16 targetBalance; + + AmbientSound(); + }; + + struct AmbientSoundList { + bool fading; + bool suspend; + Common::Array<AmbientSound> sounds; + + AmbientSoundList(); + }; + + enum FadeFlags { + kFadeOutPreviousSounds = 1, + kFadeInNewSounds = 2 + }; + + MohawkEngine *_vm; + + int16 _mainAmbientSoundId; + AmbientSoundList _ambientSounds; + AmbientSoundList _previousAmbientSounds; + uint32 _nextFadeUpdate; + + RivenSound *_effect; + bool _effectPlayOnDraw; + + Audio::RewindableAudioStream *makeAudioStream(uint16 id); + + // Ambient sound management + void addAmbientSounds(const SLSTRecord &record); + void playAmbientSounds(); + void pauseAmbientSounds(); + void moveAmbientSoundsToPreviousSounds(); + void freePreviousAmbientSounds(); + + // Ambient sound fading + void setTargetVolumes(const SLSTRecord &record); + void applyTargetVolumes(); + void startFadingAmbientSounds(uint16 flags); + void fadeAmbientSoundList(AmbientSoundList &list); + bool fadeVolume(AmbientSound &ambientSound); + bool fadeBalance(AmbientSound &ambientSound); + void setAmbientLooping(bool loop); +}; + +/** + * A sound used internally by the SoundManager + */ +class RivenSound { +public: + RivenSound(MohawkEngine *vm, Audio::RewindableAudioStream *rewindStream); + ~RivenSound(); + + /** Start playing the sound stream passed to the constructor */ + void play(); + + /** Is the sound currently playing ar paused? */ + bool isPlaying() const; + + /** Pause the playback, the play method resumes */ + void pause(); + + /** Get the current volume */ + uint16 getVolume() const; + + /** Change the playback volume */ + void setVolume(uint16 volume); + + /** Get the current balance */ + int16 getBalance() const; + + /** Change the balance */ + void setBalance(int16 balance); + + /** Set the sound to indefinitely loop. Must be called before startting the playback */ + void setLooping(bool loop); + +private: + static byte convertVolume(uint16 volume); + static int8 convertBalance(int16 balance); + + MohawkEngine *_vm; + + Audio::SoundHandle _handle; + Audio::RewindableAudioStream *_stream; + + uint16 _volume; + int16 _balance; + bool _looping; +}; + +} // End of namespace Mohawk + +#endif diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index 38cb0b3608..0711561068 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -37,6 +37,150 @@ namespace Mohawk { +Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) { + uint32 tag = 0; + ADPCMStatus adpcmStatus; + DataChunk dataChunk; + uint32 dataSize = 0; + + memset(&dataChunk, 0, sizeof(DataChunk)); + + if (stream->readUint32BE() != ID_MHWK) // MHWK tag again + error ("Could not find tag 'MHWK'"); + + stream->readUint32BE(); // Skip size + + if (stream->readUint32BE() != ID_WAVE) + error ("Could not find tag 'WAVE'"); + + while (!dataChunk.audioData) { + tag = stream->readUint32BE(); + + switch (tag) { + case ID_ADPC: + debug(2, "Found Tag ADPC"); + // ADPCM Sound Only + // + // This is useful for seeking in the stream, and is actually quite brilliant + // considering some of the other things Broderbund did with the engine. + // Only Riven and CSTime are known to use ADPCM audio and only CSTime + // actually requires this for seeking. On the other hand, it may be interesting + // to look at that one Riven sample that uses the cue points. + // + // Basically, the sample frame from the cue list is looked up here and then + // sets the starting sample and step index at the point specified. Quite + // an elegant/efficient system, really. + + adpcmStatus.size = stream->readUint32BE(); + adpcmStatus.itemCount = stream->readUint16BE(); + adpcmStatus.channels = stream->readUint16BE(); + adpcmStatus.statusItems = new ADPCMStatus::StatusItem[adpcmStatus.itemCount]; + + assert(adpcmStatus.channels <= 2); + + for (uint16 i = 0; i < adpcmStatus.itemCount; i++) { + adpcmStatus.statusItems[i].sampleFrame = stream->readUint32BE(); + + for (uint16 j = 0; j < adpcmStatus.channels; j++) { + adpcmStatus.statusItems[i].channelStatus[j].last = stream->readSint16BE(); + adpcmStatus.statusItems[i].channelStatus[j].stepIndex = stream->readUint16BE(); + } + } + + // TODO: Actually use this chunk. For now, just delete the status items... + delete[] adpcmStatus.statusItems; + break; + case ID_CUE: + debug(2, "Found Tag Cue#"); + // Cues are used for animation sync. There are a couple in Myst and + // Riven but are not used there at all. + + if (!cueList) { + uint32 size = stream->readUint32BE(); + stream->skip(size); + break; + } + + cueList->size = stream->readUint32BE(); + cueList->pointCount = stream->readUint16BE(); + + if (cueList->pointCount == 0) + debug(2, "Cue# chunk found with no points!"); + else + debug(2, "Cue# chunk found with %d point(s)!", cueList->pointCount); + + cueList->points.resize(cueList->pointCount); + for (uint16 i = 0; i < cueList->pointCount; i++) { + cueList->points[i].sampleFrame = stream->readUint32BE(); + + byte nameLength = stream->readByte(); + cueList->points[i].name.clear(); + for (byte j = 0; j < nameLength; j++) + cueList->points[i].name += stream->readByte(); + + // Realign to an even boundary + if (!(nameLength & 1)) + stream->readByte(); + + debug (3, "Cue# chunk point %d (frame %d): %s", i, cueList->points[i].sampleFrame, cueList->points[i].name.c_str()); + } + break; + case ID_DATA: + debug(2, "Found Tag DATA"); + // We subtract 20 from the actual chunk size, which is the total size + // of the chunk's header + dataSize = stream->readUint32BE() - 20; + dataChunk.sampleRate = stream->readUint16BE(); + dataChunk.sampleCount = stream->readUint32BE(); + dataChunk.bitsPerSample = stream->readByte(); + dataChunk.channels = stream->readByte(); + dataChunk.encoding = stream->readUint16BE(); + dataChunk.loopCount = stream->readUint16BE(); + dataChunk.loopStart = stream->readUint32BE(); + dataChunk.loopEnd = stream->readUint32BE(); + + // NOTE: We currently ignore all of the loop parameters here. Myst uses the + // loopCount variable but the loopStart and loopEnd are always 0 and the size of + // the sample. Myst ME doesn't use the Mohawk Sound format and just standard WAVE + // files and therefore does not contain any of this metadata and we have to specify + // whether or not to loop elsewhere. + + dataChunk.audioData = stream->readStream(dataSize); + break; + default: + error ("Unknown tag found in 'tWAV' chunk -- '%s'", tag2str(tag)); + } + } + + // makeMohawkWaveStream always takes control of the original stream + delete stream; + + // The sound in Myst uses raw unsigned 8-bit data + // The sound in the CD version of Riven is encoded in Intel DVI ADPCM + // The sound in the DVD version of Riven is encoded in MPEG-2 Layer II or Intel DVI ADPCM + if (dataChunk.encoding == kCodecRaw) { + byte flags = Audio::FLAG_UNSIGNED; + + if (dataChunk.channels == 2) + flags |= Audio::FLAG_STEREO; + + return Audio::makeRawStream(dataChunk.audioData, dataChunk.sampleRate, flags); + } else if (dataChunk.encoding == kCodecADPCM) { + uint32 blockAlign = dataChunk.channels * dataChunk.bitsPerSample / 8; + return Audio::makeADPCMStream(dataChunk.audioData, DisposeAfterUse::YES, dataSize, Audio::kADPCMDVI, dataChunk.sampleRate, dataChunk.channels, blockAlign); + } else if (dataChunk.encoding == kCodecMPEG2) { +#ifdef USE_MAD + return Audio::makeMP3Stream(dataChunk.audioData, DisposeAfterUse::YES); +#else + warning ("MAD library not included - unable to play MP2 audio"); +#endif + } else { + error ("Unknown Mohawk WAVE encoding %d", dataChunk.encoding); + } + + return nullptr; +} + Sound::Sound(MohawkEngine* vm) : _vm(vm) { _midiDriver = NULL; _midiParser = NULL; @@ -47,7 +191,6 @@ Sound::Sound(MohawkEngine* vm) : _vm(vm) { Sound::~Sound() { stopSound(); - stopAllSLST(); stopBackgroundMyst(); if (_midiParser) { @@ -234,300 +377,6 @@ void Sound::stopMidi() { _midiParser->unloadMusic(); } -byte Sound::convertRivenVolume(uint16 volume) { - return (volume == 256) ? 255 : volume; -} - -void Sound::playSLST(uint16 index, uint16 card) { - Common::SeekableReadStream *slstStream = _vm->getResource(ID_SLST, card); - SLSTRecord slstRecord; - uint16 recordCount = slstStream->readUint16BE(); - - for (uint16 i = 0; i < recordCount; i++) { - slstRecord.index = slstStream->readUint16BE(); - slstRecord.sound_count = slstStream->readUint16BE(); - slstRecord.sound_ids = new uint16[slstRecord.sound_count]; - - for (uint16 j = 0; j < slstRecord.sound_count; j++) - slstRecord.sound_ids[j] = slstStream->readUint16BE(); - - slstRecord.fade_flags = slstStream->readUint16BE(); - slstRecord.loop = slstStream->readUint16BE(); - slstRecord.global_volume = slstStream->readUint16BE(); - slstRecord.u0 = slstStream->readUint16BE(); // Unknown - - if (slstRecord.u0 > 1) - warning("slstRecord.u0: %d non-boolean", slstRecord.u0); - - slstRecord.u1 = slstStream->readUint16BE(); // Unknown - - if (slstRecord.u1 != 0) - warning("slstRecord.u1: %d non-zero", slstRecord.u1); - - slstRecord.volumes = new uint16[slstRecord.sound_count]; - slstRecord.balances = new int16[slstRecord.sound_count]; - slstRecord.u2 = new uint16[slstRecord.sound_count]; - - for (uint16 j = 0; j < slstRecord.sound_count; j++) - slstRecord.volumes[j] = slstStream->readUint16BE(); - - for (uint16 j = 0; j < slstRecord.sound_count; j++) - slstRecord.balances[j] = slstStream->readSint16BE(); // negative = left, 0 = center, positive = right - - for (uint16 j = 0; j < slstRecord.sound_count; j++) { - slstRecord.u2[j] = slstStream->readUint16BE(); // Unknown - - if (slstRecord.u2[j] != 255 && slstRecord.u2[j] != 256) - warning("slstRecord.u2[%d]: %d not 255 or 256", j, slstRecord.u2[j]); - } - - if (slstRecord.index == index) { - playSLST(slstRecord); - delete[] slstRecord.sound_ids; - delete[] slstRecord.volumes; - delete[] slstRecord.balances; - delete[] slstRecord.u2; - delete slstStream; - return; - } - - delete[] slstRecord.sound_ids; - delete[] slstRecord.volumes; - delete[] slstRecord.balances; - delete[] slstRecord.u2; - } - - delete slstStream; - - // If we have no matching entries, we do nothing and just let - // the previous ambient sounds continue. -} - -void Sound::playSLST(SLSTRecord slstRecord) { - // End old sounds - for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) { - bool noLongerPlay = true; - for (uint16 j = 0; j < slstRecord.sound_count; j++) - if (_currentSLSTSounds[i].id == slstRecord.sound_ids[j]) - noLongerPlay = false; - if (noLongerPlay) - stopSLSTSound(i, (slstRecord.fade_flags & 1) != 0); - } - - // Start new sounds - for (uint16 i = 0; i < slstRecord.sound_count; i++) { - bool alreadyPlaying = false; - for (uint16 j = 0; j < _currentSLSTSounds.size(); j++) { - if (_currentSLSTSounds[j].id == slstRecord.sound_ids[i]) - alreadyPlaying = true; - } - if (!alreadyPlaying) { - playSLSTSound(slstRecord.sound_ids[i], - (slstRecord.fade_flags & (1 << 1)) != 0, - slstRecord.loop != 0, - slstRecord.volumes[i], - slstRecord.balances[i]); - } - } -} - -void Sound::stopAllSLST(bool fade) { - for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) { - // TODO: Fade out, if requested - _vm->_mixer->stopHandle(*_currentSLSTSounds[i].handle); - delete _currentSLSTSounds[i].handle; - } - - _currentSLSTSounds.clear(); -} - -static int8 convertBalance(int16 balance) { - return (int8)(balance >> 8); -} - -void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16 balance) { - // WORKAROUND: Some Riven SLST entries have a volume of 0, so we just ignore them. - if (volume == 0) - return; - - SLSTSndHandle sndHandle; - sndHandle.handle = new Audio::SoundHandle(); - sndHandle.id = id; - _currentSLSTSounds.push_back(sndHandle); - - Audio::RewindableAudioStream *rewindStream = makeMohawkWaveStream(_vm->getResource(ID_TWAV, id)); - - // Loop here if necessary - Audio::AudioStream *audStream = rewindStream; - if (loop) - audStream = Audio::makeLoopingAudioStream(rewindStream, 0); - - // TODO: Handle fading, possibly just raise the volume of the channel in increments? - - _vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, sndHandle.handle, audStream, -1, convertRivenVolume(volume), convertBalance(balance)); -} - -void Sound::stopSLSTSound(uint16 index, bool fade) { - // TODO: Fade out, if requested - _vm->_mixer->stopHandle(*_currentSLSTSounds[index].handle); - delete _currentSLSTSounds[index].handle; - _currentSLSTSounds.remove_at(index); -} - -void Sound::pauseSLST() { - for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) - _vm->_mixer->pauseHandle(*_currentSLSTSounds[i].handle, true); -} - -void Sound::resumeSLST() { - for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) - _vm->_mixer->pauseHandle(*_currentSLSTSounds[i].handle, false); -} - -Audio::RewindableAudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) { - uint32 tag = 0; - ADPCMStatus adpcmStatus; - DataChunk dataChunk; - uint32 dataSize = 0; - - memset(&dataChunk, 0, sizeof(DataChunk)); - - if (stream->readUint32BE() != ID_MHWK) // MHWK tag again - error ("Could not find tag 'MHWK'"); - - stream->readUint32BE(); // Skip size - - if (stream->readUint32BE() != ID_WAVE) - error ("Could not find tag 'WAVE'"); - - while (!dataChunk.audioData) { - tag = stream->readUint32BE(); - - switch (tag) { - case ID_ADPC: - debug(2, "Found Tag ADPC"); - // ADPCM Sound Only - // - // This is useful for seeking in the stream, and is actually quite brilliant - // considering some of the other things Broderbund did with the engine. - // Only Riven and CSTime are known to use ADPCM audio and only CSTime - // actually requires this for seeking. On the other hand, it may be interesting - // to look at that one Riven sample that uses the cue points. - // - // Basically, the sample frame from the cue list is looked up here and then - // sets the starting sample and step index at the point specified. Quite - // an elegant/efficient system, really. - - adpcmStatus.size = stream->readUint32BE(); - adpcmStatus.itemCount = stream->readUint16BE(); - adpcmStatus.channels = stream->readUint16BE(); - adpcmStatus.statusItems = new ADPCMStatus::StatusItem[adpcmStatus.itemCount]; - - assert(adpcmStatus.channels <= 2); - - for (uint16 i = 0; i < adpcmStatus.itemCount; i++) { - adpcmStatus.statusItems[i].sampleFrame = stream->readUint32BE(); - - for (uint16 j = 0; j < adpcmStatus.channels; j++) { - adpcmStatus.statusItems[i].channelStatus[j].last = stream->readSint16BE(); - adpcmStatus.statusItems[i].channelStatus[j].stepIndex = stream->readUint16BE(); - } - } - - // TODO: Actually use this chunk. For now, just delete the status items... - delete[] adpcmStatus.statusItems; - break; - case ID_CUE: - debug(2, "Found Tag Cue#"); - // Cues are used for animation sync. There are a couple in Myst and - // Riven but are not used there at all. - - if (!cueList) { - uint32 size = stream->readUint32BE(); - stream->skip(size); - break; - } - - cueList->size = stream->readUint32BE(); - cueList->pointCount = stream->readUint16BE(); - - if (cueList->pointCount == 0) - debug(2, "Cue# chunk found with no points!"); - else - debug(2, "Cue# chunk found with %d point(s)!", cueList->pointCount); - - cueList->points.resize(cueList->pointCount); - for (uint16 i = 0; i < cueList->pointCount; i++) { - cueList->points[i].sampleFrame = stream->readUint32BE(); - - byte nameLength = stream->readByte(); - cueList->points[i].name.clear(); - for (byte j = 0; j < nameLength; j++) - cueList->points[i].name += stream->readByte(); - - // Realign to an even boundary - if (!(nameLength & 1)) - stream->readByte(); - - debug (3, "Cue# chunk point %d (frame %d): %s", i, cueList->points[i].sampleFrame, cueList->points[i].name.c_str()); - } - break; - case ID_DATA: - debug(2, "Found Tag DATA"); - // We subtract 20 from the actual chunk size, which is the total size - // of the chunk's header - dataSize = stream->readUint32BE() - 20; - dataChunk.sampleRate = stream->readUint16BE(); - dataChunk.sampleCount = stream->readUint32BE(); - dataChunk.bitsPerSample = stream->readByte(); - dataChunk.channels = stream->readByte(); - dataChunk.encoding = stream->readUint16BE(); - dataChunk.loopCount = stream->readUint16BE(); - dataChunk.loopStart = stream->readUint32BE(); - dataChunk.loopEnd = stream->readUint32BE(); - - // NOTE: We currently ignore all of the loop parameters here. Myst uses the - // loopCount variable but the loopStart and loopEnd are always 0 and the size of - // the sample. Myst ME doesn't use the Mohawk Sound format and just standard WAVE - // files and therefore does not contain any of this metadata and we have to specify - // whether or not to loop elsewhere. - - dataChunk.audioData = stream->readStream(dataSize); - break; - default: - error ("Unknown tag found in 'tWAV' chunk -- '%s'", tag2str(tag)); - } - } - - // makeMohawkWaveStream always takes control of the original stream - delete stream; - - // The sound in Myst uses raw unsigned 8-bit data - // The sound in the CD version of Riven is encoded in Intel DVI ADPCM - // The sound in the DVD version of Riven is encoded in MPEG-2 Layer II or Intel DVI ADPCM - if (dataChunk.encoding == kCodecRaw) { - byte flags = Audio::FLAG_UNSIGNED; - - if (dataChunk.channels == 2) - flags |= Audio::FLAG_STEREO; - - return Audio::makeRawStream(dataChunk.audioData, dataChunk.sampleRate, flags); - } else if (dataChunk.encoding == kCodecADPCM) { - uint32 blockAlign = dataChunk.channels * dataChunk.bitsPerSample / 8; - return Audio::makeADPCMStream(dataChunk.audioData, DisposeAfterUse::YES, dataSize, Audio::kADPCMDVI, dataChunk.sampleRate, dataChunk.channels, blockAlign); - } else if (dataChunk.encoding == kCodecMPEG2) { -#ifdef USE_MAD - return Audio::makeMP3Stream(dataChunk.audioData, DisposeAfterUse::YES); -#else - warning ("MAD library not included - unable to play MP2 audio"); -#endif - } else { - error ("Unknown Mohawk WAVE encoding %d", dataChunk.encoding); - } - - return NULL; -} - Audio::RewindableAudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) { uint16 header = stream->readUint16BE(); uint16 rate = 0; @@ -591,18 +440,6 @@ void Sound::stopSound(uint16 id) { } } -void Sound::pauseSound() { - for (uint32 i = 0; i < _handles.size(); i++) - if (_handles[i].type == kUsedHandle) - _vm->_mixer->pauseHandle(_handles[i].handle, true); -} - -void Sound::resumeSound() { - for (uint32 i = 0; i < _handles.size(); i++) - if (_handles[i].type == kUsedHandle) - _vm->_mixer->pauseHandle(_handles[i].handle, false); -} - bool Sound::isPlaying(uint16 id) { for (uint32 i = 0; i < _handles.size(); i++) if (_handles[i].type == kUsedHandle && _handles[i].id == id) diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h index f09706e155..2b4b1ce091 100644 --- a/engines/mohawk/sound.h +++ b/engines/mohawk/sound.h @@ -42,20 +42,6 @@ namespace Mohawk { #define MAX_CHANNELS 2 // Can there be more than 2? -struct SLSTRecord { - uint16 index; - uint16 sound_count; - uint16 *sound_ids; - uint16 fade_flags; - uint16 loop; - uint16 global_volume; - uint16 u0; - uint16 u1; - uint16 *volumes; - int16 *balances; - uint16 *u2; -}; - enum SndHandleType { kFreeHandle, kUsedHandle @@ -68,11 +54,6 @@ struct SndHandle { uint16 id; }; -struct SLSTSndHandle { - Audio::SoundHandle *handle; - uint16 id; -}; - struct ADPCMStatus { // Holds ADPCM status data, but is irrelevant for us. uint32 size; uint16 itemCount; @@ -116,6 +97,8 @@ struct DataChunk { Common::SeekableReadStream *audioData; }; +Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = nullptr); + class MohawkEngine; class Sound { @@ -130,8 +113,6 @@ public: void stopMidi(); void stopSound(); void stopSound(uint16 id); - void pauseSound(); - void resumeSound(); bool isPlaying(uint16 id); bool isPlaying(); uint getNumSamplesPlayed(uint16 id); @@ -144,21 +125,12 @@ public: void stopBackgroundMyst(); void changeBackgroundVolumeMyst(uint16 vol); - // Riven-specific sound functions - void playSLST(uint16 index, uint16 card); - void playSLST(SLSTRecord slstRecord); - void pauseSLST(); - void resumeSLST(); - void stopAllSLST(bool fade = false); - static byte convertRivenVolume(uint16 volume); - private: MohawkEngine *_vm; MidiDriver *_midiDriver; MidiParser *_midiParser; byte *_midiData; - static Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL); static Audio::RewindableAudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream); void initMidi(); @@ -169,11 +141,6 @@ private: // Myst-specific SndHandle _mystBackgroundSound; - - // Riven-specific - void playSLSTSound(uint16 index, bool fade, bool loop, uint16 volume, int16 balance); - void stopSLSTSound(uint16 id, bool fade); - Common::Array<SLSTSndHandle> _currentSLSTSounds; }; } // End of namespace Mohawk diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp index 81b2edb57d..4f0899deb4 100644 --- a/engines/mortevielle/mortevielle.cpp +++ b/engines/mortevielle/mortevielle.cpp @@ -48,6 +48,10 @@ MortevielleEngine *g_vm; MortevielleEngine::MortevielleEngine(OSystem *system, const MortevielleGameDescription *gameDesc): Engine(system), _gameDescription(gameDesc), _randomSource("mortevielle") { + // Set debug channels + DebugMan.addDebugChannel(kMortevielleCore, "core", "Core debugging"); + DebugMan.addDebugChannel(kMortevielleGraphics, "graphics", "Graphics debugging"); + g_vm = this; _debugger = new Debugger(this); _dialogManager = new DialogManager(this); @@ -244,10 +248,6 @@ Common::ErrorCode MortevielleEngine::initialize() { // Initialize graphics mode initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, true); - // Set debug channels - DebugMan.addDebugChannel(kMortevielleCore, "core", "Core debugging"); - DebugMan.addDebugChannel(kMortevielleGraphics, "graphics", "Graphics debugging"); - // Set up an intermediate screen surface _screenSurface->create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8()); diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 6898745858..b20ed3f8be 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -54,7 +54,6 @@ #include "sci/graphics/frameout.h" #include "sci/graphics/paint32.h" #include "video/coktel_decoder.h" -#include "sci/video/robot_decoder.h" #endif #include "common/file.h" @@ -266,8 +265,6 @@ void Console::postEnter() { #ifdef ENABLE_SCI32 } else if (_videoFile.hasSuffix(".vmd")) { videoDecoder = new Video::AdvancedVMDDecoder(); - } else if (_videoFile.hasSuffix(".rbt")) { - videoDecoder = new RobotDecoder(_engine->getPlatform() == Common::kPlatformMacintosh); } else if (_videoFile.hasSuffix(".duk")) { duckMode = true; videoDecoder = new Video::AVIDecoder(); @@ -489,6 +486,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) { debugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); debugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); debugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); + debugPrintf("PseudoMouse ability: %s\n", _engine->_features->detectPseudoMouseAbility() == kPseudoMouseAbilityTrue ? "yes" : "no"); #ifdef ENABLE_SCI32 if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); @@ -2080,6 +2078,10 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { case SEG_TYPE_STRING: debugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); break; + + case SEG_TYPE_BITMAP: + debugPrintf("T SCI32 bitmaps (%d)", (*(BitmapTable *)mobj).entries_used); + break; #endif default: @@ -2214,6 +2216,9 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_ARRAY: debugPrintf("SCI32 arrays\n"); break; + case SEG_TYPE_BITMAP: + debugPrintf("SCI32 bitmaps\n"); + break; #endif default : @@ -2815,6 +2820,12 @@ bool Console::cmdViewReference(int argc, const char **argv) { hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true); break; } + case SEG_TYPE_BITMAP: { + debugPrintf("SCI32 bitmap:\n"); + const SciBitmap *bitmap = _engine->_gamestate->_segMan->lookupBitmap(reg); + Common::hexdump((const byte *) bitmap->getRawData(), bitmap->getRawSize(), 16, 0); + break; + } #endif default: { const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index f5797dc106..ad2b0f31a5 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -565,8 +565,8 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, // the file should be over 10MB, as it contains all the game speech and is usually // around 450MB+. The size check is for some floppy game versions like KQ6 floppy, which // also have a small resource.aud file - if (allFiles.contains("resource.aud") || allFiles.contains("audio001.002")) { - Common::FSNode file = allFiles.contains("resource.aud") ? allFiles["resource.aud"] : allFiles["audio001.002"]; + if (allFiles.contains("resource.aud") || allFiles.contains("resaud.001") || allFiles.contains("audio001.002")) { + Common::FSNode file = allFiles.contains("resource.aud") ? allFiles["resource.aud"] : (allFiles.contains("resaud.001") ? allFiles["resaud.001"] : allFiles["audio001.002"]); Common::SeekableReadStream *tmpStream = file.createReadStream(); if (tmpStream->size() > 10 * 1024 * 1024) { // We got a CD version, so set the CD flag accordingly diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index b945b5559c..eda6bfae64 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -22,15 +22,7 @@ namespace Sci { -#define GAMEOPTION_PREFER_DIGITAL_SFX GUIO_GAMEOPTIONS1 -#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS2 -#define GAMEOPTION_FB01_MIDI GUIO_GAMEOPTIONS3 -#define GAMEOPTION_JONES_CDAUDIO GUIO_GAMEOPTIONS4 -#define GAMEOPTION_KQ6_WINDOWS_CURSORS GUIO_GAMEOPTIONS5 -#define GAMEOPTION_SQ4_SILVER_CURSORS GUIO_GAMEOPTIONS6 -#define GAMEOPTION_EGA_UNDITHER GUIO_GAMEOPTIONS7 -#define GAMEOPTION_HIGH_RESOLUTION_GRAPHICS GUIO_GAMEOPTIONS8 -#define GAMEOPTION_ENABLE_BLACK_LINED_VIDEO GUIO_GAMEOPTIONS9 +#include "sci/sci.h" // SCI3 games have a different script format (in CSC files) and are currently unsupported #define ENABLE_SCI3_GAMES @@ -734,8 +726,9 @@ static const struct ADGameDescription SciGameDescriptions[] = { GAMEOPTION_PREFER_DIGITAL_SFX, \ GAMEOPTION_ORIGINAL_SAVELOAD, \ GAMEOPTION_FB01_MIDI) -#define GUIO_GK1_CD GUIO3(GAMEOPTION_PREFER_DIGITAL_SFX, \ +#define GUIO_GK1_CD GUIO4(GAMEOPTION_PREFER_DIGITAL_SFX, \ GAMEOPTION_ORIGINAL_SAVELOAD, \ + GAMEOPTION_HIGH_RESOLUTION_GRAPHICS, \ GAMEOPTION_FB01_MIDI) #define GUIO_GK1_MAC GUIO_GK1_FLOPPY @@ -835,7 +828,10 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::ES_ESP, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO_GK1_CD }, - // Gabriel Knight - English Macintosh + // Gabriel Knight - English Macintosh (Floppy!) + // This version is hi-res ONLY, so it should NOT get GAMEOPTION_HIGH_RESOLUTION_GRAPHICS + // (which is meant for enforcing hi-res graphics), but instead hi-res mode should be enabled all the time. + // Confirmed by [md5] and originally by clone2727. {"gk1", "", { {"Data1", 0, "044d3bcd7e5b5bb0393d954ade8053fe", 5814918}, {"Data2", 0, "99a0c63febf9e44e12a00f99c00eae0f", 6685352}, @@ -3772,6 +3768,14 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO_QFG4_CD }, + // Quest for Glory 4 CD - English DOS/Windows (from jvprat) + // Executable scanning reports "2.100.002", VERSION file reports "1.0" + {"qfg4", "CD", { + {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246}, + {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD | ADGF_UNSTABLE, GUIO_QFG4_CD }, + #define GUIO_RAMA_DEMO GUIO5(GAMEOPTION_ENABLE_BLACK_LINED_VIDEO, \ GUIO_NOASPECT, \ GAMEOPTION_PREFER_DIGITAL_SFX, \ diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index a993506f7a..e37a1651ef 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -45,6 +45,7 @@ GameFeatures::GameFeatures(SegManager *segMan, Kernel *kernel) : _segMan(segMan) if (!ConfMan.getBool("use_cdaudio")) _usesCdTrack = false; _forceDOSTracks = false; + _pseudoMouseAbility = kPseudoMouseAbilityUninitialized; } reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc, int methodNum) { @@ -605,4 +606,50 @@ bool GameFeatures::useAltWinGMSound() { } } +// PseudoMouse was added during SCI1 +// PseudoMouseAbility is about a tiny difference in the keyboard driver, which sets the event type to either +// 40h (old behaviour) or 44h (the keyboard driver actually added 40h to the existing value). +// See engine/kevent.cpp, kMapKeyToDir - also script 933 + +// SCI1EGA: +// Quest for Glory 2 still used the old way. +// +// SCI1EARLY: +// King's Quest 5 0.000.062 uses the old way. +// Leisure Suit Larry 1 demo uses the new way, but no PseudoMouse class. +// Fairy Tales uses the new way. +// X-Mas 1990 uses the old way, no PseudoMouse class. +// Space Quest 4 floppy (1.1) uses the new way. +// Mixed Up Mother Goose uses the old way, no PseudoMouse class. +// +// SCI1MIDDLE: +// Leisure Suit Larry 5 demo uses the new way. +// Conquests of the Longbow demo uses the new way. +// Leisure Suit Larry 1 (2.0) uses the new way. +// Astro Chicken II uses the new way. +PseudoMouseAbilityType GameFeatures::detectPseudoMouseAbility() { + if (_pseudoMouseAbility == kPseudoMouseAbilityUninitialized) { + if (getSciVersion() < SCI_VERSION_1_EARLY) { + // SCI1 EGA or earlier -> pseudo mouse ability is always disabled + _pseudoMouseAbility = kPseudoMouseAbilityFalse; + + } else if (getSciVersion() == SCI_VERSION_1_EARLY) { + // For SCI1 early some games had it enabled, some others didn't. + // We try to find an object called "PseudoMouse". If it's found, we enable the ability otherwise we don't. + reg_t pseudoMouseAddr = _segMan->findObjectByName("PseudoMouse", 0); + + if (pseudoMouseAddr != NULL_REG) { + _pseudoMouseAbility = kPseudoMouseAbilityTrue; + } else { + _pseudoMouseAbility = kPseudoMouseAbilityFalse; + } + + } else { + // SCI1 middle or later -> pseudo mouse ability is always enabled + _pseudoMouseAbility = kPseudoMouseAbilityTrue; + } + } + return _pseudoMouseAbility; +} + } // End of namespace Sci diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h index 1c410267e6..b2d40f400f 100644 --- a/engines/sci/engine/features.h +++ b/engines/sci/engine/features.h @@ -34,6 +34,12 @@ enum MoveCountType { kIncrementMoveCount }; +enum PseudoMouseAbilityType { + kPseudoMouseAbilityUninitialized, + kPseudoMouseAbilityFalse, + kPseudoMouseAbilityTrue +}; + class GameFeatures { public: GameFeatures(SegManager *segMan, Kernel *kernel); @@ -110,6 +116,12 @@ public: */ void forceDOSTracks() { _forceDOSTracks = true; } + /** + * Autodetects, if Pseudo Mouse ability is enabled (different behavior in keyboard driver) + * @return kPseudoMouseAbilityTrue or kPseudoMouseAbilityFalse + */ + PseudoMouseAbilityType detectPseudoMouseAbility(); + private: reg_t getDetectionAddr(const Common::String &objName, Selector slc, int methodNum = -1); @@ -130,6 +142,8 @@ private: bool _usesCdTrack; bool _forceDOSTracks; + PseudoMouseAbilityType _pseudoMouseAbility; + SegManager *_segMan; Kernel *_kernel; }; diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp index 156f6f51f7..8cecd8c82c 100644 --- a/engines/sci/engine/file.cpp +++ b/engines/sci/engine/file.cpp @@ -200,7 +200,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u #ifdef ENABLE_SCI32 if (mode != _K_FILE_MODE_OPEN_OR_FAIL && ( - (g_sci->getGameId() == GID_PHANTASMAGORIA && filename == "phantsg.dir") || + (g_sci->getGameId() == GID_PHANTASMAGORIA && (filename == "phantsg.dir" || filename == "chase.dat")) || (g_sci->getGameId() == GID_PQSWAT && filename == "swat.dat"))) { debugC(kDebugLevelFile, " -> file_open opening %s for rewriting", wrappedName.c_str()); diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index b229490570..6c1713bed9 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -143,22 +143,31 @@ AddrSet *findAllActiveReferences(EngineState *s) { const Common::Array<SegmentObj *> &heap = s->_segMan->getSegments(); uint heapSize = heap.size(); - // Init: Explicitly loaded scripts for (uint i = 1; i < heapSize; i++) { - if (heap[i] && heap[i]->getType() == SEG_TYPE_SCRIPT) { - Script *script = (Script *)heap[i]; + if (heap[i]) { + // Init: Explicitly loaded scripts + if (heap[i]->getType() == SEG_TYPE_SCRIPT) { + Script *script = (Script *)heap[i]; - if (script->getLockers()) { // Explicitly loaded? - wm.pushArray(script->listObjectReferences()); + if (script->getLockers()) { // Explicitly loaded? + wm.pushArray(script->listObjectReferences()); + } } - } - } #ifdef ENABLE_SCI32 - // Init: ScrollWindows - if (g_sci->_gfxControls32) - wm.pushArray(g_sci->_gfxControls32->listObjectReferences()); + // Init: Explicitly opted-out bitmaps + else if (heap[i]->getType() == SEG_TYPE_BITMAP) { + BitmapTable *bt = static_cast<BitmapTable *>(heap[i]); + + for (uint j = 0; j < bt->_table.size(); j++) { + if (bt->_table[j].data && bt->_table[j].data->getShouldGC() == false) { + wm.push(make_reg(i, j)); + } + } + } #endif + } + } debugC(kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set"); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2afb8b73d1..d764a88a0a 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -408,6 +408,7 @@ uint16 Kernel::findRegType(reg_t reg) { #ifdef ENABLE_SCI32 case SEG_TYPE_ARRAY: case SEG_TYPE_STRING: + case SEG_TYPE_BITMAP: #endif result |= SIG_TYPE_REFERENCE; break; diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 5ff4f932be..45477e1153 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -421,6 +421,14 @@ reg_t kStubNull(EngineState *s, int argc, reg_t *argv); #ifdef ENABLE_SCI32 // SCI2 Kernel Functions +reg_t kSetCursor32(EngineState *s, int argc, reg_t *argv); +reg_t kSetNowSeen32(EngineState *s, int argc, reg_t *argv); +reg_t kBaseSetter32(EngineState *s, int argc, reg_t *argv); +reg_t kShakeScreen32(EngineState *s, int argc, reg_t *argv); +reg_t kPlatform32(EngineState *s, int argc, reg_t *argv); +reg_t kGlobalToLocal32(EngineState *s, int argc, reg_t *argv); +reg_t kLocalToGlobal32(EngineState *s, int argc, reg_t *argv); + reg_t kDoAudio32(EngineState *s, int argc, reg_t *argv); reg_t kDoAudioInit(EngineState *s, int argc, reg_t *argv); reg_t kDoAudioWaitForPlay(EngineState *s, int argc, reg_t *argv); @@ -441,15 +449,40 @@ reg_t kDoAudioFade(EngineState *s, int argc, reg_t *argv); reg_t kDoAudioHasSignal(EngineState *s, int argc, reg_t *argv); reg_t kDoAudioSetLoop(EngineState *s, int argc, reg_t *argv); +reg_t kRobot(EngineState *s, int argc, reg_t *argv); +reg_t kRobotOpen(EngineState *s, int argc, reg_t *argv); +reg_t kRobotShowFrame(EngineState *s, int argc, reg_t *argv); +reg_t kRobotGetFrameSize(EngineState *s, int argc, reg_t *argv); +reg_t kRobotPlay(EngineState *s, int argc, reg_t *argv); +reg_t kRobotGetIsFinished(EngineState *s, int argc, reg_t *argv); +reg_t kRobotGetIsPlaying(EngineState *s, int argc, reg_t *argv); +reg_t kRobotClose(EngineState *s, int argc, reg_t *argv); +reg_t kRobotGetCue(EngineState *s, int argc, reg_t *argv); +reg_t kRobotPause(EngineState *s, int argc, reg_t *argv); +reg_t kRobotGetFrameNo(EngineState *s, int argc, reg_t *argv); +reg_t kRobotSetPriority(EngineState *s, int argc, reg_t *argv); + reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDOpen(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDInit(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDClose(EngineState *s, int argc, reg_t *argv); +reg_t kPlayVMDGetStatus(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDPlayUntilEvent(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDShowCursor(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDSetBlackoutArea(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMDRestrictPalette(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovie32(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWin(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinOpen(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinInit(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinPlay(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinClose(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinCue(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinGetDuration(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinPlayUntilEvent(EngineState *s, int argc, reg_t *argv); +reg_t kShowMovieWinInitDouble(EngineState *s, int argc, reg_t *argv); + reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv); reg_t kArray(EngineState *s, int argc, reg_t *argv); reg_t kListAt(EngineState *s, int argc, reg_t *argv); @@ -550,6 +583,7 @@ reg_t kSetScroll(EngineState *s, int argc, reg_t *argv); reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv); reg_t kPaletteFindColor32(EngineState *s, int argc, reg_t *argv); reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetGamma(EngineState *s, int argc, reg_t *argv); reg_t kPalCycle(EngineState *s, int argc, reg_t *argv); reg_t kPalCycleSetCycle(EngineState *s, int argc, reg_t *argv); @@ -576,9 +610,9 @@ reg_t kTextWidth(EngineState *s, int argc, reg_t *argv); reg_t kSave(EngineState *s, int argc, reg_t *argv); reg_t kAutoSave(EngineState *s, int argc, reg_t *argv); reg_t kList(EngineState *s, int argc, reg_t *argv); -reg_t kRobot(EngineState *s, int argc, reg_t *argv); -reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv); reg_t kCD(EngineState *s, int argc, reg_t *argv); +reg_t kCheckCD(EngineState *s, int argc, reg_t *argv); +reg_t kGetSavedCD(EngineState *s, int argc, reg_t *argv); reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv); reg_t kAddBefore(EngineState *s, int argc, reg_t *argv); reg_t kMoveToFront(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 8a1176eed8..9c0fb2267b 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -183,8 +183,8 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { }; #ifdef ENABLE_SCI32 -// NOTE: In SSCI, some 'unused' kDoAudio subops are actually -// called indirectly by kDoSound: +// NOTE: In SSCI, some 'unused' kDoAudio subops are actually called indirectly +// by kDoSound: // // kDoSoundGetAudioCapability -> kDoAudioGetCapability // kDoSoundPlay -> kDoAudioPlay, kDoAudioStop @@ -194,23 +194,26 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { // kDoSoundSetLoop -> kDoAudioSetLoop // kDoSoundUpdateCues -> kDoAudioPosition // -// In ScummVM, logic inside these kernel functions has been -// moved to methods of Audio32, and direct calls to Audio32 -// are made from kDoSound instead. +// In ScummVM, logic inside these kernel functions has been moved to methods of +// Audio32, and direct calls to Audio32 are made from kDoSound instead. // -// Some kDoAudio methods are esoteric and appear to be used -// only by one or two games: +// Some kDoAudio methods are esoteric and appear to be used only by one or two +// games: // -// kDoAudioMixing: Phantasmagoria (other games call this -// function, but only to disable the feature) -// kDoAudioHasSignal: SQ6 TalkRandCycle -// kDoAudioPan: Rama RegionSFX::pan method +// - kDoAudioMixing: Phantasmagoria (other games call this function, but only +// to disable the feature) +// - kDoAudioHasSignal: SQ6 TalkRandCycle +// - kDoAudioPan: Rama RegionSFX::pan method +// - kDoAudioCritical: Phantasmagoria, chapter 3, nursery (room 14200), during +// the "ghost lullaby" event. It is used to make the +// lullaby sound exclusive, but it really doesn't make any +// major difference. Returning 0 means "non-critical", i.e. +// normal audio behavior. // -// Finally, there is a split in SCI2.1mid audio code. -// QFG4CD & SQ6 do not have opcodes 18 and 19, but they -// exist in GK2, KQ7 2.00b, Phantasmagoria 1, PQ:SWAT, and -// Torin. (It is unknown if they exist in MUMG Deluxe or -// Shivers 1; they are not used in either of these games.) +// Finally, there is a split in SCI2.1mid audio code. QFG4CD & SQ6 do not have +// opcodes 18 and 19, but they exist in GK2, KQ7 2.00b, Phantasmagoria 1, +// PQ:SWAT, and Torin. It is unknown if they exist in MUMG Deluxe or Shivers 1; +// they are not used in either of these games. // version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kDoAudio_subops[] = { @@ -235,7 +238,7 @@ static const SciKernelMapSubEntry kDoAudio_subops[] = { { SIG_SINCE_SCI21MID, 15, MAP_CALL(DoAudioFade), "(iiii)(i)(i)", NULL }, { SIG_SINCE_SCI21MID, 16, MAP_DUMMY(DoAudioFade36), "iiiii(iii)(i)", NULL }, { SIG_SINCE_SCI21MID, 17, MAP_CALL(DoAudioHasSignal), "", NULL }, - { SIG_SINCE_SCI21MID, 18, MAP_EMPTY(DoAudioCritical), "", NULL }, + { SIG_SINCE_SCI21MID, 18, MAP_EMPTY(DoAudioCritical), "(i)", NULL }, { SIG_SINCE_SCI21MID, 19, MAP_CALL(DoAudioSetLoop), "iii(o)", NULL }, { SIG_SCI3, 20, MAP_DUMMY(DoAudioPan), "", NULL }, { SIG_SCI3, 21, MAP_DUMMY(DoAudioPanOff), "", NULL }, @@ -294,16 +297,17 @@ static const SciKernelMapSubEntry kPalette_subops[] = { { SIG_SCI16, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL }, { SIG_SCI16, 2, MAP_CALL(PaletteSetFlag), "iii", NULL }, { SIG_SCI16, 3, MAP_CALL(PaletteUnsetFlag), "iii", kPaletteUnsetFlag_workarounds }, -#ifdef ENABLE_SCI32 - { SIG_SCI32, 1, MAP_CALL(PaletteSetFromResource32), "i(i)", NULL }, - { SIG_SCI32, 2, MAP_CALL(PaletteSetFade), "iii", NULL }, - { SIG_SCI32, 3, MAP_CALL(PaletteFindColor32), "iii", NULL }, -#endif { SIG_SCI16, 4, MAP_CALL(PaletteSetIntensity), "iii(i)", NULL }, { SIG_SCI16, 5, MAP_CALL(PaletteFindColor), "iii", NULL }, { SIG_SCI16, 6, MAP_CALL(PaletteAnimate), "i*", NULL }, { SIG_SCI16, 7, MAP_CALL(PaletteSave), "", NULL }, { SIG_SCI16, 8, MAP_CALL(PaletteRestore), "[r0]", NULL }, +#ifdef ENABLE_SCI32 + { SIG_SCI32, 1, MAP_CALL(PaletteSetFromResource32), "i(i)", NULL }, + { SIG_SCI32, 2, MAP_CALL(PaletteSetFade), "iii", NULL }, + { SIG_SCI32, 3, MAP_CALL(PaletteFindColor32), "iii", NULL }, + { SIG_SCI3, 4, MAP_CALL(PaletteSetGamma), "i", NULL }, +#endif SCI_SUBOPENTRY_TERMINATOR }; @@ -396,6 +400,13 @@ static const SciKernelMapSubEntry kBitmap_subops[] = { }; // version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kCD_subops[] = { + { SIG_SINCE_SCI21MID, 0, MAP_CALL(CheckCD), "(i)", NULL }, + { SIG_SINCE_SCI21MID, 1, MAP_CALL(GetSavedCD), "", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; + +// version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kList_subops[] = { { SIG_SINCE_SCI21, 0, MAP_CALL(NewList), "", NULL }, { SIG_SINCE_SCI21, 1, MAP_CALL(DisposeList), "l", NULL }, @@ -406,8 +417,8 @@ static const SciKernelMapSubEntry kList_subops[] = { { SIG_SINCE_SCI21, 6, MAP_CALL(NextNode), "n", NULL }, { SIG_SINCE_SCI21, 7, MAP_CALL(PrevNode), "n", NULL }, { SIG_SINCE_SCI21, 8, MAP_CALL(NodeValue), "[n0]", NULL }, - { SIG_SINCE_SCI21, 9, MAP_CALL(AddAfter), "lnn.", NULL }, - { SIG_SINCE_SCI21, 10, MAP_CALL(AddToFront), "ln.", NULL }, + { SIG_SINCE_SCI21, 9, MAP_CALL(AddAfter), "lnn(.)", NULL }, + { SIG_SINCE_SCI21, 10, MAP_CALL(AddToFront), "ln(.)", NULL }, { SIG_SINCE_SCI21, 11, MAP_CALL(AddToEnd), "ln(.)", NULL }, { SIG_SINCE_SCI21, 12, MAP_CALL(AddBefore), "ln.", NULL }, { SIG_SINCE_SCI21, 13, MAP_CALL(MoveToFront), "ln", NULL }, @@ -423,6 +434,27 @@ static const SciKernelMapSubEntry kList_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +// version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kShowMovieWin_subops[] = { + { SIG_SCI2, 0, MAP_CALL(ShowMovieWinOpen), "r", NULL }, + { SIG_SCI2, 1, MAP_CALL(ShowMovieWinInit), "ii(ii)", NULL }, + { SIG_SCI2, 2, MAP_CALL(ShowMovieWinPlay), "i", NULL }, + { SIG_SCI2, 6, MAP_CALL(ShowMovieWinClose), "", NULL }, + { SIG_SINCE_SCI21, 0, MAP_CALL(ShowMovieWinOpen), "ir", NULL }, + { SIG_SINCE_SCI21, 1, MAP_CALL(ShowMovieWinInit), "iii(ii)", NULL }, + { SIG_SINCE_SCI21, 2, MAP_CALL(ShowMovieWinPlay), "i(ii)(i)(i)", NULL }, + { SIG_SINCE_SCI21, 6, MAP_CALL(ShowMovieWinClose), "i", NULL }, + // Since movies are rendered within the graphics engine in ScummVM, + // it is not necessary to copy the palette from SCI to MCI, so this + // can be a no-op + { SIG_SINCE_SCI21, 7, MAP_EMPTY(ShowMovieWinSetPalette), "i", NULL }, + { SIG_SINCE_SCI21, 8, MAP_CALL(ShowMovieWinGetDuration), "i", NULL }, + { SIG_SINCE_SCI21, 11, MAP_CALL(ShowMovieWinCue), "ii", NULL }, + { SIG_SINCE_SCI21, 14, MAP_CALL(ShowMovieWinPlayUntilEvent), "i(i)", NULL }, + { SIG_SINCE_SCI21, 15, MAP_CALL(ShowMovieWinInitDouble), "iii", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; + // There are a lot of subops to PlayVMD, but only a few of them are ever // actually used by games // version, subId, function-mapping, signature, workarounds @@ -430,12 +462,30 @@ static const SciKernelMapSubEntry kPlayVMD_subops[] = { { SIG_SINCE_SCI21, 0, MAP_CALL(PlayVMDOpen), "r(i)(i)", NULL }, { SIG_SINCE_SCI21, 1, MAP_CALL(PlayVMDInit), "ii(i)(i)(ii)", NULL }, { SIG_SINCE_SCI21, 6, MAP_CALL(PlayVMDClose), "", NULL }, + { SIG_SINCE_SCI21, 10, MAP_CALL(PlayVMDGetStatus), "", NULL }, { SIG_SINCE_SCI21, 14, MAP_CALL(PlayVMDPlayUntilEvent), "i(i)(i)", NULL }, { SIG_SINCE_SCI21, 16, MAP_CALL(PlayVMDShowCursor), "i", NULL }, { SIG_SINCE_SCI21, 17, MAP_DUMMY(PlayVMDStartBlob), "", NULL }, { SIG_SINCE_SCI21, 18, MAP_DUMMY(PlayVMDStopBlobs), "", NULL }, { SIG_SINCE_SCI21, 21, MAP_CALL(PlayVMDSetBlackoutArea), "iiii", NULL }, { SIG_SINCE_SCI21, 23, MAP_CALL(PlayVMDRestrictPalette), "ii", NULL }, + { SIG_SCI3, 28, MAP_EMPTY(PlayVMDSetPreload), "i", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; + +// version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kRobot_subops[] = { + { SIG_SINCE_SCI21, 0, MAP_CALL(RobotOpen), "ioiii(i)", NULL }, + { SIG_SINCE_SCI21, 1, MAP_CALL(RobotShowFrame), "i(ii)", NULL }, + { SIG_SINCE_SCI21, 2, MAP_CALL(RobotGetFrameSize), "r", NULL }, + { SIG_SINCE_SCI21, 4, MAP_CALL(RobotPlay), "", NULL }, + { SIG_SINCE_SCI21, 5, MAP_CALL(RobotGetIsFinished), "", NULL }, + { SIG_SINCE_SCI21, 6, MAP_CALL(RobotGetIsPlaying), "", NULL }, + { SIG_SINCE_SCI21, 7, MAP_CALL(RobotClose), "", NULL }, + { SIG_SINCE_SCI21, 8, MAP_CALL(RobotGetCue), "o", NULL }, + { SIG_SINCE_SCI21, 10, MAP_CALL(RobotPause), "", NULL }, + { SIG_SINCE_SCI21, 11, MAP_CALL(RobotGetFrameNo), "", NULL }, + { SIG_SINCE_SCI21, 12, MAP_CALL(RobotSetPriority), "i", NULL }, SCI_SUBOPENTRY_TERMINATOR }; @@ -455,7 +505,7 @@ static const SciKernelMapSubEntry kString_subops[] = { { SIG_SCI32, 0, MAP_CALL(StringNew), "i(i)", NULL }, { SIG_SCI32, 1, MAP_CALL(StringSize), "[or]", NULL }, { SIG_SCI32, 2, MAP_CALL(StringAt), "[or]i", NULL }, - { SIG_SCI32, 3, MAP_CALL(StringPutAt), "[or]i(i*)", NULL }, + { SIG_SCI32, 3, MAP_CALL(StringPutAt), "[or]i(i*)", kStringPutAt_workarounds }, // StringFree accepts invalid references { SIG_SCI32, 4, MAP_CALL(StringFree), "[or0!]", NULL }, { SIG_SCI32, 5, MAP_CALL(StringFill), "[or]ii", NULL }, @@ -548,7 +598,10 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL }, { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL }, - { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(BaseSetter), SIG_SCI16, SIGFOR_ALL, "o", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "BaseSetter", kBaseSetter32, SIG_SCI32, SIGFOR_ALL, "o", NULL, NULL }, +#endif { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, { MAP_CALL(CantBeHere), SIG_SCI16, SIGFOR_ALL, "o(l)", NULL, NULL }, #ifdef ENABLE_SCI32 @@ -617,8 +670,10 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL }, { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, - { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, - { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_SCI16, SIGFOR_ALL, "o", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "GlobalToLocal", kGlobalToLocal32, SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, +#endif { MAP_CALL(Graph), SIG_EVERYWHERE, NULL, kGraph_subops, NULL }, { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, @@ -629,8 +684,10 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL }, { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL }, - { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, - { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_SCI16, SIGFOR_ALL, "o", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "LocalToGlobal", kLocalToGlobal32, SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, +#endif { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, kMemory_workarounds }, // subop @@ -655,11 +712,15 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", kPalette_subops, NULL }, { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, - { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Platform), SIG_SCI16, SIGFOR_ALL, "(.*)", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "Platform", kPlatform32, SIG_SCI32, SIGFOR_MAC, "(.*)", NULL, NULL }, + { "Platform", kPlatform32, SIG_SCI32, SIGFOR_ALL, "(i)", NULL, NULL }, +#endif { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL }, { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, NULL }, + { MAP_CALL(Random), SIG_EVERYWHERE, "i(i)(i)", NULL, kRandom_workarounds }, { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, kReadNumber_workarounds }, { MAP_CALL(RemapColors), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, NULL }, #ifdef ENABLE_SCI32 @@ -672,23 +733,32 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, { MAP_CALL(SaveGame), SIG_EVERYWHERE, "[r0]i[r0](r0)", NULL, NULL }, { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, - { MAP_CALL(SetCursor), SIG_SINCE_SCI21, SIGFOR_ALL, "i(i)([io])(i*)", NULL, NULL }, - // TODO: SCI2.1 may supply an object optionally (mother goose sci21 right on startup) - find out why { MAP_CALL(SetCursor), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(iiiiii)", NULL, NULL }, - { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i)(i)(i)(i)", NULL, kSetCursor_workarounds }, + { MAP_CALL(SetCursor), SIG_SCI16, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, kSetCursor_workarounds }, +#ifdef ENABLE_SCI32 + { "SetCursor", kSetCursor32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)", NULL, kSetCursor_workarounds }, +#endif { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL }, { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL }, { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, { MAP_CALL(SetNowSeen), SIG_SCI16, SIGFOR_ALL, "o(i)", NULL, NULL }, #ifdef ENABLE_SCI32 - { MAP_CALL(SetNowSeen), SIG_SCI32, SIGFOR_ALL, "o", NULL, NULL }, + { "SetNowSeen", kSetNowSeen32, SIG_SCI32, SIGFOR_ALL, "o", NULL, NULL }, #endif { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iiiii)(i)", NULL, kSetPort_workarounds }, { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL }, - { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(ShakeScreen), SIG_SCI16, SIGFOR_ALL, "(i)(i)", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "ShakeScreen", kShakeScreen32, SIG_SCI32, SIGFOR_ALL, "i(i)", NULL, NULL }, +#endif + { MAP_CALL(ShowMovie), SIG_SCI16, SIGFOR_ALL, "(.*)", NULL, NULL }, +#ifdef ENABLE_SCI32 + { "ShowMovie", kShowMovie32, SIG_SCI32, SIGFOR_DOS, "ri(i)(i)", NULL, NULL }, + { "ShowMovie", kShowMovie32, SIG_SCI32, SIGFOR_MAC, "ri(i)(i)", NULL, NULL }, + { "ShowMovie", kShowMovieWin, SIG_SCI32, SIGFOR_WIN, "(.*)", kShowMovieWin_subops, NULL }, +#endif { MAP_CALL(Show), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL }, @@ -772,7 +842,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(EditText), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(MakeSaveCatName), SIG_EVERYWHERE, "rr", NULL, NULL }, { MAP_CALL(MakeSaveFileName), SIG_EVERYWHERE, "rri", NULL, NULL }, - { MAP_CALL(SetScroll), SIG_EVERYWHERE, "oiiiii(i)", NULL, NULL }, + { MAP_CALL(SetScroll), SIG_EVERYWHERE, "oiiii(i)(i)", NULL, NULL }, { MAP_CALL(PalCycle), SIG_EVERYWHERE, "(.*)", kPalCycle_subops, NULL }, // SCI2 Empty functions @@ -815,15 +885,15 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_DUMMY(PointSize), SIG_EVERYWHERE, "(.*)", NULL, NULL }, // SCI2.1 Kernel Functions - { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(CD), SIG_SINCE_SCI21MID, SIGFOR_ALL, "(.*)", kCD_subops, NULL }, { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iioi", NULL, NULL }, { MAP_CALL(List), SIG_SINCE_SCI21, SIGFOR_ALL, "(.*)", kList_subops, NULL }, { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", kPlayVMD_subops, NULL }, - { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", kRobot_subops, NULL }, { MAP_CALL(Save), SIG_EVERYWHERE, "i(.*)", kSave_subops, NULL }, { MAP_CALL(Text), SIG_SINCE_SCI21MID, SIGFOR_ALL, "i(.*)", kText_subops, NULL }, - { MAP_CALL(AddPicAt), SIG_EVERYWHERE, "oiii", NULL, NULL }, + { MAP_CALL(AddPicAt), SIG_EVERYWHERE, "oiii(i)(i)", NULL, NULL }, { MAP_CALL(GetWindowsOption), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(WinHelp), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(GetConfig), SIG_EVERYWHERE, "ro", NULL, NULL }, diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 534d9ce713..9250e0fc13 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -34,6 +34,9 @@ #include "sci/graphics/coordadjuster.h" #include "sci/graphics/cursor.h" #include "sci/graphics/maciconbar.h" +#ifdef ENABLE_SCI32 +#include "sci/graphics/frameout.h" +#endif namespace Sci { @@ -58,10 +61,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { if (g_debug_simulated_key && (mask & SCI_EVENT_KEYBOARD)) { // In case we use a simulated event we query the current mouse position mousePos = g_sci->_gfxCursor->getPosition(); -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2_1_EARLY) - g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x); -#endif + // Limit the mouse cursor position, if necessary g_sci->_gfxCursor->refreshPosition(); @@ -86,11 +86,14 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) mousePos = curEvent.mousePosSci; - else + else { #endif mousePos = curEvent.mousePos; - // Limit the mouse cursor position, if necessary - g_sci->_gfxCursor->refreshPosition(); + // Limit the mouse cursor position, if necessary + g_sci->_gfxCursor->refreshPosition(); +#ifdef ENABLE_SCI32 + } +#endif if (g_sci->getVocabulary()) g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event @@ -258,11 +261,12 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) { if (readSelectorValue(segMan, obj, SELECTOR(type)) == SCI_EVENT_KEYBOARD) { // Keyboard uint16 message = readSelectorValue(segMan, obj, SELECTOR(message)); uint16 eventType = SCI_EVENT_DIRECTION; - // Check if the game is using cursor views. These games allowed control - // of the mouse cursor via the keyboard controls (the so called - // "PseudoMouse" functionality in script 933). - if (g_sci->_features->detectSetCursorType() == SCI_VERSION_1_1) + // It seems with SCI1 Sierra started to add the SCI_EVENT_DIRECTION bit instead of setting it directly. + // It was done inside the keyboard driver and is required for the PseudoMouse functionality and class + // to work (script 933). + if (g_sci->_features->detectPseudoMouseAbility() == kPseudoMouseAbilityTrue) { eventType |= SCI_EVENT_KEYBOARD; + } for (int i = 0; i < 9; i++) { if (keyToDirMap[i].key == message) { @@ -280,14 +284,13 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) { reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[0]; - reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32 SegManager *segMan = s->_segMan; if (obj.getSegment()) { int16 x = readSelectorValue(segMan, obj, SELECTOR(x)); int16 y = readSelectorValue(segMan, obj, SELECTOR(y)); - g_sci->_gfxCoordAdjuster->kernelGlobalToLocal(x, y, planeObject); + g_sci->_gfxCoordAdjuster->kernelGlobalToLocal(x, y); writeSelectorValue(segMan, obj, SELECTOR(x), x); writeSelectorValue(segMan, obj, SELECTOR(y), y); @@ -299,14 +302,13 @@ reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) { reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[0]; - reg_t planeObject = argc > 1 ? argv[1] : NULL_REG; // SCI32 SegManager *segMan = s->_segMan; if (obj.getSegment()) { int16 x = readSelectorValue(segMan, obj, SELECTOR(x)); int16 y = readSelectorValue(segMan, obj, SELECTOR(y)); - g_sci->_gfxCoordAdjuster->kernelLocalToGlobal(x, y, planeObject); + g_sci->_gfxCoordAdjuster->kernelLocalToGlobal(x, y); writeSelectorValue(segMan, obj, SELECTOR(x), x); writeSelectorValue(segMan, obj, SELECTOR(y), y); @@ -321,4 +323,52 @@ reg_t kJoystick(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +#ifdef ENABLE_SCI32 +reg_t kGlobalToLocal32(EngineState *s, int argc, reg_t *argv) { + const reg_t result = argv[0]; + const reg_t planeObj = argv[1]; + + bool visible = true; + Plane *plane = g_sci->_gfxFrameout->getVisiblePlanes().findByObject(planeObj); + if (plane == nullptr) { + plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObj); + visible = false; + } + if (plane == nullptr) { + error("kGlobalToLocal: Plane %04x:%04x not found", PRINT_REG(planeObj)); + } + + const int16 x = readSelectorValue(s->_segMan, result, SELECTOR(x)) - plane->_gameRect.left; + const int16 y = readSelectorValue(s->_segMan, result, SELECTOR(y)) - plane->_gameRect.top; + + writeSelectorValue(s->_segMan, result, SELECTOR(x), x); + writeSelectorValue(s->_segMan, result, SELECTOR(y), y); + + return make_reg(0, visible); +} + +reg_t kLocalToGlobal32(EngineState *s, int argc, reg_t *argv) { + const reg_t result = argv[0]; + const reg_t planeObj = argv[1]; + + bool visible = true; + Plane *plane = g_sci->_gfxFrameout->getVisiblePlanes().findByObject(planeObj); + if (plane == nullptr) { + plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObj); + visible = false; + } + if (plane == nullptr) { + error("kLocalToGlobal: Plane %04x:%04x not found", PRINT_REG(planeObj)); + } + + const int16 x = readSelectorValue(s->_segMan, result, SELECTOR(x)) + plane->_gameRect.left; + const int16 y = readSelectorValue(s->_segMan, result, SELECTOR(y)) + plane->_gameRect.top; + + writeSelectorValue(s->_segMan, result, SELECTOR(x), x); + writeSelectorValue(s->_segMan, result, SELECTOR(y), y); + + return make_reg(0, visible); +} +#endif + } // End of namespace Sci diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 4508a481a0..e8b9d0461d 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -40,6 +40,9 @@ #include "sci/engine/savegame.h" #include "sci/sound/audio.h" #include "sci/console.h" +#ifdef ENABLE_SCI32 +#include "sci/resource.h" +#endif namespace Sci { @@ -196,26 +199,25 @@ reg_t kValidPath(EngineState *s, int argc, reg_t *argv) { #ifdef ENABLE_SCI32 reg_t kCD(EngineState *s, int argc, reg_t *argv) { - // TODO: Stub - switch (argv[0].toUint16()) { - case 0: - if (argc == 1) { - // Check if a disc is in the drive - return TRUE_REG; - } else { - // Check if the specified disc is in the drive - // and return the current disc number. We just - // return the requested disc number. - return argv[1]; - } - case 1: - // Return the current CD number - return make_reg(0, 1); - default: - warning("CD(%d)", argv[0].toUint16()); + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} + +reg_t kCheckCD(EngineState *s, int argc, reg_t *argv) { + const int16 cdNo = argc > 0 ? argv[0].toSint16() : 0; + + if (cdNo) { + g_sci->getResMan()->findDisc(cdNo); } - return NULL_REG; + return make_reg(0, g_sci->getResMan()->getCurrentDiscNo()); +} + +reg_t kGetSavedCD(EngineState *s, int argc, reg_t *argv) { + // TODO: This is wrong, CD number needs to be available prior to + // the save game being loaded + return make_reg(0, g_sci->getResMan()->getCurrentDiscNo()); } #endif @@ -251,6 +253,28 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { return SIGNAL_REG; } + // Torin's autosave system checks for the presence of autosave.cat + // by opening it. Since we don't use .cat files, we instead check + // for autosave.000 or autosave.001. + // + // The same logic is being followed for torinsg.cat - this shows + // the "Open..." button when continuing a game. + // + // This has the added benefit of not detecting an SSCI autosave.cat + // accompanying SSCI autosave files that we wouldn't be able to load. + if (g_sci->getGameId() == GID_TORIN && (name == "autosave.cat" || name == "torinsg.cat")) { + Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); + const Common::String pattern = (name == "autosave.cat") ? g_sci->wrapFilename("autosave.###") : g_sci->getSavegamePattern(); + bool exists = !saveFileMan->listSavefiles(pattern).empty(); + if (exists) { + // Dummy handle. Torin only checks if this is SIGNAL_REG, + // and calls kFileIOClose on it. + return make_reg(0, VIRTUALFILE_HANDLE_SCI32SAVE); + } else { + return SIGNAL_REG; + } + } + if (name.empty()) { // Happens many times during KQ1 (e.g. when typing something) debugC(kDebugLevelFile, "Attempted to open a file with an empty filename"); @@ -608,6 +632,15 @@ reg_t kFileIORename(EngineState *s, int argc, reg_t *argv) { Common::String oldName = s->_segMan->getString(argv[0]); Common::String newName = s->_segMan->getString(argv[1]); + // We don't fully implement all cases that could occur here, and + // assume the file to be renamed is a wrapped filename. + // Known usage: In Phant1 and KQ7 while deleting savegames. + // The scripts rewrite the dir file as a temporary file, and then + // rename it to the actual dir file. + + oldName = g_sci->wrapFilename(oldName); + newName = g_sci->wrapFilename(newName); + // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 // returns -1 on fail. We just return -1 for all versions. if (g_sci->getSaveFileManager()->renameSavefile(oldName, newName)) @@ -688,7 +721,7 @@ reg_t kSave(EngineState *s, int argc, reg_t *argv) { #endif reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { - Common::String game_id; + Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : ""; int16 virtualId = argv[1].toSint16(); int16 savegameId = -1; Common::String game_description; @@ -703,6 +736,13 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } + // Torin has two sets of saves: autosave.### and torinsg.###, both with + // their own slots and .cat file. + // The autosave system uses autosave.000 and autosave.001. + // It also checks the presence of autosave.cat to determine if it should + // show the chapter selection menu on startup. (See kFileIOOpen.) + bool torinAutosave = g_sci->getGameId() == GID_TORIN && game_id == "Autosave"; + if (argv[0].isNull()) { // Direct call, from a patched Game::save if ((argv[1] != SIGNAL_REG) || (!argv[2].isNull())) @@ -722,9 +762,15 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { if (savegameId < 0) return NULL_REG; + } else if (torinAutosave) { + if (argv[2].isNull()) + error("kSaveGame: called with description being NULL"); + game_description = s->_segMan->getString(argv[2]); + savegameId = virtualId; + + debug(3, "kSaveGame(%s,%d,%s,%s) [Torin autosave]", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); } else { // Real call from script - game_id = s->_segMan->getString(argv[0]); if (argv[2].isNull()) error("kSaveGame: called with description being NULL"); game_description = s->_segMan->getString(argv[2]); @@ -798,6 +844,10 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { Common::SaveFileManager *saveFileMan = g_sci->getSaveFileManager(); Common::OutSaveFile *out; + if (torinAutosave) { + filename = g_sci->wrapFilename(Common::String::format("autosave.%03d", savegameId)); + } + out = saveFileMan->openForSaving(filename); if (!out) { warning("Error opening savegame \"%s\" for writing", filename.c_str()); @@ -826,6 +876,10 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); + + // See comment in kSaveGame + bool torinAutosave = g_sci->getGameId() == GID_TORIN && game_id == "Autosave"; + if (argv[0].isNull()) { // Direct call, either from launcher or from a patched Game::restore if (savegameId == -1) { @@ -841,7 +895,7 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { pausedMusic = true; } // don't adjust ID of the saved game, it's already correct - } else { + } else if (!torinAutosave) { if (g_sci->getGameId() == GID_JONES) { // Jones has one save slot only savegameId = 0; @@ -858,8 +912,9 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; // signals success Common::Array<SavegameDesc> saves; - listSavegames(saves); - if (findSavegame(saves, savegameId) == -1) { + if (!torinAutosave) + listSavegames(saves); + if (!torinAutosave && findSavegame(saves, savegameId) == -1) { s->r_acc = TRUE_REG; warning("Savegame ID %d not found", savegameId); } else { @@ -867,6 +922,10 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { Common::String filename = g_sci->getSavegameName(savegameId); Common::SeekableReadStream *in; + if (torinAutosave) { + filename = g_sci->wrapFilename(Common::String::format("autosave.%03d", savegameId)); + } + in = saveFileMan->openForLoading(filename); if (in) { // found a savegame file diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index cae5a09789..d375a27954 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -579,17 +579,8 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) { } reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) { -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2) { - g_sci->_gfxFrameout->kernelSetNowSeen(argv[0]); - return NULL_REG; - } else { -#endif - g_sci->_gfxCompare->kernelSetNowSeen(argv[0]); - return s->r_acc; -#ifdef ENABLE_SCI32 - } -#endif + g_sci->_gfxCompare->kernelSetNowSeen(argv[0]); + return s->r_acc; } reg_t kPalette(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 9cfe53255b..51437f10f8 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -37,8 +37,6 @@ #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" #include "sci/graphics/controls16.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/cursor.h" #include "sci/graphics/palette.h" #include "sci/graphics/paint16.h" #include "sci/graphics/picture.h" @@ -48,6 +46,7 @@ #include "sci/graphics/text16.h" #include "sci/graphics/view.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/cursor32.h" #include "sci/graphics/celobj32.h" #include "sci/graphics/controls32.h" #include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class @@ -56,6 +55,7 @@ #include "sci/graphics/palette32.h" #include "sci/graphics/remap32.h" #include "sci/graphics/text32.h" +#include "sci/graphics/transitions32.h" #endif namespace Sci { @@ -63,6 +63,107 @@ namespace Sci { extern void showScummVMDialog(const Common::String &message); +reg_t kBaseSetter32(EngineState *s, int argc, reg_t *argv) { + reg_t object = argv[0]; + + const GuiResourceId viewId = readSelectorValue(s->_segMan, object, SELECTOR(view)); + const int16 loopNo = readSelectorValue(s->_segMan, object, SELECTOR(loop)); + const int16 celNo = readSelectorValue(s->_segMan, object, SELECTOR(cel)); + const int16 x = readSelectorValue(s->_segMan, object, SELECTOR(x)); + const int16 y = readSelectorValue(s->_segMan, object, SELECTOR(y)); + + CelObjView celObj(viewId, loopNo, celNo); + + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + + const Ratio scaleX(scriptWidth, celObj._scaledWidth); + const Ratio scaleY(scriptHeight, celObj._scaledHeight); + + int16 brLeft; + + if (celObj._mirrorX) { + brLeft = x - ((celObj._width - celObj._displace.x) * scaleX).toInt(); + } else { + brLeft = x - (celObj._displace.x * scaleX).toInt(); + } + + const int16 brRight = brLeft + (celObj._width * scaleX).toInt() - 1; + + writeSelectorValue(s->_segMan, object, SELECTOR(brLeft), brLeft); + writeSelectorValue(s->_segMan, object, SELECTOR(brRight), brRight); + writeSelectorValue(s->_segMan, object, SELECTOR(brBottom), y + 1); + writeSelectorValue(s->_segMan, object, SELECTOR(brTop), y + 1 - readSelectorValue(s->_segMan, object, SELECTOR(yStep))); + + return s->r_acc; +} + +reg_t kSetNowSeen32(EngineState *s, int argc, reg_t *argv) { + const bool found = g_sci->_gfxFrameout->kernelSetNowSeen(argv[0]); + + // NOTE: MGDX is assumed to use the older kSetNowSeen since it was + // released before SQ6, but this has not been verified since it cannot be + // disassembled at the moment (Phar Lap Windows-only release) + if (getSciVersion() <= SCI_VERSION_2_1_EARLY || + g_sci->getGameId() == GID_SQ6 || + g_sci->getGameId() == GID_MOTHERGOOSEHIRES) { + + if (!found) { + error("kSetNowSeen: Unable to find screen item %04x:%04x", PRINT_REG(argv[0])); + } + return s->r_acc; + } + + if (!found) { + warning("kSetNowSeen: Unable to find screen item %04x:%04x", PRINT_REG(argv[0])); + } + + return make_reg(0, found); +} + +reg_t kSetCursor32(EngineState *s, int argc, reg_t *argv) { + switch (argc) { + case 1: { + if (argv[0].toSint16() == -2) { + g_sci->_gfxCursor32->clearRestrictedArea(); + } else { + if (argv[0].isNull()) { + g_sci->_gfxCursor32->hide(); + } else { + g_sci->_gfxCursor32->show(); + } + } + break; + } + case 2: { + const Common::Point position(argv[0].toSint16(), argv[1].toSint16()); + g_sci->_gfxCursor32->setPosition(position); + break; + } + case 3: { + g_sci->_gfxCursor32->setView(argv[0].toUint16(), argv[1].toSint16(), argv[2].toSint16()); + break; + } + case 4: { + const Common::Rect restrictRect(argv[0].toSint16(), + argv[1].toSint16(), + argv[2].toSint16() + 1, + argv[3].toSint16() + 1); + g_sci->_gfxCursor32->setRestrictedArea(restrictRect); + break; + } + default: + error("kSetCursor: Invalid number of arguments (%d)", argc); + } + + return s->r_acc; +} + +reg_t kShakeScreen32(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxFrameout->shakeScreen(argv[0].toSint16(), (ShakeDirection)argv[1].toSint16()); + return s->r_acc; +} + reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { const Buffer &buffer = g_sci->_gfxFrameout->getCurrentBuffer(); if (buffer.screenWidth < 640 || buffer.screenHeight < 400) @@ -123,8 +224,9 @@ reg_t kAddPicAt(EngineState *s, int argc, reg_t *argv) { int16 x = argv[2].toSint16(); int16 y = argv[3].toSint16(); bool mirrorX = argc > 4 ? argv[4].toSint16() : false; + bool deleteDuplicate = argc > 5 ? argv[5].toSint16() : true; - g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, x, y, mirrorX); + g_sci->_gfxFrameout->kernelAddPicAt(planeObj, pictureId, x, y, mirrorX, deleteDuplicate); return s->r_acc; } @@ -139,7 +241,7 @@ reg_t kFrameOut(EngineState *s, int argc, reg_t *argv) { } reg_t kSetPalStyleRange(EngineState *s, int argc, reg_t *argv) { - g_sci->_gfxFrameout->kernelSetPalStyleRange(argv[0].toUint16(), argv[1].toUint16()); + g_sci->_gfxTransitions32->kernelSetPalStyleRange(argv[0].toUint16(), argv[1].toUint16()); return s->r_acc; } @@ -195,14 +297,14 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { if (subop == 0) { TextAlign alignment = (TextAlign)readSelectorValue(segMan, object, SELECTOR(mode)); - return g_sci->_gfxText32->createFontBitmap(width, height, rect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, true); + return g_sci->_gfxText32->createFontBitmap(width, height, rect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, true, true); } else { CelInfo32 celInfo; celInfo.type = kCelTypeView; celInfo.resourceId = readSelectorValue(segMan, object, SELECTOR(view)); celInfo.loopNo = readSelectorValue(segMan, object, SELECTOR(loop)); celInfo.celNo = readSelectorValue(segMan, object, SELECTOR(cel)); - return g_sci->_gfxText32->createFontBitmap(celInfo, rect, text, foreColor, backColor, fontId, skipColor, borderColor, dimmed); + return g_sci->_gfxText32->createFontBitmap(celInfo, rect, text, foreColor, backColor, fontId, skipColor, borderColor, dimmed, true); } } @@ -264,7 +366,7 @@ reg_t kMessageBox(EngineState *s, int argc, reg_t *argv) { * effect */ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { - ShowStyleType type = (ShowStyleType)argv[0].toUint16(); + const uint16 type = argv[0].toUint16(); reg_t planeObj = argv[1]; int16 seconds = argv[2].toSint16(); // NOTE: This value seems to indicate whether the transition is an @@ -299,6 +401,10 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { divisions = argc > 9 ? argv[9].toSint16() : -1; } + if ((getSciVersion() < SCI_VERSION_2_1_MIDDLE && g_sci->getGameId() != GID_KQ7 && type == 15) || type > 15) { + error("Illegal show style %d for plane %04x:%04x", type, PRINT_REG(planeObj)); + } + // TODO: Reuse later for SCI2 and SCI3 implementation and then discard // warning("kSetShowStyle: effect %d, plane: %04x:%04x (%s), sec: %d, " // "dir: %d, prio: %d, animate: %d, ref frame: %d, black screen: %d, " @@ -310,7 +416,7 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { // NOTE: The order of planeObj and showStyle are reversed // because this is how SCI3 called the corresponding method // on the KernelMgr - g_sci->_gfxFrameout->kernelSetShowStyle(argc, planeObj, type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen); + g_sci->_gfxTransitions32->kernelSetShowStyle(argc, planeObj, (ShowStyleType)type, seconds, back, priority, animate, refFrame, pFadeArray, divisions, blackScreen); return s->r_acc; } @@ -534,13 +640,14 @@ reg_t kBitmapCreate(EngineState *s, int argc, reg_t *argv) { int16 scaledHeight = argc > 5 ? argv[5].toSint16() : g_sci->_gfxText32->_scaledHeight; bool useRemap = argc > 6 ? argv[6].toSint16() : false; - BitmapResource bitmap(s->_segMan, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap); + reg_t bitmapId; + SciBitmap &bitmap = *s->_segMan->allocateBitmap(&bitmapId, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap, true); memset(bitmap.getPixels(), backColor, width * height); - return bitmap.getObject(); + return bitmapId; } reg_t kBitmapDestroy(EngineState *s, int argc, reg_t *argv) { - s->_segMan->freeHunkEntry(argv[0]); + s->_segMan->freeBitmap(argv[0]); return s->r_acc; } @@ -550,7 +657,7 @@ reg_t kBitmapDrawLine(EngineState *s, int argc, reg_t *argv) { } reg_t kBitmapDrawView(EngineState *s, int argc, reg_t *argv) { - BitmapResource bitmap(argv[0]); + SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]); CelObjView view(argv[1].toUint16(), argv[2].toSint16(), argv[3].toSint16()); const int16 x = argc > 4 ? argv[4].toSint16() : 0; @@ -580,7 +687,7 @@ reg_t kBitmapDrawView(EngineState *s, int argc, reg_t *argv) { reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) { // called e.g. from TextButton::createBitmap() in Torin's Passage, script 64894 - BitmapResource bitmap(argv[0]); + SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]); Common::String text = s->_segMan->getString(argv[1]); Common::Rect textRect( argv[2].toSint16(), @@ -604,10 +711,10 @@ reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) { // Then clips. But this seems stupid. textRect.clip(Common::Rect(bitmap.getWidth(), bitmap.getHeight())); - reg_t textBitmapObject = g_sci->_gfxText32->createFontBitmap(textRect.width(), textRect.height(), Common::Rect(textRect.width(), textRect.height()), text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, false); + reg_t textBitmapObject = g_sci->_gfxText32->createFontBitmap(textRect.width(), textRect.height(), Common::Rect(textRect.width(), textRect.height()), text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, false, false); CelObjMem textCel(textBitmapObject); textCel.draw(bitmap.getBuffer(), textRect, Common::Point(textRect.left, textRect.top), false); - s->_segMan->freeHunkEntry(textBitmapObject); + s->_segMan->freeBitmap(textBitmapObject); return s->r_acc; } @@ -615,7 +722,7 @@ reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) { reg_t kBitmapDrawColor(EngineState *s, int argc, reg_t *argv) { // called e.g. from TextView::init() and TextView::draw() in Torin's Passage, script 64890 - BitmapResource bitmap(argv[0]); + SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]); Common::Rect fillRect( argv[1].toSint16(), argv[2].toSint16(), @@ -640,7 +747,7 @@ reg_t kBitmapInvert(EngineState *s, int argc, reg_t *argv) { } reg_t kBitmapSetDisplace(EngineState *s, int argc, reg_t *argv) { - BitmapResource bitmap(argv[0]); + SciBitmap &bitmap = *s->_segMan->lookupBitmap(argv[0]); bitmap.setDisplace(Common::Point(argv[1].toSint16(), argv[2].toSint16())); return s->r_acc; } @@ -760,28 +867,19 @@ reg_t kDeleteLine(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// Used by LSL6hires intro (room 110) reg_t kSetScroll(EngineState *s, int argc, reg_t *argv) { - // Called in the intro of LSL6 hires (room 110) - // The end effect of this is the same as the old screen scroll transition - - // 7 parameters - reg_t planeObject = argv[0]; - //int16 x = argv[1].toSint16(); - //int16 y = argv[2].toSint16(); - uint16 pictureId = argv[3].toUint16(); - // param 4: int (0 in LSL6, probably scroll direction? The picture in LSL6 scrolls down) - // param 5: int (first call is 1, then the subsequent one is 0 in LSL6) - // param 6: optional int (0 in LSL6) - - // Set the new picture directly for now - //writeSelectorValue(s->_segMan, planeObject, SELECTOR(left), x); - //writeSelectorValue(s->_segMan, planeObject, SELECTOR(top), y); - writeSelectorValue(s->_segMan, planeObject, SELECTOR(picture), pictureId); - // and update our draw list - g_sci->_gfxFrameout->kernelUpdatePlane(planeObject); + const reg_t plane = argv[0]; + const int16 deltaX = argv[1].toSint16(); + const int16 deltaY = argv[2].toSint16(); + const GuiResourceId pictureId = argv[3].toUint16(); + const bool animate = argv[4].toUint16(); + // NOTE: speed was accepted as an argument, but then never actually used + // const int16 speed = argc > 5 ? (bool)argv[5].toSint16() : -1; + const bool mirrorX = argc > 6 ? (bool)argv[6].toUint16() : false; - // TODO - return kStub(s, argc, argv); + g_sci->_gfxTransitions32->kernelSetScroll(plane, deltaX, deltaY, pictureId, animate, mirrorX); + return s->r_acc; } // Used by SQ6, script 900, the datacorder reprogramming puzzle (from room 270) @@ -803,6 +901,19 @@ reg_t kPaletteFindColor32(EngineState *s, int argc, reg_t *argv) { return make_reg(0, g_sci->_gfxPalette32->matchColor(r, g, b)); } +/* + * Used in SCI3. SCI3 contains 6 gamma look-up tables, with the first + * table (gamma = 0) being the default one. + */ +reg_t kPaletteSetGamma(EngineState *s, int argc, reg_t *argv) { + const uint8 gamma = argv[0].toUint16(); + assert(gamma <= 6); + + warning("TODO: kPaletteSetGamma(%d)", gamma); + + return s->r_acc; +} + reg_t kPaletteSetFade(EngineState *s, int argc, reg_t *argv) { uint16 fromColor = argv[0].toUint16(); uint16 toColor = argv[1].toUint16(); diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index c0da2daaeb..e780d3cdc3 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -374,13 +374,21 @@ reg_t kFindKey(EngineState *s, int argc, reg_t *argv) { reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { reg_t node_pos = kFindKey(s, 2, argv); - Node *n; List *list = s->_segMan->lookupList(argv[0]); if (node_pos.isNull()) return NULL_REG; // Signal failure - n = s->_segMan->lookupNode(node_pos); + Node *n = s->_segMan->lookupNode(node_pos); + +#ifdef ENABLE_SCI32 + for (int i = 1; i <= list->numRecursions; ++i) { + if (list->nextNodes[i] == node_pos) { + list->nextNodes[i] = n->succ; + } + } +#endif + if (list->first == node_pos) list->first = n->succ; if (list->last == node_pos) @@ -486,7 +494,7 @@ reg_t kListAt(EngineState *s, int argc, reg_t *argv) { List *list = s->_segMan->lookupList(argv[0]); reg_t curAddress = list->first; if (list->first.isNull()) { - error("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0])); + // Happens in Torin when examining Di's locket in chapter 3 return NULL_REG; } Node *curNode = s->_segMan->lookupNode(curAddress); @@ -544,9 +552,18 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { ObjVarRef address; + ++list->numRecursions; + + if (list->numRecursions > ARRAYSIZE(list->nextNodes)) { + error("Too much recursion in kListEachElementDo"); + } + while (curNode) { - // We get the next node here as the current node might be gone after the invoke - reg_t nextNode = curNode->succ; + // We get the next node here as the current node might be deleted by the + // invoke. In the case that the next node is also deleted, kDeleteKey + // needs to be able to adjust the location of the next node, which is + // why it is stored on the list instead of on the stack + list->nextNodes[list->numRecursions] = curNode->succ; curObject = curNode->value; // First, check if the target selector is a variable @@ -559,11 +576,18 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { } } else { invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); + // Check if the call above leads to a game restore, in which case + // the segment manager will be reset, and the original list will + // be invalidated + if (s->abortScriptProcessing == kAbortLoadGame) + return s->r_acc; } - curNode = s->_segMan->lookupNode(nextNode); + curNode = s->_segMan->lookupNode(list->nextNodes[list->numRecursions]); } + --list->numRecursions; + return s->r_acc; } diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 1924848717..f2a3c6b0f7 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -20,6 +20,7 @@ * */ +#include "common/config-manager.h" #include "common/system.h" #include "sci/sci.h" @@ -29,6 +30,9 @@ #include "sci/engine/kernel.h" #include "sci/engine/gc.h" #include "sci/graphics/cursor.h" +#ifdef ENABLE_SCI32 +#include "sci/graphics/cursor32.h" +#endif #include "sci/graphics/maciconbar.h" #include "sci/console.h" @@ -510,9 +514,12 @@ reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) { // In SCI1, its usage is still unknown // In SCI1.1, it's NOP // In SCI32, it's used for remapping cursor ID's +#ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2_1_EARLY) // Set Mac cursor remap - g_sci->_gfxCursor->setMacCursorRemapList(argc - 1, argv + 1); - else if (getSciVersion() != SCI_VERSION_1_1) + g_sci->_gfxCursor32->setMacCursorRemapList(argc - 1, argv + 1); + else +#endif + if (getSciVersion() != SCI_VERSION_1_1) warning("Unknown SCI1 kMacPlatform(0) call"); break; case 4: // Handle icon bar code @@ -535,31 +542,28 @@ reg_t kMacPlatform(EngineState *s, int argc, reg_t *argv) { } enum kSciPlatforms { + kSciPlatformMacintosh = 0, kSciPlatformDOS = 1, kSciPlatformWindows = 2 }; -enum kPlatformOps { - kPlatformUnk0 = 0, - kPlatformCDSpeed = 1, - kPlatformUnk2 = 2, - kPlatformCDCheck = 3, - kPlatformGetPlatform = 4, - kPlatformUnk5 = 5, - kPlatformIsHiRes = 6, - kPlatformIsItWindows = 7 -}; - reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { + enum Operation { + kPlatformUnknown = 0, + kPlatformGetPlatform = 4, + kPlatformUnknown5 = 5, + kPlatformIsHiRes = 6, + kPlatformWin311OrHigher = 7 + }; + bool isWindows = g_sci->getPlatform() == Common::kPlatformWindows; - if (argc == 0 && getSciVersion() < SCI_VERSION_2) { + if (argc == 0) { // This is called in KQ5CD with no parameters, where it seems to do some // graphics driver check. This kernel function didn't have subfunctions // then. If 0 is returned, the game functions normally, otherwise all // the animations show up like a slideshow (e.g. in the intro). So we - // return 0. However, the behavior changed for kPlatform with no - // parameters in SCI32. + // return 0. return NULL_REG; } @@ -571,30 +575,23 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { uint16 operation = (argc == 0) ? 0 : argv[0].toUint16(); switch (operation) { - case kPlatformCDSpeed: - // TODO: Returns CD Speed? - warning("STUB: kPlatform(CDSpeed)"); - break; - case kPlatformUnk2: - // Always returns 2 - return make_reg(0, 2); - case kPlatformCDCheck: - // TODO: Some sort of CD check? - warning("STUB: kPlatform(CDCheck)"); - break; - case kPlatformUnk0: + case kPlatformUnknown: // For Mac versions, kPlatform(0) with other args has more functionality if (g_sci->getPlatform() == Common::kPlatformMacintosh && argc > 1) return kMacPlatform(s, argc - 1, argv + 1); // Otherwise, fall through case kPlatformGetPlatform: - return make_reg(0, (isWindows) ? kSciPlatformWindows : kSciPlatformDOS); - case kPlatformUnk5: + if (isWindows) + return make_reg(0, kSciPlatformWindows); + else if (g_sci->getPlatform() == Common::kPlatformMacintosh) + return make_reg(0, kSciPlatformMacintosh); + else + return make_reg(0, kSciPlatformDOS); + case kPlatformUnknown5: // This case needs to return the opposite of case 6 to get hires graphics return make_reg(0, !isWindows); case kPlatformIsHiRes: - return make_reg(0, isWindows); - case kPlatformIsItWindows: + case kPlatformWin311OrHigher: return make_reg(0, isWindows); default: error("Unsupported kPlatform operation %d", operation); @@ -603,6 +600,43 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +#ifdef ENABLE_SCI32 +reg_t kPlatform32(EngineState *s, int argc, reg_t *argv) { + enum Operation { + kGetPlatform = 0, + kGetCDSpeed = 1, + kGetColorDepth = 2, + kGetCDDrive = 3 + }; + + const Operation operation = argc > 0 ? (Operation)argv[0].toSint16() : kGetPlatform; + + switch (operation) { + case kGetPlatform: + switch (g_sci->getPlatform()) { + case Common::kPlatformDOS: + return make_reg(0, kSciPlatformDOS); + case Common::kPlatformWindows: + return make_reg(0, kSciPlatformWindows); + case Common::kPlatformMacintosh: + // For Mac versions, kPlatform(0) with other args has more functionality + if (argc > 1) + return kMacPlatform(s, argc - 1, argv + 1); + else + return make_reg(0, kSciPlatformMacintosh); + default: + error("Unknown platform %d", g_sci->getPlatform()); + } + case kGetColorDepth: + return make_reg(0, /* 256 color */ 2); + case kGetCDSpeed: + case kGetCDDrive: + default: + return make_reg(0, 0); + } +} +#endif + reg_t kEmpty(EngineState *s, int argc, reg_t *argv) { // Placeholder for empty kernel functions which are still called from the // engine scripts (like the empty kSetSynonyms function in SCI1.1). This diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 1096e78cca..b539c84f5d 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -61,40 +61,21 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { uint16 screenWidth = g_sci->_gfxScreen->getDisplayWidth(); uint16 screenHeight = g_sci->_gfxScreen->getDisplayHeight(); - videoState.fileName.toLowercase(); - bool isVMD = videoState.fileName.hasSuffix(".vmd"); - - if (screenWidth == 640 && width <= 320 && height <= 240 && ((videoState.flags & kDoubled) || !isVMD)) { + if (screenWidth == 640 && width <= 320 && height <= 240) { width *= 2; height *= 2; pitch *= 2; scaleBuffer = new byte[width * height * bytesPerPixel]; } - uint16 x, y; - - // Sanity check... - if (videoState.x > 0 && videoState.y > 0 && isVMD) { - x = videoState.x; - y = videoState.y; - - if (x + width > screenWidth || y + height > screenHeight) { - // Happens in the Lighthouse demo - warning("VMD video won't fit on screen, centering it instead"); - x = (screenWidth - width) / 2; - y = (screenHeight - height) / 2; - } - } else { - x = (screenWidth - width) / 2; - y = (screenHeight - height) / 2; - } + uint16 x = (screenWidth - width) / 2; + uint16 y = (screenHeight - height) / 2; bool skipVideo = false; - EngineState *s = g_sci->getEngineState(); if (videoDecoder->hasDirtyPalette()) { - const byte *palette = videoDecoder->getPalette() + s->_vmdPalStart * 3; - g_system->getPaletteManager()->setPalette(palette, s->_vmdPalStart, s->_vmdPalEnd - s->_vmdPalStart); + const byte *palette = videoDecoder->getPalette(); + g_system->getPaletteManager()->setPalette(palette, 0, 255); } while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { @@ -103,7 +84,7 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { if (frame) { if (scaleBuffer) { - // TODO: Probably should do aspect ratio correction in e.g. GK1 Windows + // TODO: Probably should do aspect ratio correction in KQ6 g_sci->_gfxScreen->scale2x((const byte *)frame->getPixels(), scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel); g_system->copyRectToScreen(scaleBuffer, pitch, x, y, width, height); } else { @@ -111,8 +92,8 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { } if (videoDecoder->hasDirtyPalette()) { - const byte *palette = videoDecoder->getPalette() + s->_vmdPalStart * 3; - g_system->getPaletteManager()->setPalette(palette, s->_vmdPalStart, s->_vmdPalEnd - s->_vmdPalStart); + const byte *palette = videoDecoder->getPalette(); + g_system->getPaletteManager()->setPalette(palette, 0, 255); } g_system->updateScreen(); @@ -181,16 +162,6 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { // TODO: This appears to be some sort of subop. case 0 contains the string // for the video, so we'll just play it from there for now. -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2_1_EARLY) { - // SCI2.1 always has argv[0] as 1, the rest of the arguments seem to - // follow SCI1.1/2. - if (argv[0].toUint16() != 1) - error("SCI2.1 kShowMovie argv[0] not 1"); - argv++; - argc--; - } -#endif switch (argv[0].toUint16()) { case 0: { Common::String filename = s->_segMan->getString(argv[1]); @@ -230,7 +201,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { // We also won't be copying the screen to the SCI screen... if (g_system->getScreenFormat().bytesPerPixel != 1) initGraphics(screenWidth, screenHeight, screenWidth > 320); - else { + else if (getSciVersion() < SCI_VERSION_2) { g_sci->_gfxScreen->kernelSyncWithFramebuffer(); g_sci->_gfxPalette16->kernelSyncScreenPalette(); } @@ -243,52 +214,176 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } #ifdef ENABLE_SCI32 +reg_t kShowMovie32(EngineState *s, int argc, reg_t *argv) { + Common::String fileName = s->_segMan->getString(argv[0]); + const int16 numTicks = argv[1].toSint16(); + const int16 x = argc > 3 ? argv[2].toSint16() : 0; + const int16 y = argc > 3 ? argv[3].toSint16() : 0; + + g_sci->_video32->getSEQPlayer().play(fileName, numTicks, x, y); + + return s->r_acc; +} reg_t kRobot(EngineState *s, int argc, reg_t *argv) { - int16 subop = argv[0].toUint16(); - - switch (subop) { - case 0: { // init - int id = argv[1].toUint16(); - reg_t obj = argv[2]; - int16 flag = argv[3].toSint16(); - int16 x = argv[4].toUint16(); - int16 y = argv[5].toUint16(); - warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y); - g_sci->_robotDecoder->load(id); - g_sci->_robotDecoder->start(); - g_sci->_robotDecoder->setPos(x, y); - } - break; - case 1: // LSL6 hires (startup) - // TODO - return NULL_REG; // an integer is expected - case 4: { // start - we don't really have a use for this one - //int id = argv[1].toUint16(); - //warning("kRobot(start), id %d", id); - } - break; - case 7: // unknown, called e.g. by Phantasmagoria - warning("kRobot(%d)", subop); - break; - case 8: // sync - //if (true) { // debug: automatically skip all robot videos - if (g_sci->_robotDecoder->endOfVideo()) { - g_sci->_robotDecoder->close(); - // Signal the engine scripts that the video is done - writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG); - } else { - writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG); - } - break; - default: - warning("kRobot(%d)", subop); - break; - } + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} +reg_t kRobotOpen(EngineState *s, int argc, reg_t *argv) { + const GuiResourceId robotId = argv[0].toUint16(); + const reg_t plane = argv[1]; + const int16 priority = argv[2].toSint16(); + const int16 x = argv[3].toSint16(); + const int16 y = argv[4].toSint16(); + const int16 scale = argc > 5 ? argv[5].toSint16() : 128; + g_sci->_video32->getRobotPlayer().open(robotId, plane, priority, x, y, scale); + return make_reg(0, 0); +} +reg_t kRobotShowFrame(EngineState *s, int argc, reg_t *argv) { + const uint16 frameNo = argv[0].toUint16(); + const uint16 newX = argc > 1 ? argv[1].toUint16() : (uint16)RobotDecoder::kUnspecified; + const uint16 newY = argc > 1 ? argv[2].toUint16() : (uint16)RobotDecoder::kUnspecified; + g_sci->_video32->getRobotPlayer().showFrame(frameNo, newX, newY, RobotDecoder::kUnspecified); return s->r_acc; } +reg_t kRobotGetFrameSize(EngineState *s, int argc, reg_t *argv) { + Common::Rect frameRect; + const uint16 numFramesTotal = g_sci->_video32->getRobotPlayer().getFrameSize(frameRect); + + reg_t *outRect = s->_segMan->derefRegPtr(argv[0], 4); + outRect[0] = make_reg(0, frameRect.left); + outRect[1] = make_reg(0, frameRect.top); + outRect[2] = make_reg(0, frameRect.right - 1); + outRect[3] = make_reg(0, frameRect.bottom - 1); + + return make_reg(0, numFramesTotal); +} + +reg_t kRobotPlay(EngineState *s, int argc, reg_t *argv) { + g_sci->_video32->getRobotPlayer().resume(); + return s->r_acc; +} + +reg_t kRobotGetIsFinished(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_video32->getRobotPlayer().getStatus() == RobotDecoder::kRobotStatusEnd); +} + +reg_t kRobotGetIsPlaying(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_video32->getRobotPlayer().getStatus() == RobotDecoder::kRobotStatusPlaying); +} + +reg_t kRobotClose(EngineState *s, int argc, reg_t *argv) { + g_sci->_video32->getRobotPlayer().close(); + return s->r_acc; +} + +reg_t kRobotGetCue(EngineState *s, int argc, reg_t *argv) { + writeSelectorValue(s->_segMan, argv[0], SELECTOR(signal), g_sci->_video32->getRobotPlayer().getCue()); + return s->r_acc; +} + +reg_t kRobotPause(EngineState *s, int argc, reg_t *argv) { + g_sci->_video32->getRobotPlayer().pause(); + return s->r_acc; +} + +reg_t kRobotGetFrameNo(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_video32->getRobotPlayer().getFrameNo()); +} + +reg_t kRobotSetPriority(EngineState *s, int argc, reg_t *argv) { + g_sci->_video32->getRobotPlayer().setPriority(argv[0].toSint16()); + return s->r_acc; +} + +reg_t kShowMovieWin(EngineState *s, int argc, reg_t *argv) { + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} + +reg_t kShowMovieWinOpen(EngineState *s, int argc, reg_t *argv) { + // SCI2.1 adds a movie ID to the call, but the movie ID is broken, + // so just ignore it + if (getSciVersion() > SCI_VERSION_2) { + ++argv; + --argc; + } + + const Common::String fileName = s->_segMan->getString(argv[0]); + return make_reg(0, g_sci->_video32->getAVIPlayer().open(fileName)); +} + +reg_t kShowMovieWinInit(EngineState *s, int argc, reg_t *argv) { + // SCI2.1 adds a movie ID to the call, but the movie ID is broken, + // so just ignore it + if (getSciVersion() > SCI_VERSION_2) { + ++argv; + --argc; + } + + const int16 x = argv[0].toSint16(); + const int16 y = argv[1].toSint16(); + const int16 width = argc > 3 ? argv[2].toSint16() : 0; + const int16 height = argc > 3 ? argv[3].toSint16() : 0; + return make_reg(0, g_sci->_video32->getAVIPlayer().init1x(x, y, width, height)); +} + +reg_t kShowMovieWinPlay(EngineState *s, int argc, reg_t *argv) { + if (getSciVersion() == SCI_VERSION_2) { + AVIPlayer::EventFlags flags = (AVIPlayer::EventFlags)argv[0].toUint16(); + return make_reg(0, g_sci->_video32->getAVIPlayer().playUntilEvent(flags)); + } else { + // argv[0] is a broken movie ID + const int16 from = argc > 2 ? argv[1].toSint16() : 0; + const int16 to = argc > 2 ? argv[2].toSint16() : 0; + const int16 showStyle = argc > 3 ? argv[3].toSint16() : 0; + const bool cue = argc > 4 ? (bool)argv[4].toSint16() : false; + return make_reg(0, g_sci->_video32->getAVIPlayer().play(from, to, showStyle, cue)); + } +} + +reg_t kShowMovieWinClose(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_video32->getAVIPlayer().close()); +} + +reg_t kShowMovieWinGetDuration(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_video32->getAVIPlayer().getDuration()); +} + +reg_t kShowMovieWinCue(EngineState *s, int argc, reg_t *argv) { + // SCI2.1 adds a movie ID to the call, but the movie ID is broken, + // so just ignore it + if (getSciVersion() > SCI_VERSION_2) { + ++argv; + --argc; + } + + const uint16 frameNo = argv[0].toUint16(); + return make_reg(0, g_sci->_video32->getAVIPlayer().cue(frameNo)); +} + +reg_t kShowMovieWinPlayUntilEvent(EngineState *s, int argc, reg_t *argv) { + const int defaultFlags = + AVIPlayer::kEventFlagEnd | + AVIPlayer::kEventFlagEscapeKey; + + // argv[0] is the movie number, which is not used by this method + const AVIPlayer::EventFlags flags = (AVIPlayer::EventFlags)(argc > 1 ? argv[1].toUint16() : defaultFlags); + + return make_reg(0, g_sci->_video32->getAVIPlayer().playUntilEvent(flags)); +} + +reg_t kShowMovieWinInitDouble(EngineState *s, int argc, reg_t *argv) { + // argv[0] is a broken movie ID + const int16 x = argv[1].toSint16(); + const int16 y = argv[2].toSint16(); + return make_reg(0, g_sci->_video32->getAVIPlayer().init2x(x, y)); +} + reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { if (!s) return make_reg(0, getSciVersion()); @@ -330,6 +425,10 @@ reg_t kPlayVMDClose(EngineState *s, int argc, reg_t *argv) { return make_reg(0, g_sci->_video32->getVMDPlayer().close()); } +reg_t kPlayVMDGetStatus(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_video32->getVMDPlayer().getStatus()); +} + reg_t kPlayVMDPlayUntilEvent(EngineState *s, int argc, reg_t *argv) { const VMDPlayer::EventFlags flags = (VMDPlayer::EventFlags)argv[0].toUint16(); const int16 lastFrameNo = argc > 1 ? argv[1].toSint16() : -1; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 31fb848a2c..eeddda8390 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -48,6 +48,7 @@ #include "sci/sound/music.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/cursor32.h" #include "sci/graphics/frameout.h" #include "sci/graphics/palette32.h" #include "sci/graphics/remap32.h" @@ -158,6 +159,7 @@ void syncWithSerializer(Common::Serializer &s, SciString &obj) { obj.setValue(i, value); } } + #endif #pragma mark - @@ -165,7 +167,7 @@ void syncWithSerializer(Common::Serializer &s, SciString &obj) { // By default, sync using syncWithSerializer, which in turn can easily be overloaded. template<typename T> struct DefaultSyncer : Common::BinaryFunction<Common::Serializer, T, void> { - void operator()(Common::Serializer &s, T &obj) const { + void operator()(Common::Serializer &s, T &obj, int) const { syncWithSerializer(s, obj); } }; @@ -173,10 +175,31 @@ struct DefaultSyncer : Common::BinaryFunction<Common::Serializer, T, void> { // Syncer for entries in a segment obj table template<typename T> struct SegmentObjTableEntrySyncer : Common::BinaryFunction<Common::Serializer, typename T::Entry &, void> { - void operator()(Common::Serializer &s, typename T::Entry &entry) const { + void operator()(Common::Serializer &s, typename T::Entry &entry, int index) const { s.syncAsSint32LE(entry.next_free); - syncWithSerializer(s, entry.data); + bool hasData; + if (s.getVersion() >= 37) { + if (s.isSaving()) { + hasData = entry.data != nullptr; + } + s.syncAsByte(hasData); + } else { + hasData = (entry.next_free == index); + } + + if (hasData) { + if (s.isLoading()) { + entry.data = new typename T::value_type; + } + syncWithSerializer(s, *entry.data); + } else if (s.isLoading()) { + if (s.getVersion() < 37) { + typename T::value_type dummy; + syncWithSerializer(s, dummy); + } + entry.data = nullptr; + } } }; @@ -204,9 +227,8 @@ struct ArraySyncer : Common::BinaryFunction<Common::Serializer, T, void> { if (s.isLoading()) arr.resize(len); - typename Common::Array<T>::iterator i; - for (i = arr.begin(); i != arr.end(); ++i) { - sync(s, *i); + for (uint i = 0; i < len; ++i) { + sync(s, arr[i], i); } } }; @@ -273,6 +295,8 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { } else if (type == SEG_TYPE_STRING) { // Set the correct segment for SCI32 strings _stringSegId = i; + } else if (s.getVersion() >= 36 && type == SEG_TYPE_BITMAP) { + _bitmapSegId = i; #endif } @@ -402,6 +426,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { g_sci->_gfxPalette32->saveLoadWithSerializer(s); + g_sci->_gfxRemap32->saveLoadWithSerializer(s); } else #endif g_sci->_gfxPalette16->saveLoadWithSerializer(s); @@ -687,6 +712,31 @@ void StringTable::saveLoadWithSerializer(Common::Serializer &ser) { sync_Table<StringTable>(ser, *this); } + +void BitmapTable::saveLoadWithSerializer(Common::Serializer &ser) { + if (ser.getVersion() < 36) { + return; + } + + sync_Table(ser, *this); +} + +void SciBitmap::saveLoadWithSerializer(Common::Serializer &s) { + if (s.getVersion() < 36) { + return; + } + + s.syncAsByte(_gc); + s.syncAsUint32LE(_dataSize); + if (s.isLoading()) { + _data = (byte *)malloc(_dataSize); + } + s.syncBytes(_data, _dataSize); + + if (s.isLoading()) { + _buffer = Buffer(getWidth(), getHeight(), getPixels()); + } +} #endif void GfxPalette::palVarySaveLoadPalette(Common::Serializer &s, Palette *palette) { @@ -840,6 +890,29 @@ void GfxRemap32::saveLoadWithSerializer(Common::Serializer &s) { _needsUpdate = true; } } + +void GfxCursor32::saveLoadWithSerializer(Common::Serializer &s) { + if (s.getVersion() < 37) { + return; + } + + s.syncAsSint32LE(_hideCount); + s.syncAsSint16LE(_restrictedArea.left); + s.syncAsSint16LE(_restrictedArea.top); + s.syncAsSint16LE(_restrictedArea.right); + s.syncAsSint16LE(_restrictedArea.bottom); + s.syncAsUint16LE(_cursorInfo.resourceId); + s.syncAsUint16LE(_cursorInfo.loopNo); + s.syncAsUint16LE(_cursorInfo.celNo); + + if (s.isLoading()) { + hide(); + setView(_cursorInfo.resourceId, _cursorInfo.loopNo, _cursorInfo.celNo); + if (!_hideCount) { + show(); + } + } +} #endif void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) { diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index 43909accf2..51dbbedd87 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -37,6 +37,8 @@ struct EngineState; * * Version - new/changed feature * ============================= + * 37 - Segment entry data changed to pointers, SCI32 cursor + * 36 - SCI32 bitmap segment * 35 - SCI32 remap * 34 - SCI32 palettes, and store play time in ticks * 33 - new overridePriority flag in MusicEntry @@ -60,7 +62,7 @@ struct EngineState; */ enum { - CURRENT_SAVEGAME_VERSION = 35, + CURRENT_SAVEGAME_VERSION = 37, MINIMUM_SAVEGAME_VERSION = 14 }; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 95e3cd15f9..5cf8d6162d 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -43,6 +43,7 @@ SegManager::SegManager(ResourceManager *resMan, ScriptPatcher *scriptPatcher) #ifdef ENABLE_SCI32 _arraysSegId = 0; _stringSegId = 0; + _bitmapSegId = 0; #endif createClassTable(); @@ -72,6 +73,7 @@ void SegManager::resetSegMan() { #ifdef ENABLE_SCI32 _arraysSegId = 0; _stringSegId = 0; + _bitmapSegId = 0; #endif // Reinitialize class table @@ -941,6 +943,55 @@ void SegManager::freeString(reg_t addr) { stringTable.freeEntry(addr.getOffset()); } +#pragma mark - +#pragma mark Bitmaps + +SciBitmap *SegManager::allocateBitmap(reg_t *addr, const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 paletteSize, const bool remap, const bool gc) { + BitmapTable *table; + int offset; + + if (!_bitmapSegId) { + table = (BitmapTable *)allocSegment(new BitmapTable(), &(_bitmapSegId)); + } else { + table = (BitmapTable *)_heap[_bitmapSegId]; + } + + offset = table->allocEntry(); + + *addr = make_reg(_bitmapSegId, offset); + SciBitmap &bitmap = table->at(offset); + + bitmap.create(width, height, skipColor, displaceX, displaceY, scaledWidth, scaledHeight, paletteSize, remap, gc); + + return &bitmap; +} + +SciBitmap *SegManager::lookupBitmap(const reg_t addr) { + if (_heap[addr.getSegment()]->getType() != SEG_TYPE_BITMAP) + error("Attempt to use non-bitmap %04x:%04x as bitmap", PRINT_REG(addr)); + + BitmapTable &bitmapTable = *(BitmapTable *)_heap[addr.getSegment()]; + + if (!bitmapTable.isValidEntry(addr.getOffset())) + error("Attempt to use invalid entry %04x:%04x as bitmap", PRINT_REG(addr)); + + return &(bitmapTable.at(addr.getOffset())); +} + +void SegManager::freeBitmap(const reg_t addr) { + if (_heap[addr.getSegment()]->getType() != SEG_TYPE_BITMAP) + error("Attempt to free non-bitmap %04x:%04x as bitmap", PRINT_REG(addr)); + + BitmapTable &bitmapTable = *(BitmapTable *)_heap[addr.getSegment()]; + + if (!bitmapTable.isValidEntry(addr.getOffset())) + error("Attempt to free invalid entry %04x:%04x as bitmap", PRINT_REG(addr)); + + bitmapTable.freeEntry(addr.getOffset()); +} + +#pragma mark - + #endif void SegManager::createClassTable() { diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 9da7e58770..8ed1c3a143 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -29,6 +29,9 @@ #include "sci/engine/vm.h" #include "sci/engine/vm_types.h" #include "sci/engine/segment.h" +#ifdef ENABLE_SCI32 +#include "sci/graphics/celobj32.h" // kLowResX, kLowResY +#endif namespace Sci { @@ -433,10 +436,15 @@ public: SciArray<reg_t> *allocateArray(reg_t *addr); SciArray<reg_t> *lookupArray(reg_t addr); void freeArray(reg_t addr); + SciString *allocateString(reg_t *addr); SciString *lookupString(reg_t addr); void freeString(reg_t addr); SegmentId getStringSegmentId() { return _stringSegId; } + + SciBitmap *allocateBitmap(reg_t *addr, const int16 width, const int16 height, const uint8 skipColor = kDefaultSkipColor, const int16 displaceX = 0, const int16 displaceY = 0, const int16 scaledWidth = kLowResX, const int16 scaledHeight = kLowResY, const uint32 paletteSize = 0, const bool remap = false, const bool gc = true); + SciBitmap *lookupBitmap(reg_t addr); + void freeBitmap(reg_t addr); #endif const Common::Array<SegmentObj *> &getSegments() const { return _heap; } @@ -462,6 +470,7 @@ private: #ifdef ENABLE_SCI32 SegmentId _arraysSegId; SegmentId _stringSegId; + SegmentId _bitmapSegId; #endif public: diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 2cff799f4b..7943946ee4 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -70,6 +70,9 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) { case SEG_TYPE_STRING: mem = new StringTable(); break; + case SEG_TYPE_BITMAP: + mem = new BitmapTable(); + break; #endif default: error("Unknown SegmentObj type %d", type); diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 50c77d0538..add5f4c57c 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -71,6 +71,7 @@ enum SegmentType { #ifdef ENABLE_SCI32 SEG_TYPE_ARRAY = 11, SEG_TYPE_STRING = 12, + SEG_TYPE_BITMAP = 13, #endif SEG_TYPE_MAX // For sanity checking @@ -199,6 +200,21 @@ struct Node { struct List { reg_t first; reg_t last; + +#ifdef ENABLE_SCI32 + /** + * The next node for each level of recursion during iteration over this list + * by kListEachElementDo. + */ + reg_t nextNodes[10]; + + /** + * The current level of recursion of kListEachElementDo for this list. + */ + int numRecursions; + + List() : numRecursions(0) {} +#endif }; struct Hunk { @@ -211,7 +227,7 @@ template<typename T> struct SegmentObjTable : public SegmentObj { typedef T value_type; struct Entry { - T data; + T *data; int next_free; /* Only used for free entries */ }; enum { HEAPENTRY_INVALID = -1 }; @@ -227,6 +243,14 @@ public: initTable(); } + ~SegmentObjTable() { + for (uint i = 0; i < _table.size(); i++) { + if (isValidEntry(i)) { + freeEntry(i); + } + } + } + void initTable() { entries_used = 0; first_free = HEAPENTRY_INVALID; @@ -240,10 +264,13 @@ public: first_free = _table[oldff].next_free; _table[oldff].next_free = oldff; + assert(_table[oldff].data == nullptr); + _table[oldff].data = new T; return oldff; } else { uint newIdx = _table.size(); _table.push_back(Entry()); + _table.back().data = new T; _table[newIdx].next_free = newIdx; // Tag as 'valid' return newIdx; } @@ -262,6 +289,8 @@ public: ::error("Table::freeEntry: Attempt to release invalid table index %d", idx); _table[idx].next_free = first_free; + delete _table[idx].data; + _table[idx].data = nullptr; first_free = idx; entries_used--; } @@ -276,8 +305,8 @@ public: uint size() const { return _table.size(); } - T &at(uint index) { return _table[index].data; } - const T &at(uint index) const { return _table[index].data; } + T &at(uint index) { return *_table[index].data; } + const T &at(uint index) const { return *_table[index].data; } T &operator[](uint index) { return at(index); } const T &operator[](uint index) const { return at(index); } @@ -337,8 +366,8 @@ struct HunkTable : public SegmentObjTable<Hunk> { } virtual void freeEntry(int idx) { - SegmentObjTable<Hunk>::freeEntry(idx); freeEntryContents(idx); + SegmentObjTable<Hunk>::freeEntry(idx); } virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) { @@ -519,6 +548,277 @@ struct StringTable : public SegmentObjTable<SciString> { SegmentRef dereference(reg_t pointer); }; +#pragma mark - +#pragma mark Bitmaps + +enum { + kDefaultSkipColor = 250 +}; + +#define BITMAP_PROPERTY(size, property, offset)\ +inline uint##size get##property() const {\ + return READ_SCI11ENDIAN_UINT##size(_data + (offset));\ +}\ +inline void set##property(uint##size value) {\ + WRITE_SCI11ENDIAN_UINT##size(_data + (offset), (value));\ +} + +struct BitmapTable; + +/** + * A convenience class for creating and modifying in-memory + * bitmaps. + */ +class SciBitmap : public Common::Serializable { + byte *_data; + int _dataSize; + Buffer _buffer; + bool _gc; + +public: + enum BitmapFlags { + kBitmapRemap = 2 + }; + + /** + * Gets the size of the bitmap header for the current + * engine version. + */ + static inline uint16 getBitmapHeaderSize() { + // TODO: These values are accurate for each engine, but there may be no reason + // to not simply just always use size 40, since SCI2.1mid does not seem to + // actually store any data above byte 40, and SCI2 did not allow bitmaps with + // scaling resolutions other than the default (320x200). Perhaps SCI3 used + // the extra bytes, or there is some reason why they tried to align the header + // size with other headers like pic headers? +// uint32 bitmapHeaderSize; +// if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) { +// bitmapHeaderSize = 46; +// } else if (getSciVersion() == SCI_VERSION_2_1_EARLY) { +// bitmapHeaderSize = 40; +// } else { +// bitmapHeaderSize = 36; +// } +// return bitmapHeaderSize; + return 46; + } + + /** + * Gets the byte size of a bitmap with the given width + * and height. + */ + static inline uint32 getBitmapSize(const uint16 width, const uint16 height) { + return width * height + getBitmapHeaderSize(); + } + + inline SciBitmap() : _data(nullptr), _dataSize(0), _gc(true) {} + + inline SciBitmap(const SciBitmap &other) { + _dataSize = other._dataSize; + _data = (byte *)malloc(other._dataSize); + memcpy(_data, other._data, other._dataSize); + if (_dataSize) { + _buffer = Buffer(getWidth(), getHeight(), getPixels()); + } + _gc = other._gc; + } + + inline ~SciBitmap() { + free(_data); + _data = nullptr; + _dataSize = 0; + } + + inline SciBitmap &operator=(const SciBitmap &other) { + if (this == &other) { + return *this; + } + + free(_data); + _dataSize = other._dataSize; + _data = (byte *)malloc(other._dataSize); + memcpy(_data, other._data, _dataSize); + if (_dataSize) { + _buffer = Buffer(getWidth(), getHeight(), getPixels()); + } + _gc = other._gc; + + return *this; + } + + /** + * Allocates and initialises a new bitmap. + */ + inline void create(const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 paletteSize, const bool remap, const bool gc) { + + _dataSize = getBitmapSize(width, height) + paletteSize; + _data = (byte *)realloc(_data, _dataSize); + _gc = gc; + + const uint16 bitmapHeaderSize = getBitmapHeaderSize(); + + setWidth(width); + setHeight(height); + setDisplace(Common::Point(displaceX, displaceY)); + setSkipColor(skipColor); + _data[9] = 0; + WRITE_SCI11ENDIAN_UINT16(_data + 10, 0); + setRemap(remap); + setDataSize(width * height); + WRITE_SCI11ENDIAN_UINT32(_data + 16, 0); + setHunkPaletteOffset(paletteSize > 0 ? (width * height) : 0); + setDataOffset(bitmapHeaderSize); + setUncompressedDataOffset(bitmapHeaderSize); + setControlOffset(0); + setScaledWidth(scaledWidth); + setScaledHeight(scaledHeight); + + _buffer = Buffer(getWidth(), getHeight(), getPixels()); + } + + inline int getRawSize() const { + return _dataSize; + } + + inline byte *getRawData() const { + return _data; + } + + inline Buffer &getBuffer() { + return _buffer; + } + + inline bool getShouldGC() const { + return _gc; + } + + inline void enableGC() { + _gc = true; + } + + inline void disableGC() { + _gc = false; + } + + BITMAP_PROPERTY(16, Width, 0); + BITMAP_PROPERTY(16, Height, 2); + + inline Common::Point getDisplace() const { + return Common::Point( + (int16)READ_SCI11ENDIAN_UINT16(_data + 4), + (int16)READ_SCI11ENDIAN_UINT16(_data + 6) + ); + } + + inline void setDisplace(const Common::Point &displace) { + WRITE_SCI11ENDIAN_UINT16(_data + 4, (uint16)displace.x); + WRITE_SCI11ENDIAN_UINT16(_data + 6, (uint16)displace.y); + } + + inline uint8 getSkipColor() const { + return _data[8]; + } + + inline void setSkipColor(const uint8 skipColor) { + _data[8] = skipColor; + } + + inline bool getRemap() const { + return READ_SCI11ENDIAN_UINT16(_data + 10) & kBitmapRemap; + } + + inline void setRemap(const bool remap) { + uint16 flags = READ_SCI11ENDIAN_UINT16(_data + 10); + if (remap) { + flags |= kBitmapRemap; + } else { + flags &= ~kBitmapRemap; + } + WRITE_SCI11ENDIAN_UINT16(_data + 10, flags); + } + + BITMAP_PROPERTY(32, DataSize, 12); + + inline uint32 getHunkPaletteOffset() const { + return READ_SCI11ENDIAN_UINT32(_data + 20); + } + + inline void setHunkPaletteOffset(uint32 hunkPaletteOffset) { + if (hunkPaletteOffset) { + hunkPaletteOffset += getBitmapHeaderSize(); + } + + WRITE_SCI11ENDIAN_UINT32(_data + 20, hunkPaletteOffset); + } + + BITMAP_PROPERTY(32, DataOffset, 24); + + // NOTE: This property is used as a "magic number" for + // validating that a block of memory is a valid bitmap, + // and so is always set to the size of the header. + BITMAP_PROPERTY(32, UncompressedDataOffset, 28); + + // NOTE: This property always seems to be zero + BITMAP_PROPERTY(32, ControlOffset, 32); + + inline uint16 getScaledWidth() const { + if (getDataOffset() >= 40) { + return READ_SCI11ENDIAN_UINT16(_data + 36); + } + + // SCI2 bitmaps did not have scaling ability + return 320; + } + + inline void setScaledWidth(uint16 scaledWidth) { + if (getDataOffset() >= 40) { + WRITE_SCI11ENDIAN_UINT16(_data + 36, scaledWidth); + } + } + + inline uint16 getScaledHeight() const { + if (getDataOffset() >= 40) { + return READ_SCI11ENDIAN_UINT16(_data + 38); + } + + // SCI2 bitmaps did not have scaling ability + return 200; + } + + inline void setScaledHeight(uint16 scaledHeight) { + if (getDataOffset() >= 40) { + WRITE_SCI11ENDIAN_UINT16(_data + 38, scaledHeight); + } + } + + inline byte *getPixels() { + return _data + getUncompressedDataOffset(); + } + + inline byte *getHunkPalette() { + if (getHunkPaletteOffset() == 0) { + return nullptr; + } + return _data + getHunkPaletteOffset(); + } + + virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; + +struct BitmapTable : public SegmentObjTable<SciBitmap> { + BitmapTable() : SegmentObjTable<SciBitmap>(SEG_TYPE_BITMAP) {} + + SegmentRef dereference(reg_t pointer) { + SegmentRef ret; + ret.isRaw = true; + ret.maxSize = at(pointer.getOffset()).getRawSize(); + ret.raw = at(pointer.getOffset()).getRawData(); + return ret; + } + + void saveLoadWithSerializer(Common::Serializer &ser); +}; + #endif diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 2c85907628..a338beffc9 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -121,9 +121,6 @@ void EngineState::reset(bool isRestoring) { _videoState.reset(); _syncedAudioOptions = false; - - _vmdPalStart = 0; - _vmdPalEnd = 256; } void EngineState::speedThrottler(uint32 neededSleep) { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index dd8d76f002..baa912b60e 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -203,7 +203,6 @@ public: // TODO: Excise video code from the state manager VideoState _videoState; - uint16 _vmdPalStart, _vmdPalEnd; bool _syncedAudioOptions; /** diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3e12084ed6..548fd477bf 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -405,6 +405,21 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { error("[VM] k%s[%x]: no subfunction ID parameter given", kernelCall.name, kernelCallNr); if (argv[0].isPointer()) error("[VM] k%s[%x]: given subfunction ID is actually a pointer", kernelCall.name, kernelCallNr); + +#ifdef ENABLE_SCI32 + // The Windows version of kShowMovie has subops, but the subop number + // is put in the second parameter in SCI2.1+, even though every other + // kcall with subops puts the subop in the first parameter. To allow use + // of the normal subops system, we swap the arguments so the subop + // number is in the usual place. + if (getSciVersion() > SCI_VERSION_2 && + g_sci->getPlatform() == Common::kPlatformWindows && + strcmp(kernelCall.name, "ShowMovie") == 0) { + assert(argc > 1); + SWAP(argv[0], argv[1]); + } +#endif + const uint16 subId = argv[0].toUint16(); // Skip over subfunction-id argc--; diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index f304f774af..7aaea0902a 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -88,6 +88,7 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { { GID_QFG2, 200, 200, 0, "astro", "messages", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152 { GID_QFG3, 780, 999, 0, "", "export 6", NULL, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692 { GID_QFG4, 710,64941, 0, "RandCycle", "doit", NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves + { GID_TORIN, 51400,64928, 0, "Blink", "init", NULL, 0, { WORKAROUND_FAKE, 1 } }, // op_div: when Lycentia knocks Torin out after he removes her collar SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -329,7 +330,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_PEPPER, -1, 894, 0, "Package", "doVerb", NULL, 3, { WORKAROUND_FAKE, 0 } }, // using the hand on the book in the inventory - bug #5154 { GID_PEPPER, 150, 928, 0, "Narrator", "startText", NULL, 0, { WORKAROUND_FAKE, 0 } }, // happens during the non-interactive demo of Pepper { GID_PQ4, -1, 25, 0, "iconToggle", "select", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when toggling the icon bar to auto-hide or not - { GID_PQSWAT, -1, 64950, 0, "View", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using the menu in the beginning + { GID_PQSWAT, -1, 64950, 0, NULL, "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // Using any menus in-game { GID_QFG1, -1, 210, 0, "Encounter", "init", sig_uninitread_qfg1_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1/hq1: going to the brigands hideout { GID_QFG1VGA, 16, 16, 0, "lassoFailed", "changeState", NULL, -1, { WORKAROUND_FAKE, 0 } }, // qfg1vga: casting the "fetch" spell in the screen with the flowers, temps 0 and 1 - bug #5309 { GID_QFG1VGA, -1, 210, 0, "Encounter", "init", sig_uninitread_qfg1vga_1, 0, { WORKAROUND_FAKE, 0 } }, // qfg1vga: going to the brigands hideout - bug #5515 @@ -379,7 +380,8 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SQ6, -1, 64950, -1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // called when pressing "Start game" in the main menu, when entering the Orion's Belt bar (room 300), and perhaps other places { GID_SQ6, -1, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game { GID_TORIN, -1, 64017, 0, "oFlags", "clear", NULL, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version - { GID_TORIN, 10000, 64029, 0, "oMessager", "nextMsg", NULL, 3, { WORKAROUND_FAKE, 0 } }, // start of chapter one + { GID_TORIN, 10000, 64029, 0, "oMessager", "nextMsg", NULL, 3, { WORKAROUND_FAKE, 0 } }, // start of chapter one + { GID_TORIN, 20100, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // going down the cliff at the first screen of chapter 2 (washing area) SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -492,7 +494,7 @@ const SciWorkaroundEntry kDisplay_workarounds[] = { { GID_PQ2, 23, 23, 0, "rm23Script", "elements", sig_kDisplay_pq2_1, 0, { WORKAROUND_IGNORE, 0 } }, // when looking at the 2nd page of pate's file - 0x75 as id - bug #5223 { GID_QFG1, 11, 11, 0, "battle", "init", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // DEMO: When entering battle, 0x75 as id { GID_SQ4, 397, 0, 0, "", "export 12", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // FLOPPY: when going into the computer store - bug #5227 - { GID_SQ4, 391, 391, 0, "doCatalog", "mode", sig_kDisplay_sq4_1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object + { GID_SQ4, 391, 391, 0, "doCatalog", "changeState", sig_kDisplay_sq4_1, 0, { WORKAROUND_IGNORE, 0 } }, // CD: clicking on catalog in roboter sale - a parameter is an object { GID_SQ4, 391, 391, 0, "choosePlug", "changeState", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // CD: ordering connector in roboter sale - a parameter is an object SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -519,6 +521,7 @@ const SciWorkaroundEntry kDoSoundPlay_workarounds[] = { { GID_LSL6HIRES, -1, 64989, 0, NULL, "play", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // always passes an extra null argument { GID_QFG4, -1, 64989, 0, NULL, "play", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // always passes an extra null argument { GID_PQ4, -1, 64989, 0, NULL, "play", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // always passes an extra null argument + { GID_GK1, -1, 64989, 0, NULL, "play", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // Mac version always passes an extra null argument SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -673,6 +676,14 @@ const SciWorkaroundEntry kPalVarySetPercent_workarounds[] = { }; // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround +const SciWorkaroundEntry kRandom_workarounds[] = { + { GID_TORIN, 51400,64928, 0, "Blink", "init", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when Lycentia knocks Torin out after he removes her collar + { GID_TORIN, 51400,64928, 0, "Blink", "cycleDone", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // when Lycentia knocks Torin out after he removes her collar + SCI_WORKAROUNDENTRY_TERMINATOR +}; + + +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kReadNumber_workarounds[] = { { GID_CNICK_LAURABOW,100, 101, 0, "dominoes.opt", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 { GID_HOYLE3, 100, 101, 0, "dominoes.opt", "doit", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // When dominoes.opt is present, the game scripts call kReadNumber with an extra integer parameter - bug #6425 @@ -688,6 +699,7 @@ const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = { // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kSetCursor_workarounds[] = { { GID_KQ5, -1, 768, 0, "KQCursor", "init", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters + { GID_MOTHERGOOSEHIRES,0, 0, -1, "MG", "setCursor", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // At the start of the game, an object is passed as the cel number SCI_WORKAROUNDENTRY_TERMINATOR }; @@ -755,6 +767,11 @@ const SciWorkaroundEntry kUnLoad_workarounds[] = { }; // gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround +const SciWorkaroundEntry kStringPutAt_workarounds[] = { + { GID_PHANTASMAGORIA,902, 64918, 0, "Str", "callKernel", NULL, 0, { WORKAROUND_IGNORE, 0 } }, // When starting a new game from after chapter 1, the game tries to save ego's object in a string +}; + +// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround const SciWorkaroundEntry kScrollWindowAdd_workarounds[] = { { GID_PHANTASMAGORIA, 45, 64907, 0, "ScrollableWindow", "addString", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // ScrollWindow interface passes the last two parameters twice }; diff --git a/engines/sci/engine/workarounds.h b/engines/sci/engine/workarounds.h index 248d37fc6c..2cccd05475 100644 --- a/engines/sci/engine/workarounds.h +++ b/engines/sci/engine/workarounds.h @@ -91,6 +91,7 @@ extern const SciWorkaroundEntry kMemory_workarounds[]; extern const SciWorkaroundEntry kMoveCursor_workarounds[]; extern const SciWorkaroundEntry kNewWindow_workarounds[]; extern const SciWorkaroundEntry kPalVarySetPercent_workarounds[]; +extern const SciWorkaroundEntry kRandom_workarounds[]; extern const SciWorkaroundEntry kReadNumber_workarounds[]; extern const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[]; extern const SciWorkaroundEntry kSetCursor_workarounds[]; @@ -99,6 +100,7 @@ extern const SciWorkaroundEntry kStrAt_workarounds[]; extern const SciWorkaroundEntry kStrCpy_workarounds[]; extern const SciWorkaroundEntry kStrLen_workarounds[]; extern const SciWorkaroundEntry kUnLoad_workarounds[]; +extern const SciWorkaroundEntry kStringPutAt_workarounds[]; extern const SciWorkaroundEntry kScrollWindowAdd_workarounds[]; extern SciWorkaroundSolution trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin); diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 4ad2a0cfa3..b267d2ebc2 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -30,6 +30,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/cursor32.h" #include "sci/graphics/frameout.h" #endif #include "sci/graphics/screen.h" @@ -168,9 +169,17 @@ SciEvent EventManager::getScummVMEvent() { if (getSciVersion() >= SCI_VERSION_2) { const Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer(); + if (ev.type == Common::EVENT_MOUSEMOVE) { + // This will clamp `mousePos` according to the restricted zone, + // so any cursor or screen item associated with the mouse position + // does not bounce when it hits the edge (or ignore the edge) + g_sci->_gfxCursor32->deviceMoved(mousePos); + } + Common::Point mousePosSci = mousePos; mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight)); noEvent.mousePosSci = input.mousePosSci = mousePosSci; + } else { #endif g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp index fb1f557ad6..9c77f31a14 100644 --- a/engines/sci/graphics/cache.cpp +++ b/engines/sci/graphics/cache.cpp @@ -95,10 +95,20 @@ int16 GfxCache::kernelViewGetCelHeight(GuiResourceId viewId, int16 loopNo, int16 } int16 GfxCache::kernelViewGetLoopCount(GuiResourceId viewId) { +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + return CelObjView::getNumLoops(viewId); + } +#endif return getView(viewId)->getLoopCount(); } int16 GfxCache::kernelViewGetCelCount(GuiResourceId viewId, int16 loopNo) { +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + return CelObjView::getNumCels(viewId, loopNo); + } +#endif return getView(viewId)->getCelCount(loopNo); } diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp index 48de054a31..d67a4dc03c 100644 --- a/engines/sci/graphics/celobj32.cpp +++ b/engines/sci/graphics/celobj32.cpp @@ -45,7 +45,7 @@ void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) { } } - int i = 1 - _activeIndex; + const int i = 1 - _activeIndex; _activeIndex = i; CelScalerTable &table = _scaleTables[i]; @@ -65,7 +65,7 @@ void CelScaler::activateScaleTables(const Ratio &scaleX, const Ratio &scaleY) { void CelScaler::buildLookupTable(int *table, const Ratio &ratio, const int size) { int value = 0; int remainder = 0; - int num = ratio.getNumerator(); + const int num = ratio.getNumerator(); for (int i = 0; i < size; ++i) { *table++ = value; remainder += ratio.getDenominator(); @@ -164,8 +164,8 @@ struct SCALER_Scale { const byte *_row; READER _reader; int16 _x; - static int16 _valuesX[1024]; - static int16 _valuesY[1024]; + static int16 _valuesX[4096]; + static int16 _valuesY[4096]; SCALER_Scale(const CelObj &celObj, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio scaleX, const Ratio scaleY) : _row(nullptr), @@ -204,7 +204,7 @@ struct SCALER_Scale { if (g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth == kLowResX) { const int16 unscaledX = (scaledPosition.x / scaleX).toInt(); if (FLIP) { - int lastIndex = celObj._width - 1; + const int lastIndex = celObj._width - 1; for (int16 x = targetRect.left; x < targetRect.right; ++x) { _valuesX[x] = lastIndex - (table->valuesX[x] - unscaledX); } @@ -220,7 +220,7 @@ struct SCALER_Scale { } } else { if (FLIP) { - int lastIndex = celObj._width - 1; + const int lastIndex = celObj._width - 1; for (int16 x = 0; x < targetRect.width(); ++x) { _valuesX[targetRect.left + x] = lastIndex - table->valuesX[x]; } @@ -249,9 +249,9 @@ struct SCALER_Scale { }; template<bool FLIP, typename READER> -int16 SCALER_Scale<FLIP, READER>::_valuesX[1024]; +int16 SCALER_Scale<FLIP, READER>::_valuesX[4096]; template<bool FLIP, typename READER> -int16 SCALER_Scale<FLIP, READER>::_valuesY[1024]; +int16 SCALER_Scale<FLIP, READER>::_valuesY[4096]; #pragma mark - #pragma mark CelObj - Resource readers @@ -261,7 +261,7 @@ private: #ifndef NDEBUG const int16 _sourceHeight; #endif - byte *_pixels; + const byte *_pixels; const int16 _sourceWidth; public: @@ -270,7 +270,7 @@ public: _sourceHeight(celObj._height), #endif _sourceWidth(celObj._width) { - byte *resource = celObj.getResPointer(); + const byte *resource = celObj.getResPointer(); _pixels = resource + READ_SCI11ENDIAN_UINT32(resource + celObj._celHeaderOffset + 24); } @@ -282,8 +282,8 @@ public: struct READER_Compressed { private: - byte *_resource; - byte _buffer[1024]; + const byte *const _resource; + byte _buffer[4096]; uint32 _controlOffset; uint32 _dataOffset; uint32 _uncompressedDataOffset; @@ -301,7 +301,7 @@ public: _maxWidth(maxWidth) { assert(maxWidth <= celObj._width); - byte *celHeader = _resource + celObj._celHeaderOffset; + const byte *const celHeader = _resource + celObj._celHeaderOffset; _dataOffset = READ_SCI11ENDIAN_UINT32(celHeader + 24); _uncompressedDataOffset = READ_SCI11ENDIAN_UINT32(celHeader + 28); _controlOffset = READ_SCI11ENDIAN_UINT32(celHeader + 32); @@ -311,14 +311,14 @@ public: assert(y >= 0 && y < _sourceHeight); if (y != _y) { // compressed data segment for row - byte *row = _resource + _dataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + y * 4); + const byte *row = _resource + _dataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + y * 4); // uncompressed data segment for row - byte *literal = _resource + _uncompressedDataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + _sourceHeight * 4 + y * 4); + const byte *literal = _resource + _uncompressedDataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + _sourceHeight * 4 + y * 4); uint8 length; for (int16 i = 0; i < _maxWidth; i += length) { - byte controlByte = *row++; + const byte controlByte = *row++; length = controlByte; // Run-length encoded @@ -581,7 +581,7 @@ void CelObj::submitPalette() const { int CelObj::_nextCacheId = 1; CelCache *CelObj::_cache = nullptr; -int CelObj::searchCache(const CelInfo32 &celInfo, int *nextInsertIndex) const { +int CelObj::searchCache(const CelInfo32 &celInfo, int *const nextInsertIndex) const { *nextInsertIndex = -1; int oldestId = _nextCacheId + 1; int oldestIndex = 0; @@ -685,10 +685,6 @@ void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common } } -void dummyFill(Buffer &target, const Common::Rect &targetRect) { - target.fillRect(targetRect, 250); -} - void CelObj::drawHzFlip(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const { render<MAPPER_NoMap, SCALER_NoScale<true, READER_Compressed> >(target, targetRect, scaledPosition); } @@ -795,6 +791,49 @@ void CelObj::scaleDrawUncompNoMD(Buffer &target, const Ratio &scaleX, const Rati #pragma mark - #pragma mark CelObjView +int16 CelObjView::getNumLoops(const GuiResourceId viewId) { + const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false); + + if (!resource) { + return 0; + } + + assert(resource->size >= 3); + return resource->data[2]; +} + +int16 CelObjView::getNumCels(const GuiResourceId viewId, const int16 loopNo) { + const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false); + + if (!resource) { + return 0; + } + + const byte *const data = resource->data; + + const uint16 loopCount = data[2]; + if (loopNo >= loopCount || loopNo < 0) { + return 0; + } + + const uint16 viewHeaderSize = READ_SCI11ENDIAN_UINT16(data); + const uint8 loopHeaderSize = data[12]; + const uint8 viewHeaderFieldSize = 2; + +#ifndef NDEBUG + const byte *const dataMax = data + resource->size; +#endif + const byte *loopHeader = data + viewHeaderFieldSize + viewHeaderSize + (loopHeaderSize * loopNo); + assert(loopHeader + 3 <= dataMax); + + if ((int8)loopHeader[0] != -1) { + loopHeader = data + viewHeaderFieldSize + viewHeaderSize + (loopHeaderSize * (int8)loopHeader[0]); + assert(loopHeader >= data && loopHeader + 3 <= dataMax); + } + + return loopHeader[2]; +} + CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) { _info.type = kCelTypeView; _info.resourceId = viewId; @@ -805,7 +844,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int _transparent = true; int cacheInsertIndex; - int cacheIndex = searchCache(_info, &cacheInsertIndex); + const int cacheIndex = searchCache(_info, &cacheInsertIndex); if (cacheIndex != -1) { CelCacheEntry &entry = (*_cache)[cacheIndex]; const CelObjView *const cachedCelObj = dynamic_cast<CelObjView *>(entry.celObj); @@ -821,20 +860,19 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int // generates view resource metadata for both SCI16 and SCI32 // implementations - Resource *resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false); + const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, viewId), false); // NOTE: SCI2.1/SQ6 just silently returns here. if (!resource) { - warning("View resource %d not loaded", viewId); - return; + error("View resource %d not found", viewId); } - byte *data = resource->data; + const byte *const data = resource->data; _scaledWidth = READ_SCI11ENDIAN_UINT16(data + 14); _scaledHeight = READ_SCI11ENDIAN_UINT16(data + 16); - if (_scaledWidth == 0 || _scaledHeight == 0) { + if (_scaledWidth == 0 && _scaledHeight == 0) { byte sizeFlag = data[5]; if (sizeFlag == 0) { _scaledWidth = kLowResX; @@ -848,7 +886,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int } } - uint16 loopCount = data[2]; + const uint16 loopCount = data[2]; if (_info.loopNo >= loopCount) { _info.loopNo = loopCount - 1; } @@ -856,14 +894,14 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int // NOTE: This is the actual check, in the actual location, // from SCI engine. if (loopNo < 0) { - error("Loop is less than 0!"); + error("Loop is less than 0"); } const uint16 viewHeaderSize = READ_SCI11ENDIAN_UINT16(data); const uint8 loopHeaderSize = data[12]; const uint8 viewHeaderFieldSize = 2; - byte *loopHeader = data + viewHeaderFieldSize + viewHeaderSize + (loopHeaderSize * _info.loopNo); + const byte *loopHeader = data + viewHeaderFieldSize + viewHeaderSize + (loopHeaderSize * _info.loopNo); if ((int8)loopHeader[0] != -1) { if (loopHeader[1] == 1) { @@ -878,10 +916,23 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int _info.celNo = celCount - 1; } + // A celNo can be negative and still valid. At least PQ4CD uses this strange + // arrangement to load its high-resolution main menu resource. In PQ4CD, the + // low-resolution menu is at view 23, loop 9, cel 0, and the high-resolution + // menu is at view 2300, loop 0, cel 0. View 2300 is specially crafted to + // have 2 loops, with the second loop having 0 cels. When in high-resolution + // mode, the game scripts only change the view resource ID from 23 to 2300, + // leaving loop 9 and cel 0 the same. The code in CelObjView constructor + // auto-corrects loop 9 to loop 1, and then auto-corrects the cel number + // from 0 to -1, which effectively causes loop 0, cel 0 to be read. + if (_info.celNo < 0 && _info.loopNo == 0) { + error("Cel is less than 0 on loop 0"); + } + _hunkPaletteOffset = READ_SCI11ENDIAN_UINT32(data + 8); _celHeaderOffset = READ_SCI11ENDIAN_UINT32(loopHeader + 12) + (data[13] * _info.celNo); - byte *celHeader = data + _celHeaderOffset; + const byte *const celHeader = data + _celHeaderOffset; _width = READ_SCI11ENDIAN_UINT16(celHeader); _height = READ_SCI11ENDIAN_UINT16(celHeader + 2); @@ -910,7 +961,7 @@ CelObjView::CelObjView(const GuiResourceId viewId, const int16 loopNo, const int } bool CelObjView::analyzeUncompressedForRemap() const { - byte *pixels = getResPointer() + READ_SCI11ENDIAN_UINT32(getResPointer() + _celHeaderOffset + 24); + const byte *pixels = getResPointer() + READ_SCI11ENDIAN_UINT32(getResPointer() + _celHeaderOffset + 24); for (int i = 0; i < _width * _height; ++i) { const byte pixel = pixels[i]; if ( @@ -927,7 +978,7 @@ bool CelObjView::analyzeUncompressedForRemap() const { bool CelObjView::analyzeForRemap() const { READER_Compressed reader(*this, _width); for (int y = 0; y < _height; y++) { - const byte *curRow = reader.getRow(y); + const byte *const curRow = reader.getRow(y); for (int x = 0; x < _width; x++) { const byte pixel = curRow[x]; if ( @@ -952,7 +1003,7 @@ CelObjView *CelObjView::duplicate() const { } byte *CelObjView::getResPointer() const { - const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, _info.resourceId), false); + Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeView, _info.resourceId), false); if (resource == nullptr) { error("Failed to load view %d from resource manager", _info.resourceId); } @@ -973,7 +1024,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { _remap = false; int cacheInsertIndex; - int cacheIndex = searchCache(_info, &cacheInsertIndex); + const int cacheIndex = searchCache(_info, &cacheInsertIndex); if (cacheIndex != -1) { CelCacheEntry &entry = (*_cache)[cacheIndex]; const CelObjPic *const cachedCelObj = dynamic_cast<CelObjPic *>(entry.celObj); @@ -985,15 +1036,14 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { return; } - Resource *resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypePic, picId), false); + const Resource *const resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypePic, picId), false); // NOTE: SCI2.1/SQ6 just silently returns here. if (!resource) { - warning("Pic resource %d not loaded", picId); - return; + error("Pic resource %d not found", picId); } - byte *data = resource->data; + const byte *const data = resource->data; _celCount = data[2]; @@ -1004,7 +1054,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { _celHeaderOffset = READ_SCI11ENDIAN_UINT16(data) + (READ_SCI11ENDIAN_UINT16(data + 4) * _info.celNo); _hunkPaletteOffset = READ_SCI11ENDIAN_UINT32(data + 6); - byte *celHeader = data + _celHeaderOffset; + const byte *const celHeader = data + _celHeaderOffset; _width = READ_SCI11ENDIAN_UINT16(celHeader); _height = READ_SCI11ENDIAN_UINT16(celHeader + 2); @@ -1016,8 +1066,8 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { _relativePosition.x = (int16)READ_SCI11ENDIAN_UINT16(celHeader + 38); _relativePosition.y = (int16)READ_SCI11ENDIAN_UINT16(celHeader + 40); - uint16 sizeFlag1 = READ_SCI11ENDIAN_UINT16(data + 10); - uint16 sizeFlag2 = READ_SCI11ENDIAN_UINT16(data + 12); + const uint16 sizeFlag1 = READ_SCI11ENDIAN_UINT16(data + 10); + const uint16 sizeFlag2 = READ_SCI11ENDIAN_UINT16(data + 12); if (sizeFlag2) { _scaledWidth = sizeFlag1; @@ -1036,7 +1086,7 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { if (celHeader[10] & 128) { // NOTE: This is correct according to SCI2.1/SQ6/DOS; // the engine re-reads the byte value as a word value - uint16 flags = READ_SCI11ENDIAN_UINT16(celHeader + 10); + const uint16 flags = READ_SCI11ENDIAN_UINT16(celHeader + 10); _transparent = flags & 1 ? true : false; _remap = flags & 2 ? true : false; } else { @@ -1051,8 +1101,8 @@ CelObjPic::CelObjPic(const GuiResourceId picId, const int16 celNo) { } bool CelObjPic::analyzeUncompressedForSkip() const { - byte *resource = getResPointer(); - byte *pixels = resource + READ_SCI11ENDIAN_UINT32(resource + _celHeaderOffset + 24); + const byte *const resource = getResPointer(); + const byte *const pixels = resource + READ_SCI11ENDIAN_UINT32(resource + _celHeaderOffset + 24); for (int i = 0; i < _width * _height; ++i) { uint8 pixel = pixels[i]; if (pixel == _transparentColor) { @@ -1064,7 +1114,7 @@ bool CelObjPic::analyzeUncompressedForSkip() const { } void CelObjPic::draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const bool mirrorX) { - Ratio square; + const Ratio square; _drawMirrored = mirrorX; drawTo(target, targetRect, scaledPosition, square, square); } @@ -1092,15 +1142,21 @@ CelObjMem::CelObjMem(const reg_t bitmapObject) { _celHeaderOffset = 0; _transparent = true; - BitmapResource bitmap(bitmapObject); - _width = bitmap.getWidth(); - _height = bitmap.getHeight(); - _displace = bitmap.getDisplace(); - _transparentColor = bitmap.getSkipColor(); - _scaledWidth = bitmap.getScaledWidth(); - _scaledHeight = bitmap.getScaledHeight(); - _hunkPaletteOffset = bitmap.getHunkPaletteOffset(); - _remap = bitmap.getRemap(); + SciBitmap *bitmap = g_sci->getEngineState()->_segMan->lookupBitmap(bitmapObject); + + // NOTE: SSCI did no error checking here at all. + if (!bitmap) { + error("Bitmap %04x:%04x not found", PRINT_REG(bitmapObject)); + } + + _width = bitmap->getWidth(); + _height = bitmap->getHeight(); + _displace = bitmap->getDisplace(); + _transparentColor = bitmap->getSkipColor(); + _scaledWidth = bitmap->getScaledWidth(); + _scaledHeight = bitmap->getScaledHeight(); + _hunkPaletteOffset = bitmap->getHunkPaletteOffset(); + _remap = bitmap->getRemap(); } CelObjMem *CelObjMem::duplicate() const { @@ -1108,7 +1164,7 @@ CelObjMem *CelObjMem::duplicate() const { } byte *CelObjMem::getResPointer() const { - return g_sci->getEngineState()->_segMan->getHunkPointer(_info.bitmap); + return g_sci->getEngineState()->_segMan->lookupBitmap(_info.bitmap)->getRawData(); } #pragma mark - diff --git a/engines/sci/graphics/celobj32.h b/engines/sci/graphics/celobj32.h index eb6ce3a3c9..21e86d03e0 100644 --- a/engines/sci/graphics/celobj32.h +++ b/engines/sci/graphics/celobj32.h @@ -147,7 +147,7 @@ struct CelScalerTable { * the correct column to read from the source bitmap * when drawing a scaled version of the source bitmap. */ - int valuesX[1024]; + int valuesX[4096]; /** * The ratio used to generate the x-values. @@ -159,7 +159,7 @@ struct CelScalerTable { * the correct row to read from a source bitmap when * drawing a scaled version of the source bitmap. */ - int valuesY[1024]; + int valuesY[4096]; /** * The ratio used to generate the y-values. @@ -400,7 +400,7 @@ public: * Reads the pixel at the given coordinates. This method * is valid only for CelObjView and CelObjPic. */ - virtual uint8 readPixel(uint16 x, uint16 y, bool mirrorX) const; + virtual uint8 readPixel(const uint16 x, const uint16 y, const bool mirrorX) const; /** * Submits the palette from this cel to the palette @@ -505,6 +505,9 @@ public: using CelObj::draw; + static int16 getNumLoops(const GuiResourceId viewId); + static int16 getNumCels(const GuiResourceId viewId, const int16 loopNo); + /** * Draws the cel to the target buffer using the * positioning, mirroring, and scaling information from diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 130416ff60..36026a8134 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -37,7 +37,7 @@ namespace Sci { -GfxCompare::GfxCompare(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxCoordAdjuster *coordAdjuster) +GfxCompare::GfxCompare(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxCoordAdjuster16 *coordAdjuster) : _segMan(segMan), _cache(cache), _screen(screen), _coordAdjuster(coordAdjuster) { } diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h index c7005980d0..dd65b90bea 100644 --- a/engines/sci/graphics/compare.h +++ b/engines/sci/graphics/compare.h @@ -34,7 +34,7 @@ class Screen; */ class GfxCompare { public: - GfxCompare(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxCoordAdjuster *coordAdjuster); + GfxCompare(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxCoordAdjuster16 *coordAdjuster); ~GfxCompare(); uint16 kernelOnControl(byte screenMask, const Common::Rect &rect); @@ -50,7 +50,7 @@ private: SegManager *_segMan; GfxCache *_cache; GfxScreen *_screen; - GfxCoordAdjuster *_coordAdjuster; + GfxCoordAdjuster16 *_coordAdjuster; uint16 isOnControl(uint16 screenMask, const Common::Rect &rect); diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp index 6b91bb4679..7689655d1d 100644 --- a/engines/sci/graphics/controls32.cpp +++ b/engines/sci/graphics/controls32.cpp @@ -54,18 +54,6 @@ GfxControls32::~GfxControls32() { } #pragma mark - -#pragma mark Garbage collection - -Common::Array<reg_t> GfxControls32::listObjectReferences() { - Common::Array<reg_t> ret; - ScrollWindowMap::const_iterator it; - for (it = _scrollWindows.begin(); it != _scrollWindows.end(); ++it) - ret.push_back(it->_value->getBitmap()); - - return ret; -} - -#pragma mark - #pragma mark Text input control reg_t GfxControls32::kernelEditText(const reg_t controlObject) { @@ -115,7 +103,10 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) { reg_t planeObj = readSelector(_segMan, controlObject, SELECTOR(plane)); Plane *sourcePlane = g_sci->_gfxFrameout->getVisiblePlanes().findByObject(planeObj); if (sourcePlane == nullptr) { - error("Could not find plane %04x:%04x", PRINT_REG(planeObj)); + sourcePlane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObj); + if (sourcePlane == nullptr) { + error("Could not find plane %04x:%04x", PRINT_REG(planeObj)); + } } editorPlaneRect.translate(sourcePlane->_gameRect.left, sourcePlane->_gameRect.top); @@ -127,7 +118,7 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) { if (titleObject.isNull()) { bool dimmed = readSelectorValue(_segMan, controlObject, SELECTOR(dimmed)); - editor.bitmap = _gfxText32->createFontBitmap(width, height, editor.textRect, editor.text, editor.foreColor, editor.backColor, editor.skipColor, editor.fontId, alignment, editor.borderColor, dimmed, true); + editor.bitmap = _gfxText32->createFontBitmap(width, height, editor.textRect, editor.text, editor.foreColor, editor.backColor, editor.skipColor, editor.fontId, alignment, editor.borderColor, dimmed, true, false); } else { error("Titled bitmaps are not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); } @@ -318,7 +309,7 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) { g_sci->_gfxFrameout->frameOut(true); } - _segMan->freeHunkEntry(editor.bitmap); + _segMan->freeBitmap(editor.bitmap); if (textChanged) { editor.text.trim(); @@ -380,6 +371,7 @@ void GfxControls32::flashCursor(TextEditor &editor) { #pragma mark Scrollable window control ScrollWindow::ScrollWindow(SegManager *segMan, const Common::Rect &gameRect, const Common::Point &position, const reg_t plane, const uint8 defaultForeColor, const uint8 defaultBackColor, const GuiResourceId defaultFontId, const TextAlign defaultAlignment, const int16 defaultBorderColor, const uint16 maxNumEntries) : + _segMan(segMan), _gfxText32(segMan, g_sci->_gfxCache), _maxNumEntries(maxNumEntries), _firstVisibleChar(0), @@ -421,13 +413,13 @@ ScrollWindow::ScrollWindow(SegManager *segMan, const Common::Rect &gameRect, con } assert(bitmapRect.width() > 0 && bitmapRect.height() > 0); - _bitmap = _gfxText32.createFontBitmap(bitmapRect.width(), bitmapRect.height(), _textRect, "", _foreColor, _backColor, skipColor, _fontId, _alignment, _borderColor, false, false); + _bitmap = _gfxText32.createFontBitmap(bitmapRect.width(), bitmapRect.height(), _textRect, "", _foreColor, _backColor, skipColor, _fontId, _alignment, _borderColor, false, false, false); debugC(1, kDebugLevelGraphics, "New ScrollWindow: textRect size: %d x %d, bitmap: %04x:%04x", _textRect.width(), _textRect.height(), PRINT_REG(_bitmap)); } ScrollWindow::~ScrollWindow() { - // _gfxText32._bitmap will get GCed once ScrollWindow is gone. + _segMan->freeBitmap(_bitmap); // _screenItem will be deleted by GfxFrameout } diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h index 460b0b5625..680c70d2d6 100644 --- a/engines/sci/graphics/controls32.h +++ b/engines/sci/graphics/controls32.h @@ -227,6 +227,8 @@ public: const reg_t getBitmap() const { return _bitmap; } private: + SegManager *_segMan; + typedef Common::Array<ScrollWindowEntry> EntriesList; /** @@ -418,11 +420,6 @@ private: GfxText32 *_gfxText32; #pragma mark - -#pragma mark Garbage collection -public: - Common::Array<reg_t> listObjectReferences(); - -#pragma mark - #pragma mark Text input control public: reg_t kernelEditText(const reg_t controlObject); diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp index 93dff10382..2f22d191d0 100644 --- a/engines/sci/graphics/coordadjuster.cpp +++ b/engines/sci/graphics/coordadjuster.cpp @@ -32,9 +32,6 @@ namespace Sci { -GfxCoordAdjuster::GfxCoordAdjuster() { -} - GfxCoordAdjuster16::GfxCoordAdjuster16(GfxPorts *ports) : _ports(ports) { } @@ -83,53 +80,4 @@ Common::Rect GfxCoordAdjuster16::pictureGetDisplayArea() { return displayArea; } -#ifdef ENABLE_SCI32 -GfxCoordAdjuster32::GfxCoordAdjuster32(SegManager *segMan) - : _segMan(segMan) { - _scriptsRunningWidth = 0; - _scriptsRunningHeight = 0; -} - -GfxCoordAdjuster32::~GfxCoordAdjuster32() { -} - -void GfxCoordAdjuster32::kernelGlobalToLocal(int16 &x, int16 &y, reg_t planeObject) { - uint16 planeTop = readSelectorValue(_segMan, planeObject, SELECTOR(top)); - uint16 planeLeft = readSelectorValue(_segMan, planeObject, SELECTOR(left)); - - y -= planeTop; - x -= planeLeft; -} -void GfxCoordAdjuster32::kernelLocalToGlobal(int16 &x, int16 &y, reg_t planeObject) { - uint16 planeTop = readSelectorValue(_segMan, planeObject, SELECTOR(top)); - uint16 planeLeft = readSelectorValue(_segMan, planeObject, SELECTOR(left)); - - x += planeLeft; - y += planeTop; -} - -void GfxCoordAdjuster32::setScriptsResolution(uint16 width, uint16 height) { - _scriptsRunningWidth = width; - _scriptsRunningHeight = height; -} - -void GfxCoordAdjuster32::fromDisplayToScript(int16 &y, int16 &x) { - y = ((y * _scriptsRunningHeight) / g_sci->_gfxScreen->getHeight()); - x = ((x * _scriptsRunningWidth) / g_sci->_gfxScreen->getWidth()); -} - -void GfxCoordAdjuster32::fromScriptToDisplay(int16 &y, int16 &x) { - y = ((y * g_sci->_gfxScreen->getHeight()) / _scriptsRunningHeight); - x = ((x * g_sci->_gfxScreen->getWidth()) / _scriptsRunningWidth); -} - -void GfxCoordAdjuster32::pictureSetDisplayArea(Common::Rect displayArea) { - _pictureDisplayArea = displayArea; -} - -Common::Rect GfxCoordAdjuster32::pictureGetDisplayArea() { - return _pictureDisplayArea; -} -#endif - } // End of namespace Sci diff --git a/engines/sci/graphics/coordadjuster.h b/engines/sci/graphics/coordadjuster.h index cb0227fbe4..f7ebd3ec75 100644 --- a/engines/sci/graphics/coordadjuster.h +++ b/engines/sci/graphics/coordadjuster.h @@ -35,27 +35,7 @@ class GfxPorts; * most of the time sci32 doesn't do any coordinate adjustment at all * sci16 does a lot of port adjustment on given coordinates */ -class GfxCoordAdjuster { -public: - GfxCoordAdjuster(); - virtual ~GfxCoordAdjuster() { } - - virtual void kernelGlobalToLocal(int16 &x, int16 &y, reg_t planeObject = NULL_REG) { } - virtual void kernelLocalToGlobal(int16 &x, int16 &y, reg_t planeObject = NULL_REG) { } - - virtual Common::Rect onControl(Common::Rect rect) { return rect; } - virtual void setCursorPos(Common::Point &pos) { } - virtual void moveCursor(Common::Point &pos) { } - - virtual void setScriptsResolution(uint16 width, uint16 height) { } - virtual void fromScriptToDisplay(int16 &y, int16 &x) { } - virtual void fromDisplayToScript(int16 &y, int16 &x) { } - - virtual Common::Rect pictureGetDisplayArea() { return Common::Rect(0, 0); } -private: -}; - -class GfxCoordAdjuster16 : public GfxCoordAdjuster { +class GfxCoordAdjuster16 { public: GfxCoordAdjuster16(GfxPorts *ports); ~GfxCoordAdjuster16(); @@ -73,32 +53,6 @@ private: GfxPorts *_ports; }; -#ifdef ENABLE_SCI32 -class GfxCoordAdjuster32 : public GfxCoordAdjuster { -public: - GfxCoordAdjuster32(SegManager *segMan); - ~GfxCoordAdjuster32(); - - void kernelGlobalToLocal(int16 &x, int16 &y, reg_t planeObject = NULL_REG); - void kernelLocalToGlobal(int16 &x, int16 &y, reg_t planeObject = NULL_REG); - - void setScriptsResolution(uint16 width, uint16 height); - void fromScriptToDisplay(int16 &y, int16 &x); - void fromDisplayToScript(int16 &y, int16 &x); - - void pictureSetDisplayArea(Common::Rect displayArea); - Common::Rect pictureGetDisplayArea(); - -private: - SegManager *_segMan; - - Common::Rect _pictureDisplayArea; - - uint16 _scriptsRunningWidth; - uint16 _scriptsRunningHeight; -}; -#endif - } // End of namespace Sci #endif diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index f5dd473959..7cf9a574ef 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -80,7 +80,7 @@ GfxCursor::~GfxCursor() { kernelClearZoomZone(); } -void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, EventManager *event) { +void GfxCursor::init(GfxCoordAdjuster16 *coordAdjuster, EventManager *event) { _coordAdjuster = coordAdjuster; _event = event; } @@ -512,32 +512,18 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu // automatically. The view resources may exist, but none of the games actually // use them. - if (_macCursorRemap.empty()) { - // QFG1/Freddy/Hoyle4 use a straight viewNum->cursor ID mapping - // KQ6 uses this mapping for its cursors - if (g_sci->getGameId() == GID_KQ6) { - if (viewNum == 990) // Inventory Cursors - viewNum = loopNum * 16 + celNum + 2000; - else if (viewNum == 998) // Regular Cursors - viewNum = celNum + 1000; - else // Unknown cursor, ignored - return; - } - if (g_sci->hasMacIconBar()) - g_sci->_gfxMacIconBar->setInventoryIcon(viewNum); - } else { - // If we do have the list, we'll be using a remap based on what the - // scripts have given us. - for (uint32 i = 0; i < _macCursorRemap.size(); i++) { - if (viewNum == _macCursorRemap[i]) { - viewNum = (i + 1) * 0x100 + loopNum * 0x10 + celNum; - break; - } - - if (i == _macCursorRemap.size()) - error("Unmatched Mac cursor %d", viewNum); - } + // QFG1/Freddy/Hoyle4 use a straight viewNum->cursor ID mapping + // KQ6 uses this mapping for its cursors + if (g_sci->getGameId() == GID_KQ6) { + if (viewNum == 990) // Inventory Cursors + viewNum = loopNum * 16 + celNum + 2000; + else if (viewNum == 998) // Regular Cursors + viewNum = celNum + 1000; + else // Unknown cursor, ignored + return; } + if (g_sci->hasMacIconBar()) + g_sci->_gfxMacIconBar->setInventoryIcon(viewNum); Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, viewNum), false); @@ -568,9 +554,4 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu kernelShow(); } -void GfxCursor::setMacCursorRemapList(int cursorCount, reg_t *cursors) { - for (int i = 0; i < cursorCount; i++) - _macCursorRemap.push_back(cursors[i].toUint16()); -} - } // End of namespace Sci diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index 5125469cfe..36518ea5db 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -55,7 +55,7 @@ public: GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *screen); ~GfxCursor(); - void init(GfxCoordAdjuster *coordAdjuster, EventManager *event); + void init(GfxCoordAdjuster16 *coordAdjuster, EventManager *event); void kernelShow(); void kernelHide(); @@ -95,15 +95,13 @@ public: void kernelSetPos(Common::Point pos); void kernelMoveCursor(Common::Point pos); - void setMacCursorRemapList(int cursorCount, reg_t *cursors); - private: void purgeCache(); ResourceManager *_resMan; GfxScreen *_screen; GfxPalette *_palette; - GfxCoordAdjuster *_coordAdjuster; + GfxCoordAdjuster16 *_coordAdjuster; EventManager *_event; int _upscaledHires; @@ -136,9 +134,6 @@ private: // these instead and replace the game's gold cursors with their silver // equivalents. bool _useSilverSQ4CDCursors; - - // Mac versions of games use a remap list to remap their cursors - Common::Array<uint16> _macCursorRemap; }; } // End of namespace Sci diff --git a/engines/sci/graphics/cursor32.cpp b/engines/sci/graphics/cursor32.cpp new file mode 100644 index 0000000000..88150db6e6 --- /dev/null +++ b/engines/sci/graphics/cursor32.cpp @@ -0,0 +1,448 @@ +/* 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/rational.h" // for Rational, operator* +#include "common/system.h" // for OSystem, g_system +#include "common/memstream.h" +#include "graphics/cursorman.h" // for CursorMan +#include "graphics/maccursor.h" +#include "sci/graphics/celobj32.h" // for CelObjView, CelInfo32, Ratio +#include "sci/graphics/cursor32.h" +#include "sci/graphics/frameout.h" // for GfxFrameout + +namespace Sci { + +GfxCursor32::GfxCursor32() : + _hideCount(0), + _position(0, 0), + _writeToVMAP(false) { + CursorMan.showMouse(false); +} + +void GfxCursor32::init(const Buffer &vmap) { + _vmap = vmap; + _vmapRegion.rect = Common::Rect(_vmap.screenWidth, _vmap.screenHeight); + _vmapRegion.data = (byte *)_vmap.getPixels(); + _restrictedArea = _vmapRegion.rect; +} + +GfxCursor32::~GfxCursor32() { + CursorMan.showMouse(true); + free(_cursor.data); + free(_cursorBack.data); + free(_drawBuff1.data); + free(_drawBuff2.data); + free(_savedVmapRegion.data); +} + +void GfxCursor32::hide() { + if (_hideCount++) { + return; + } + + if (!_cursorBack.rect.isEmpty()) { + drawToHardware(_cursorBack); + } +} + +void GfxCursor32::revealCursor() { + _cursorBack.rect = _cursor.rect; + _cursorBack.rect.clip(_vmapRegion.rect); + if (_cursorBack.rect.isEmpty()) { + return; + } + + readVideo(_cursorBack); + _drawBuff1.rect = _cursor.rect; + copy(_drawBuff1, _cursorBack); + paint(_drawBuff1, _cursor); + drawToHardware(_drawBuff1); +} + +void GfxCursor32::paint(DrawRegion &target, const DrawRegion &source) { + if (source.rect.isEmpty()) { + return; + } + + Common::Rect drawRect(source.rect); + drawRect.clip(target.rect); + if (drawRect.isEmpty()) { + return; + } + + const int16 sourceXOffset = drawRect.left - source.rect.left; + const int16 sourceYOffset = drawRect.top - source.rect.top; + const int16 drawRectWidth = drawRect.width(); + const int16 drawRectHeight = drawRect.height(); + + byte *targetPixel = target.data + ((drawRect.top - target.rect.top) * target.rect.width()) + (drawRect.left - target.rect.left); + const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset; + const uint8 skipColor = source.skipColor; + + const int16 sourceStride = source.rect.width() - drawRectWidth; + const int16 targetStride = target.rect.width() - drawRectWidth; + + for (int16 y = 0; y < drawRectHeight; ++y) { + for (int16 x = 0; x < drawRectWidth; ++x) { + if (*sourcePixel != skipColor) { + *targetPixel = *sourcePixel; + } + ++targetPixel; + ++sourcePixel; + } + sourcePixel += sourceStride; + targetPixel += targetStride; + } +} + +void GfxCursor32::drawToHardware(const DrawRegion &source) { + Common::Rect drawRect(source.rect); + drawRect.clip(_vmapRegion.rect); + const int16 sourceXOffset = drawRect.left - source.rect.left; + const int16 sourceYOffset = drawRect.top - source.rect.top; + byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset; + + g_system->copyRectToScreen(sourcePixel, source.rect.width(), drawRect.left, drawRect.top, drawRect.width(), drawRect.height()); +} + +void GfxCursor32::unhide() { + if (_hideCount == 0 || --_hideCount) { + return; + } + + _cursor.rect.moveTo(_position.x - _hotSpot.x, _position.y - _hotSpot.y); + revealCursor(); +} + +void GfxCursor32::show() { + if (_hideCount) { + _hideCount = 0; + _cursor.rect.moveTo(_position.x - _hotSpot.x, _position.y - _hotSpot.y); + revealCursor(); + } +} + +void GfxCursor32::setRestrictedArea(const Common::Rect &rect) { + _restrictedArea = rect; + + const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + + mulru(_restrictedArea, Ratio(screenWidth, scriptWidth), Ratio(screenHeight, scriptHeight), 0); + + if (_position.x < rect.left) { + _position.x = rect.left; + } + if (_position.x >= rect.right) { + _position.x = rect.right - 1; + } + if (_position.y < rect.top) { + _position.y = rect.top; + } + if (_position.y >= rect.bottom) { + _position.y = rect.bottom - 1; + } + + g_system->warpMouse(_position.x, _position.y); +} + +void GfxCursor32::clearRestrictedArea() { + _restrictedArea = _vmapRegion.rect; +} + +void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) { + hide(); + + _cursorInfo.resourceId = viewId; + _cursorInfo.loopNo = loopNo; + _cursorInfo.celNo = celNo; + + if (_macCursorRemap.empty() && viewId != -1) { + CelObjView view(viewId, loopNo, celNo); + + _hotSpot = view._displace; + _width = view._width; + _height = view._height; + + // SSCI never increased the size of cursors, but some of the cursors + // in early SCI32 games were designed for low-resolution display mode + // and so are kind of hard to pick out when running in high-resolution + // mode. + // To address this, we make some slight adjustments to cursor display + // in these early games: + // GK1: All the cursors are increased in size since they all appear to + // be designed for low-res display. + // PQ4: We only make the cursors bigger if they are above a set + // threshold size because inventory items usually have a + // high-resolution cursor representation. + bool pixelDouble = false; + if (g_sci->_gfxFrameout->_isHiRes && + (g_sci->getGameId() == GID_GK1 || + (g_sci->getGameId() == GID_PQ4 && _width <= 22 && _height <= 22))) { + + _width *= 2; + _height *= 2; + _hotSpot.x *= 2; + _hotSpot.y *= 2; + pixelDouble = true; + } + + _cursor.data = (byte *)realloc(_cursor.data, _width * _height); + _cursor.rect = Common::Rect(_width, _height); + memset(_cursor.data, 255, _width * _height); + _cursor.skipColor = 255; + + Buffer target(_width, _height, _cursor.data); + if (pixelDouble) { + view.draw(target, _cursor.rect, Common::Point(0, 0), false, 2, 2); + } else { + view.draw(target, _cursor.rect, Common::Point(0, 0), false); + } + } else if (!_macCursorRemap.empty() && viewId != -1) { + // Mac cursor handling + GuiResourceId viewNum = viewId; + + // Remap cursor view based on what the scripts have given us. + for (uint32 i = 0; i < _macCursorRemap.size(); i++) { + if (viewNum == _macCursorRemap[i]) { + viewNum = (i + 1) * 0x100 + loopNo * 0x10 + celNo; + break; + } + + if (i == _macCursorRemap.size()) + error("Unmatched Mac cursor %d", viewNum); + } + + _cursorInfo.resourceId = viewNum; + + Resource *resource = g_sci->getResMan()->findResource(ResourceId(kResourceTypeCursor, viewNum), false); + + if (!resource) { + // The cursor resources often don't exist, this is normal behavior + debug(0, "Mac cursor %d not found", viewNum); + return; + } + Common::MemoryReadStream resStream(resource->data, resource->size); + Graphics::MacCursor *macCursor = new Graphics::MacCursor(); + + if (!macCursor->readFromStream(resStream)) { + warning("Failed to load Mac cursor %d", viewNum); + delete macCursor; + return; + } + + _hotSpot = Common::Point(macCursor->getHotspotX(), macCursor->getHotspotY()); + _width = macCursor->getWidth(); + _height = macCursor->getHeight(); + + _cursor.data = (byte *)realloc(_cursor.data, _width * _height); + memcpy(_cursor.data, macCursor->getSurface(), _width * _height); + _cursor.rect = Common::Rect(_width, _height); + _cursor.skipColor = macCursor->getKeyColor(); + + // The cursor will be drawn on next refresh + delete macCursor; + } else { + _hotSpot = Common::Point(0, 0); + _width = _height = 1; + _cursor.data = (byte *)realloc(_cursor.data, _width * _height); + _cursor.rect = Common::Rect(_width, _height); + *_cursor.data = _cursor.skipColor; + _cursorBack.rect = _cursor.rect; + _cursorBack.rect.clip(_vmapRegion.rect); + if (!_cursorBack.rect.isEmpty()) { + readVideo(_cursorBack); + } + } + + _cursorBack.data = (byte *)realloc(_cursorBack.data, _width * _height); + _drawBuff1.data = (byte *)realloc(_drawBuff1.data, _width * _height); + _drawBuff2.data = (byte *)realloc(_drawBuff2.data, _width * _height * 4); + _savedVmapRegion.data = (byte *)realloc(_savedVmapRegion.data, _width * _height); + + unhide(); +} + +void GfxCursor32::readVideo(DrawRegion &target) { + if (g_sci->_gfxFrameout->_frameNowVisible) { + copy(target, _vmapRegion); + } else { + // NOTE: SSCI would read the background for the cursor directly out of + // video memory here, but as far as can be determined, this does not + // seem to actually be necessary for proper cursor rendering + } +} + +void GfxCursor32::copy(DrawRegion &target, const DrawRegion &source) { + if (source.rect.isEmpty()) { + return; + } + + Common::Rect drawRect(source.rect); + drawRect.clip(target.rect); + if (drawRect.isEmpty()) { + return; + } + + const int16 sourceXOffset = drawRect.left - source.rect.left; + const int16 sourceYOffset = drawRect.top - source.rect.top; + const int16 drawWidth = drawRect.width(); + const int16 drawHeight = drawRect.height(); + + byte *targetPixel = target.data + ((drawRect.top - target.rect.top) * target.rect.width()) + (drawRect.left - target.rect.left); + const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset; + + const int16 sourceStride = source.rect.width(); + const int16 targetStride = target.rect.width(); + + for (int y = 0; y < drawHeight; ++y) { + memcpy(targetPixel, sourcePixel, drawWidth); + targetPixel += targetStride; + sourcePixel += sourceStride; + } +} + +void GfxCursor32::setPosition(const Common::Point &position) { + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + + _position.x = (position.x * Ratio(screenWidth, scriptWidth)).toInt(); + _position.y = (position.y * Ratio(screenHeight, scriptHeight)).toInt(); + + g_system->warpMouse(_position.x, _position.y); +} + +void GfxCursor32::gonnaPaint(Common::Rect paintRect) { + if (!_hideCount && !_writeToVMAP && !_cursorBack.rect.isEmpty()) { + paintRect.left &= ~3; + paintRect.right |= 3; + if (_cursorBack.rect.intersects(paintRect)) { + _writeToVMAP = true; + } + } +} + +void GfxCursor32::paintStarting() { + if (_writeToVMAP) { + _savedVmapRegion.rect = _cursor.rect; + copy(_savedVmapRegion, _vmapRegion); + paint(_vmapRegion, _cursor); + } +} + +void GfxCursor32::donePainting() { + if (_writeToVMAP) { + copy(_vmapRegion, _savedVmapRegion); + _savedVmapRegion.rect = Common::Rect(); + _writeToVMAP = false; + } + + if (!_hideCount && !_cursorBack.rect.isEmpty()) { + copy(_cursorBack, _vmapRegion); + } +} + +void GfxCursor32::deviceMoved(Common::Point &position) { + if (position.x < _restrictedArea.left) { + position.x = _restrictedArea.left; + } + if (position.x >= _restrictedArea.right) { + position.x = _restrictedArea.right - 1; + } + if (position.y < _restrictedArea.top) { + position.y = _restrictedArea.top; + } + if (position.y >= _restrictedArea.bottom) { + position.y = _restrictedArea.bottom - 1; + } + + _position = position; + + g_system->warpMouse(position.x, position.y); + move(); +} + +void GfxCursor32::move() { + if (_hideCount) { + return; + } + + // Cursor moved onto the screen after being offscreen + _cursor.rect.moveTo(_position.x - _hotSpot.x, _position.y - _hotSpot.y); + if (_cursorBack.rect.isEmpty()) { + revealCursor(); + return; + } + + // Cursor moved offscreen + if (!_cursor.rect.intersects(_vmapRegion.rect)) { + drawToHardware(_cursorBack); + return; + } + + if (!_cursor.rect.intersects(_cursorBack.rect)) { + // Cursor moved to a completely different part of the screen + _drawBuff1.rect = _cursor.rect; + _drawBuff1.rect.clip(_vmapRegion.rect); + readVideo(_drawBuff1); + + _drawBuff2.rect = _drawBuff1.rect; + copy(_drawBuff2, _drawBuff1); + + paint(_drawBuff1, _cursor); + drawToHardware(_drawBuff1); + + drawToHardware(_cursorBack); + + _cursorBack.rect = _cursor.rect; + _cursorBack.rect.clip(_vmapRegion.rect); + copy(_cursorBack, _drawBuff2); + } else { + // Cursor moved, but still overlaps the previous cursor location + Common::Rect mergedRect(_cursorBack.rect); + mergedRect.extend(_cursor.rect); + mergedRect.clip(_vmapRegion.rect); + + _drawBuff2.rect = mergedRect; + readVideo(_drawBuff2); + + copy(_drawBuff2, _cursorBack); + + _cursorBack.rect = _cursor.rect; + _cursorBack.rect.clip(_vmapRegion.rect); + copy(_cursorBack, _drawBuff2); + + paint(_drawBuff2, _cursor); + drawToHardware(_drawBuff2); + } +} + +void GfxCursor32::setMacCursorRemapList(int cursorCount, reg_t *cursors) { + for (int i = 0; i < cursorCount; i++) + _macCursorRemap.push_back(cursors[i].toUint16()); +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/cursor32.h b/engines/sci/graphics/cursor32.h new file mode 100644 index 0000000000..88a75beb7f --- /dev/null +++ b/engines/sci/graphics/cursor32.h @@ -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. + * + */ + +#ifndef SCI_GRAPHICS_CURSOR32_H +#define SCI_GRAPHICS_CURSOR32_H + +#include "common/rect.h" // for Point, Rect +#include "common/scummsys.h" // for int16, byte, uint8 +#include "common/serializer.h" // for Serializable, Serializer (ptr only) +#include "sci/graphics/celobj32.h" // for CelInfo32 +#include "sci/graphics/helpers.h" // for GuiResourceId + +namespace Sci { + +class GfxCursor32 : Common::Serializable { +public: + GfxCursor32(); + ~GfxCursor32(); + + /** + * Initialises the cursor system with the given + * buffer to use as the output buffer for + * rendering the cursor. + */ + void init(const Buffer &vmap); + + /** + * Called when the hardware mouse moves. + */ + void deviceMoved(Common::Point &position); + + /** + * Called by GfxFrameout once for each show + * rectangle that is going to be drawn to + * hardware. + */ + void gonnaPaint(Common::Rect paintRect); + + /** + * Called by GfxFrameout when the rendering to + * hardware begins. + */ + void paintStarting(); + + /** + * Called by GfxFrameout when the output buffer + * has finished rendering to hardware. + */ + void donePainting(); + + /** + * Hides the cursor. Each call to `hide` will + * increment a hide counter, which must be + * returned to 0 before the cursor will be + * shown again. + */ + void hide(); + + /** + * Shows the cursor, if the hide counter is + * returned to 0. + */ + void unhide(); + + /** + * Shows the cursor regardless of the state of + * the hide counter. + */ + void show(); + + /** + * Sets the view used to render the cursor. + */ + void setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo); + + /** + * Explicitly sets the position of the cursor, + * in game script coordinates. + */ + void setPosition(const Common::Point &position); + + /** + * Sets the region that the mouse is allowed + * to move within. + */ + void setRestrictedArea(const Common::Rect &rect); + + /** + * Removes restrictions on mouse movement. + */ + void clearRestrictedArea(); + + void setMacCursorRemapList(int cursorCount, reg_t *cursors); + + virtual void saveLoadWithSerializer(Common::Serializer &ser); + +private: + struct DrawRegion { + Common::Rect rect; + byte *data; + uint8 skipColor; + + DrawRegion() : rect(), data(nullptr) {} + }; + + /** + * Information about the current cursor. + * Used to restore cursor when loading a + * savegame. + */ + CelInfo32 _cursorInfo; + + /** + * Content behind the cursor? TODO + */ + DrawRegion _cursorBack; + + /** + * Scratch buffer. + */ + DrawRegion _drawBuff1; + + /** + * Scratch buffer 2. + */ + DrawRegion _drawBuff2; + + /** + * A draw region representing the current + * output buffer. + */ + DrawRegion _vmapRegion; + + /** + * The content behind the cursor in the + * output buffer. + */ + DrawRegion _savedVmapRegion; + + /** + * The cursor bitmap. + */ + DrawRegion _cursor; + + /** + * The width and height of the cursor, + * in screen coordinates. + */ + int16 _width, _height; + + /** + * The output buffer where the cursor is + * rendered. + */ + Buffer _vmap; + + /** + * The number of times the cursor has been + * hidden. + */ + int _hideCount; + + /** + * The rendered position of the cursor, in + * screen coordinates. + */ + Common::Point _position; + + /** + * The position of the cursor hot spot, relative + * to the cursor origin, in screen pixels. + */ + Common::Point _hotSpot; + + /** + * The area within which the cursor is allowed + * to move, in screen pixels. + */ + Common::Rect _restrictedArea; + + /** + * Indicates whether or not the cursor needs to + * be repainted on the output buffer due to a + * change of graphics in the area underneath the + * cursor. + */ + bool _writeToVMAP; + + // Mac versions of games use a remap list to remap their cursors + Common::Array<uint16> _macCursorRemap; + + /** + * Reads data from the output buffer or hardware + * to the given draw region. + */ + void readVideo(DrawRegion &target); + + /** + * Reads data from the output buffer to the + * given draw region. + */ + void readVideoFromVmap(DrawRegion &target); + + /** + * Copies pixel data from the given source to + * the given target. + */ + void copy(DrawRegion &target, const DrawRegion &source); + + /** + * Draws from the given source onto the given + * target, skipping pixels in the source that + * match the `skipColor` property. + */ + void paint(DrawRegion &target, const DrawRegion &source); + + /** + * Draws the cursor to the position it was + * drawn to prior to moving offscreen or being + * hidden by a call to `hide`. + */ + void revealCursor(); + + /** + * Draws the given source to the output buffer. + */ + void drawToHardware(const DrawRegion &source); + + /** + * Renders the cursor at its new location. + */ + void move(); +}; + +} // End of namespace Sci +#endif diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index a7899b8d89..4e0aa22669 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -29,6 +29,7 @@ #include "common/system.h" #include "common/textconsole.h" #include "engines/engine.h" +#include "engines/util.h" #include "graphics/palette.h" #include "graphics/surface.h" @@ -39,80 +40,52 @@ #include "sci/engine/selector.h" #include "sci/engine/vm.h" #include "sci/graphics/cache.h" -#include "sci/graphics/coordadjuster.h" #include "sci/graphics/compare.h" +#include "sci/graphics/cursor32.h" #include "sci/graphics/font.h" -#include "sci/graphics/screen.h" +#include "sci/graphics/frameout.h" #include "sci/graphics/paint32.h" #include "sci/graphics/palette32.h" #include "sci/graphics/plane32.h" #include "sci/graphics/remap32.h" +#include "sci/graphics/screen.h" #include "sci/graphics/screen_item32.h" #include "sci/graphics/text32.h" #include "sci/graphics/frameout.h" -#include "sci/video/robot_decoder.h" +#include "sci/graphics/transitions32.h" +#include "sci/graphics/video32.h" namespace Sci { -static int dissolveSequences[2][20] = { - /* SCI2.1early- */ { 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080 }, - /* SCI2.1mid+ */ { 0, 0, 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080, 73728, 132096, 466944 } -}; -static int16 divisionsDefaults[2][16] = { - /* SCI2.1early- */ { 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 40, 40, 101, 101 }, - /* SCI2.1mid+ */ { 1, 20, 20, 20, 20, 10, 10, 10, 10, 20, 20, 6, 10, 101, 101, 2 } -}; -static int16 unknownCDefaults[2][16] = { - /* SCI2.1early- */ { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0, 0, 0, 0 }, - /* SCI2.1mid+ */ { 0, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 0, 0, 7, 7, 0 } -}; - -GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette32 *palette) : - _isHiRes(false), +GfxFrameout::GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor) : + _isHiRes(ConfMan.getBool("enable_high_resolution_graphics")), _palette(palette), - _resMan(resMan), - _screen(screen), + _cursor(cursor), _segMan(segMan), + _transitions(transitions), _benchmarkingFinished(false), _throttleFrameOut(true), - _showStyles(nullptr), _throttleState(0), - // TODO: Stop using _gfxScreen - _currentBuffer(screen->getDisplayWidth(), screen->getDisplayHeight(), nullptr), _remapOccurred(false), _frameNowVisible(false), - _screenRect(screen->getDisplayWidth(), screen->getDisplayHeight()), _overdrawThreshold(0), _palMorphIsOn(false) { - _currentBuffer.setPixels(calloc(1, screen->getDisplayWidth() * screen->getDisplayHeight())); - - for (int i = 0; i < 236; i += 2) { - _styleRanges[i] = 0; - _styleRanges[i + 1] = -1; - } - for (int i = 236; i < ARRAYSIZE(_styleRanges); ++i) { - _styleRanges[i] = 0; - } - - // TODO: Make hires detection work uniformly across all SCI engine - // versions (this flag is normally passed by SCI::MakeGraphicsMgr - // to the GraphicsMgr constructor depending upon video configuration, - // so should be handled upstream based on game configuration instead - // of here) - if (getSciVersion() >= SCI_VERSION_2_1_EARLY && _resMan->detectHires()) { - _isHiRes = true; + // QFG4 is the only SCI32 game that doesn't have a high-resolution version + if (g_sci->getGameId() == GID_QFG4) { + _isHiRes = false; } - if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { - _dissolveSequenceSeeds = dissolveSequences[0]; - _defaultDivisions = divisionsDefaults[0]; - _defaultUnknownC = unknownCDefaults[0]; + if (g_sci->getGameId() == GID_PHANTASMAGORIA) { + _currentBuffer = Buffer(630, 450, nullptr); + } else if (_isHiRes) { + _currentBuffer = Buffer(640, 480, nullptr); } else { - _dissolveSequenceSeeds = dissolveSequences[1]; - _defaultDivisions = divisionsDefaults[1]; - _defaultUnknownC = unknownCDefaults[1]; + _currentBuffer = Buffer(320, 200, nullptr); } + _currentBuffer.setPixels(calloc(1, _currentBuffer.screenWidth * _currentBuffer.screenHeight)); + _screenRect = Common::Rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight); + initGraphics(_currentBuffer.screenWidth, _currentBuffer.screenHeight, _isHiRes); switch (g_sci->getGameId()) { case GID_HOYLE5: @@ -130,20 +103,6 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd // default script width for other games is 320x200 break; } - - // TODO: Nothing in the renderer really uses this. Currently, - // the cursor renderer does, and kLocalToGlobal/kGlobalToLocal - // do, but in the real engine (1) the cursor is handled in - // frameOut, and (2) functions do a very simple lookup of the - // plane and arithmetic with the plane's gameRect. In - // principle, CoordAdjuster could be reused for - // convertGameRectToPlaneRect, but it is not super clear yet - // what the benefit would be to do that. - _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; - - // TODO: Script resolution is hard-coded per game; - // also this must be set or else the engine will crash - _coordAdjuster->setScriptsResolution(_currentBuffer.scriptWidth, _currentBuffer.scriptHeight); } GfxFrameout::~GfxFrameout() { @@ -515,22 +474,24 @@ void GfxFrameout::updatePlane(Plane &plane) { #pragma mark - #pragma mark Pics -void GfxFrameout::kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 x, const int16 y, const bool mirrorX) { +void GfxFrameout::kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 x, const int16 y, const bool mirrorX, const bool deleteDuplicate) { Plane *plane = _planes.findByObject(planeObject); if (plane == nullptr) { error("kAddPicAt: Plane %04x:%04x not found", PRINT_REG(planeObject)); } - plane->addPic(pictureId, Common::Point(x, y), mirrorX); + plane->addPic(pictureId, Common::Point(x, y), mirrorX, deleteDuplicate); } #pragma mark - #pragma mark Rendering void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &eraseRect) { -// TODO: Robot -// if (_robot != nullptr) { -// _robot.doRobot(); -// } + RobotDecoder &robotPlayer = g_sci->_video32->getRobotPlayer(); + const bool robotIsActive = robotPlayer.getStatus() != RobotDecoder::kRobotStatusUninitialized; + + if (robotIsActive) { + robotPlayer.doRobot(); + } // NOTE: The original engine allocated these as static arrays of 100 // pointers to ScreenItemList / RectList @@ -568,10 +529,9 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &eraseR drawScreenItemList(screenItemLists[i]); } -// TODO: Robot -// if (_robot != nullptr) { -// _robot->frameAlmostVisible(); -// } + if (robotIsActive) { + robotPlayer.frameAlmostVisible(); + } _palette->updateHardware(!shouldShowBits); @@ -581,10 +541,118 @@ void GfxFrameout::frameOut(const bool shouldShowBits, const Common::Rect &eraseR _frameNowVisible = true; -// TODO: Robot -// if (_robot != nullptr) { -// robot->frameNowVisible(); -// } + if (robotIsActive) { + robotPlayer.frameNowVisible(); + } +} + +void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *showStyle) { + Palette sourcePalette(_palette->getNextPalette()); + alterVmap(sourcePalette, sourcePalette, -1, styleRanges); + + int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][12].toSint16(); + + Common::Rect rect(_currentBuffer.screenWidth, _currentBuffer.screenHeight); + _showList.add(rect); + showBits(); + + // NOTE: The original engine allocated these as static arrays of 100 + // pointers to ScreenItemList / RectList + ScreenItemListList screenItemLists; + EraseListList eraseLists; + + screenItemLists.resize(_planes.size()); + eraseLists.resize(_planes.size()); + + if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) { + remapMarkRedraw(); + } + + calcLists(screenItemLists, eraseLists); + for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { + list->sort(); + } + + for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { + for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) { + (*drawItem)->screenItem->getCelObj().submitPalette(); + } + } + + _remapOccurred = _palette->updateForFrame(); + _frameNowVisible = false; + + for (PlaneList::size_type i = 0; i < _planes.size(); ++i) { + drawEraseList(eraseLists[i], *_planes[i]); + drawScreenItemList(screenItemLists[i]); + } + + Palette nextPalette(_palette->getNextPalette()); + + if (prevRoom < 1000) { + for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) { + if (styleRanges[i] == -1 || styleRanges[i] == 0) { + sourcePalette.colors[i] = nextPalette.colors[i]; + sourcePalette.colors[i].used = true; + } + } + } else { + for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) { + if (styleRanges[i] == -1 || validZeroStyle(styleRanges[i], i)) { + sourcePalette.colors[i] = nextPalette.colors[i]; + sourcePalette.colors[i].used = true; + } + } + } + + _palette->submit(sourcePalette); + _palette->updateFFrame(); + _palette->updateHardware(); + alterVmap(nextPalette, sourcePalette, 1, _transitions->_styleRanges); + + if (showStyle && showStyle->type != kShowStyleMorph) { + _transitions->processEffects(*showStyle); + } else { + showBits(); + } + + _frameNowVisible = true; + + for (PlaneList::iterator plane = _planes.begin(); plane != _planes.end(); ++plane) { + (*plane)->_redrawAllCount = getScreenCount(); + } + + if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) { + remapMarkRedraw(); + } + + calcLists(screenItemLists, eraseLists); + for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { + list->sort(); + } + + for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { + for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) { + (*drawItem)->screenItem->getCelObj().submitPalette(); + } + } + + _remapOccurred = _palette->updateForFrame(); + // NOTE: During this second loop, `_frameNowVisible = false` is + // inside the next loop in SCI2.1mid + _frameNowVisible = false; + + for (PlaneList::size_type i = 0; i < _planes.size(); ++i) { + drawEraseList(eraseLists[i], *_planes[i]); + drawScreenItemList(screenItemLists[i]); + } + + _palette->submit(nextPalette); + _palette->updateFFrame(); + _palette->updateHardware(false); + showBits(); + + _frameNowVisible = true; } /** @@ -1038,119 +1106,11 @@ void GfxFrameout::mergeToShowList(const Common::Rect &drawRect, RectList &showLi } } -void GfxFrameout::palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle) { - Palette sourcePalette(_palette->getNextPalette()); - alterVmap(sourcePalette, sourcePalette, -1, styleRanges); - - int16 prevRoom = g_sci->getEngineState()->variables[VAR_GLOBAL][12].toSint16(); - - Common::Rect rect(_screen->getDisplayWidth(), _screen->getDisplayHeight()); - _showList.add(rect); - showBits(); - - // NOTE: The original engine allocated these as static arrays of 100 - // pointers to ScreenItemList / RectList - ScreenItemListList screenItemLists; - EraseListList eraseLists; - - screenItemLists.resize(_planes.size()); - eraseLists.resize(_planes.size()); - - if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) { - remapMarkRedraw(); - } - - calcLists(screenItemLists, eraseLists); - for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { - list->sort(); - } - - for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { - for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) { - (*drawItem)->screenItem->getCelObj().submitPalette(); - } - } - - _remapOccurred = _palette->updateForFrame(); - _frameNowVisible = false; - - for (PlaneList::size_type i = 0; i < _planes.size(); ++i) { - drawEraseList(eraseLists[i], *_planes[i]); - drawScreenItemList(screenItemLists[i]); - } - - Palette nextPalette(_palette->getNextPalette()); - - if (prevRoom < 1000) { - for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) { - if (styleRanges[i] == -1 || styleRanges[i] == 0) { - sourcePalette.colors[i] = nextPalette.colors[i]; - sourcePalette.colors[i].used = true; - } - } - } else { - for (int i = 0; i < ARRAYSIZE(sourcePalette.colors); ++i) { - // TODO: Limiting range 72 to 103 is NOT present in every game - if (styleRanges[i] == -1 || (styleRanges[i] == 0 && i > 71 && i < 104)) { - sourcePalette.colors[i] = nextPalette.colors[i]; - sourcePalette.colors[i].used = true; - } - } - } - - _palette->submit(sourcePalette); - _palette->updateFFrame(); - _palette->updateHardware(); - alterVmap(nextPalette, sourcePalette, 1, _styleRanges); - - if (showStyle && showStyle->type != kShowStyleUnknown) { -// TODO: SCI2.1mid transition effects -// processEffects(); - warning("Transition %d not implemented!", showStyle->type); - } else { - showBits(); - } - - _frameNowVisible = true; - - for (PlaneList::iterator plane = _planes.begin(); plane != _planes.end(); ++plane) { - (*plane)->_redrawAllCount = getScreenCount(); - } - - if (g_sci->_gfxRemap32->getRemapCount() > 0 && _remapOccurred) { - remapMarkRedraw(); - } - - calcLists(screenItemLists, eraseLists); - for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { - list->sort(); - } - - for (ScreenItemListList::iterator list = screenItemLists.begin(); list != screenItemLists.end(); ++list) { - for (DrawList::iterator drawItem = list->begin(); drawItem != list->end(); ++drawItem) { - (*drawItem)->screenItem->getCelObj().submitPalette(); - } - } - - _remapOccurred = _palette->updateForFrame(); - // NOTE: During this second loop, `_frameNowVisible = false` is - // inside the next loop in SCI2.1mid - _frameNowVisible = false; - - for (PlaneList::size_type i = 0; i < _planes.size(); ++i) { - drawEraseList(eraseLists[i], *_planes[i]); - drawScreenItemList(screenItemLists[i]); +void GfxFrameout::showBits() { + if (!_showList.size()) { + return; } - _palette->submit(nextPalette); - _palette->updateFFrame(); - _palette->updateHardware(false); - showBits(); - - _frameNowVisible = true; -} - -void GfxFrameout::showBits() { for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) { Common::Rect rounded(**rect); // NOTE: SCI engine used BR-inclusive rects so used slightly @@ -1158,13 +1118,10 @@ void GfxFrameout::showBits() { // was always even. rounded.left &= ~1; rounded.right = (rounded.right + 1) & ~1; - - // TODO: - // _cursor->GonnaPaint(rounded); + _cursor->gonnaPaint(rounded); } - // TODO: - // _cursor->PaintStarting(); + _cursor->paintStarting(); for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) { Common::Rect rounded(**rect); @@ -1176,11 +1133,17 @@ void GfxFrameout::showBits() { byte *sourceBuffer = (byte *)_currentBuffer.getPixels() + rounded.top * _currentBuffer.screenWidth + rounded.left; + // TODO: Sometimes transition screen items generate zero-dimension + // show rectangles. Is this a bug? + if (rounded.width() == 0 || rounded.height() == 0) { + warning("Zero-dimension show rectangle ignored"); + continue; + } + g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height()); } - // TODO: - // _cursor->DonePainting(); + _cursor->donePainting(); _showList.clear(); } @@ -1233,7 +1196,6 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co } } - // NOTE: This is currBuffer->ptr in SCI engine byte *pixels = (byte *)_currentBuffer.getPixels(); for (int pixelIndex = 0, numPixels = _currentBuffer.screenWidth * _currentBuffer.screenHeight; pixelIndex < numPixels; ++pixelIndex) { @@ -1256,348 +1218,16 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co } } -void GfxFrameout::kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor) { - if (toColor > fromColor) { - return; - } - - for (int i = fromColor; i < toColor; ++i) { - _styleRanges[i] = 0; - } -} - -inline ShowStyleEntry * GfxFrameout::findShowStyleForPlane(const reg_t planeObj) const { - ShowStyleEntry *entry = _showStyles; - while (entry != nullptr) { - if (entry->plane == planeObj) { - break; - } - entry = entry->next; - } - - return entry; -} - -inline ShowStyleEntry *GfxFrameout::deleteShowStyleInternal(ShowStyleEntry *const showStyle) { - ShowStyleEntry *lastEntry = nullptr; - - for (ShowStyleEntry *testEntry = _showStyles; testEntry != nullptr; testEntry = testEntry->next) { - if (testEntry == showStyle) { - break; - } - lastEntry = testEntry; - } - - if (lastEntry == nullptr) { - _showStyles = showStyle->next; - lastEntry = _showStyles; - } else { - lastEntry->next = showStyle->next; - } - - delete[] showStyle->fadeColorRanges; - delete showStyle; - - // TODO: Verify that this is the correct entry to return - // for the loop in processShowStyles to work correctly - return lastEntry; -} - -// TODO: 10-argument version is only in SCI3; argc checks are currently wrong for this version -// and need to be fixed in future -// TODO: SQ6 does not use 'priority' (exists since SCI2) or 'blackScreen' (exists since SCI3); -// check to see if other versions use or if they are just always ignored -void GfxFrameout::kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 back, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen) { - - bool hasDivisions = false; - bool hasFadeArray = false; - - // KQ7 2.0b uses a mismatched version of the Styler script (SCI2.1early script - // for SCI2.1mid engine), so the calls it makes to kSetShowStyle are wrong and - // put `divisions` where `pFadeArray` is supposed to be - if (getSciVersion() == SCI_VERSION_2_1_MIDDLE && g_sci->getGameId() == GID_KQ7) { - hasDivisions = argc > 7; - hasFadeArray = false; - divisions = argc > 7 ? pFadeArray.toSint16() : -1; - pFadeArray = NULL_REG; - } else if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { - hasDivisions = argc > 7; - hasFadeArray = false; - } else if (getSciVersion() < SCI_VERSION_3) { - hasDivisions = argc > 8; - hasFadeArray = argc > 7; - } else { - hasDivisions = argc > 9; - hasFadeArray = argc > 8; - } - - bool isFadeUp; - int16 color; - if (back != -1) { - isFadeUp = false; - color = back; - } else { - isFadeUp = true; - color = 0; - } - - if ((getSciVersion() < SCI_VERSION_2_1_MIDDLE && type == 15) || type > 15) { - error("Illegal show style %d for plane %04x:%04x", type, PRINT_REG(planeObj)); - } - - Plane *plane = _planes.findByObject(planeObj); - if (plane == nullptr) { - error("Plane %04x:%04x is not present in active planes list", PRINT_REG(planeObj)); - } - - bool createNewEntry = true; - ShowStyleEntry *entry = findShowStyleForPlane(planeObj); - if (entry != nullptr) { - // TODO: SCI2.1early has different criteria for show style reuse - bool useExisting = true; - - if (useExisting) { - useExisting = entry->divisions == (hasDivisions ? divisions : _defaultDivisions[type]) && entry->unknownC == _defaultUnknownC[type]; - } - - if (useExisting) { - createNewEntry = false; - isFadeUp = true; - entry->currentStep = 0; - } else { - isFadeUp = true; - color = entry->color; - deleteShowStyleInternal(entry/*, true*/); - entry = nullptr; - } - } - - if (type > 0) { - if (createNewEntry) { - entry = new ShowStyleEntry; - // NOTE: SCI2.1 engine tests if allocation returned a null pointer - // but then only avoids setting currentStep if this is so. Since - // this is a nonsensical approach, we do not do that here - entry->currentStep = 0; - entry->unknownC = _defaultUnknownC[type]; - entry->processed = false; - entry->divisions = hasDivisions ? divisions : _defaultDivisions[type]; - entry->plane = planeObj; - - entry->fadeColorRanges = nullptr; - if (hasFadeArray) { - // NOTE: SCI2.1mid engine does no check to verify that an array is - // successfully retrieved, and SegMan will cause a fatal error - // if we try to use a memory segment that is not an array - SciArray<reg_t> *table = _segMan->lookupArray(pFadeArray); - - uint32 rangeCount = table->getSize(); - entry->fadeColorRangesCount = rangeCount; - - // NOTE: SCI engine code always allocates memory even if the range - // table has no entries, but this does not really make sense, so - // we avoid the allocation call in this case - if (rangeCount > 0) { - entry->fadeColorRanges = new uint16[rangeCount]; - for (size_t i = 0; i < rangeCount; ++i) { - entry->fadeColorRanges[i] = table->getValue(i).toUint16(); - } - } - } else { - entry->fadeColorRangesCount = 0; - } - } - - // NOTE: The original engine had no nullptr check and would just crash - // if it got to here - if (entry == nullptr) { - error("Cannot edit non-existing ShowStyle entry"); - } - - entry->fadeUp = isFadeUp; - entry->color = color; - entry->nextTick = g_sci->getTickCount(); - entry->type = type; - entry->animate = animate; - entry->delay = (seconds * 60 + entry->divisions - 1) / entry->divisions; - - if (entry->delay == 0) { - if (entry->fadeColorRanges != nullptr) { - delete[] entry->fadeColorRanges; - } - delete entry; - error("ShowStyle has no duration"); - } - - if (frameOutNow) { - Common::Rect frameOutRect(0, 0); - frameOut(false, frameOutRect); - } - - if (createNewEntry) { - // TODO: Implement SCI2.1early and SCI3 - entry->next = _showStyles; - _showStyles = entry; - } - } -} - -// NOTE: Different version of SCI engine support different show styles -// SCI2 implements 0, 1/3/5/7/9, 2/4/6/8/10, 11, 12, 13, 14 -// SCI2.1 implements 0, 1/2/3/4/5/6/7/8/9/10/11/12/15, 13, 14 -// SCI3 implements 0, 1/3/5/7/9, 2/4/6/8/10, 11, 12/15, 13, 14 -// TODO: Sierra code needs to be replaced with code that uses the -// computed entry->delay property instead of just counting divisors, -// as the latter is machine-speed-dependent and leads to wrong -// transition speeds -void GfxFrameout::processShowStyles() { - uint32 now = g_sci->getTickCount(); - - bool continueProcessing; - - // TODO: Change to bool? Engine uses inc to set the value to true, - // but there does not seem to be any reason to actually count how - // many times it was set - int doFrameOut; - do { - continueProcessing = false; - doFrameOut = 0; - ShowStyleEntry *showStyle = _showStyles; - while (showStyle != nullptr) { - bool retval = false; - - if (!showStyle->animate) { - ++doFrameOut; - } - - if (showStyle->nextTick < now || !showStyle->animate) { - // TODO: Different versions of SCI use different processors! - // This is the SQ6/KQ7/SCI2.1mid table. - switch (showStyle->type) { - case kShowStyleNone: { - retval = processShowStyleNone(showStyle); - break; - } - case kShowStyleHShutterOut: - case kShowStyleVShutterOut: - case kShowStyleWipeLeft: - case kShowStyleWipeUp: - case kShowStyleIrisOut: - case kShowStyleHShutterIn: - case kShowStyleVShutterIn: - case kShowStyleWipeRight: - case kShowStyleWipeDown: - case kShowStyleIrisIn: - case kShowStyle11: - case kShowStyle12: - case kShowStyleUnknown: { - retval = processShowStyleMorph(showStyle); - break; - } - case kShowStyleFadeOut: { - retval = processShowStyleFade(-1, showStyle); - break; - } - case kShowStyleFadeIn: { - retval = processShowStyleFade(1, showStyle); - break; - } - } - } - - if (!retval) { - continueProcessing = true; - } - - if (retval && showStyle->processed) { - showStyle = deleteShowStyleInternal(showStyle); - } else { - showStyle = showStyle->next; - } - } - - if (g_engine->shouldQuit()) { - return; - } - - if (doFrameOut) { - frameOut(true); - - // TODO: Transitions without the “animate†flag are too - // fast, but the throttle value is arbitrary. Someone on - // real hardware probably needs to test what the actual - // speed of these transitions should be - throttle(); - } - } while(continueProcessing && doFrameOut); -} - -bool GfxFrameout::processShowStyleNone(ShowStyleEntry *const showStyle) { - if (showStyle->fadeUp) { - _palette->setFade(100, 0, 255); - } else { - _palette->setFade(0, 0, 255); - } - - showStyle->processed = true; - return true; -} - -bool GfxFrameout::processShowStyleMorph(ShowStyleEntry *const showStyle) { - palMorphFrameOut(_styleRanges, showStyle); - showStyle->processed = true; - return true; -} - -// TODO: Normalise use of 'entry' vs 'showStyle' -bool GfxFrameout::processShowStyleFade(const int direction, ShowStyleEntry *const showStyle) { - bool unchanged = true; - if (showStyle->currentStep < showStyle->divisions) { - int percent; - if (direction <= 0) { - percent = showStyle->divisions - showStyle->currentStep - 1; - } else { - percent = showStyle->currentStep; - } - - percent *= 100; - percent /= showStyle->divisions - 1; - - if (showStyle->fadeColorRangesCount > 0) { - for (int i = 0, len = showStyle->fadeColorRangesCount; i < len; i += 2) { - _palette->setFade(percent, showStyle->fadeColorRanges[i], showStyle->fadeColorRanges[i + 1]); - } - } else { - _palette->setFade(percent, 0, 255); - } - - ++showStyle->currentStep; - showStyle->nextTick += showStyle->delay; - unchanged = false; - } - - if (showStyle->currentStep >= showStyle->divisions && unchanged) { - if (direction > 0) { - showStyle->processed = true; - } - - return true; - } - - return false; -} - void GfxFrameout::kernelFrameOut(const bool shouldShowBits) { - if (_showStyles != nullptr) { - processShowStyles(); + if (_transitions->hasShowStyles()) { + _transitions->processShowStyles(); } else if (_palMorphIsOn) { - palMorphFrameOut(_styleRanges, nullptr); + palMorphFrameOut(_transitions->_styleRanges, nullptr); _palMorphIsOn = false; } else { -// TODO: Window scroll -// if (g_PlaneScroll) { -// processScrolls(); -// } + if (_transitions->hasScrolls()) { + _transitions->processScrolls(); + } frameOut(shouldShowBits); } @@ -1609,10 +1239,10 @@ void GfxFrameout::throttle() { if (_throttleFrameOut) { uint8 throttleTime; if (_throttleState == 2) { - throttleTime = 17; + throttleTime = 16; _throttleState = 0; } else { - throttleTime = 16; + throttleTime = 17; ++_throttleState; } @@ -1621,6 +1251,38 @@ void GfxFrameout::throttle() { } } +void GfxFrameout::showRect(const Common::Rect &rect) { + if (!rect.isEmpty()) { + _showList.clear(); + _showList.add(rect); + showBits(); + } +} + +void GfxFrameout::shakeScreen(int16 numShakes, const ShakeDirection direction) { + if (direction & kShakeHorizontal) { + // Used by QFG4 room 750 + warning("TODO: Horizontal shake not implemented"); + return; + } + + while (numShakes--) { + if (direction & kShakeVertical) { + g_system->setShakePos(_isHiRes ? 8 : 4); + } + + g_system->updateScreen(); + g_sci->getEngineState()->wait(3); + + if (direction & kShakeVertical) { + g_system->setShakePos(0); + } + + g_system->updateScreen(); + g_sci->getEngineState()->wait(3); + } +} + #pragma mark - #pragma mark Mouse cursor @@ -1679,7 +1341,7 @@ bool GfxFrameout::isOnMe(const ScreenItem &screenItem, const Plane &plane, const return true; } -void GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { +bool GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { const reg_t planeObject = readSelector(_segMan, screenItemObject, SELECTOR(plane)); Plane *plane = _planes.findByObject(planeObject); @@ -1689,7 +1351,7 @@ void GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject); if (screenItem == nullptr) { - error("kSetNowSeen: Screen item %04x:%04x not found in plane %04x:%04x", PRINT_REG(screenItemObject), PRINT_REG(planeObject)); + return false; } Common::Rect result = screenItem->getNowSeenRect(*plane); @@ -1697,6 +1359,7 @@ void GfxFrameout::kernelSetNowSeen(const reg_t screenItemObject) const { writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsTop), result.top); writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsRight), result.right - 1); writeSelectorValue(_segMan, screenItemObject, SELECTOR(nsBottom), result.bottom - 1); + return true; } void GfxFrameout::remapMarkRedraw() { diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 99658ede6a..e4caffd9e5 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -27,130 +27,12 @@ #include "sci/graphics/screen_item32.h" namespace Sci { -// TODO: Don't do this this way -int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]); - -// TODO: Verify display styles and adjust names appropriately for -// types 1 through 12 & 15 (others are correct) -// Names should be: -// * VShutterIn, VShutterOut -// * HShutterIn, HShutterOut -// * WipeLeft, WipeRight, WipeDown, WipeUp -// * PixelDissolve -// * ShutDown and Kill? (and Plain and Fade?) -enum ShowStyleType /* : uint8 */ { - kShowStyleNone = 0, - kShowStyleHShutterOut = 1, - kShowStyleHShutterIn = 2, - kShowStyleVShutterOut = 3, - kShowStyleVShutterIn = 4, - kShowStyleWipeLeft = 5, - kShowStyleWipeRight = 6, - kShowStyleWipeUp = 7, - kShowStyleWipeDown = 8, - kShowStyleIrisOut = 9, - kShowStyleIrisIn = 10, - kShowStyle11 = 11, - kShowStyle12 = 12, - kShowStyleFadeOut = 13, - kShowStyleFadeIn = 14, - // TODO: Only in SCI3 - kShowStyleUnknown = 15 -}; - -/** - * Show styles represent transitions applied to draw planes. - * One show style per plane can be active at a time. - */ -struct ShowStyleEntry { - /** - * The ID of the plane this show style belongs to. - * In SCI2.1mid (at least SQ6), per-plane transitions - * were removed and a single plane ID is used. - */ - reg_t plane; - - /** - * The type of the transition. - */ - ShowStyleType type; - - // TODO: This name is probably incorrect - bool fadeUp; - - /** - * The number of steps for the show style. - */ - int16 divisions; - - // NOTE: This property exists from SCI2 through at least - // SCI2.1mid but is never used in the actual processing - // of the styles? - int unknownC; - - /** - * The color used by transitions that draw CelObjColor - * screen items. -1 for transitions that do not draw - * screen items. - */ - int16 color; - - // TODO: Probably uint32 - // TODO: This field probably should be used in order to - // provide time-accurate processing of show styles. In the - // actual SCI engine (at least 2–2.1mid) it appears that - // style transitions are drawn “as fast as possibleâ€, one - // step per loop, even though this delay field exists - int delay; - - // TODO: Probably bool, but never seems to be true? - int animate; - - /** - * The wall time at which the next step of the animation - * should execute. - */ - uint32 nextTick; - - /** - * During playback of the show style, the current step - * (out of divisions). - */ - int currentStep; - - /** - * The next show style. - */ - ShowStyleEntry *next; - - /** - * Whether or not this style has finished running and - * is ready for disposal. - */ - bool processed; - - // - // Engine specific properties for SCI2.1mid through SCI3 - // - - /** - * The number of entries in the fadeColorRanges array. - */ - uint8 fadeColorRangesCount; - - /** - * A pointer to an dynamically sized array of palette - * indexes, in the order [ fromColor, toColor, ... ]. - * Only colors within this range are transitioned. - */ - uint16 *fadeColorRanges; -}; - typedef Common::Array<DrawList> ScreenItemListList; typedef Common::Array<RectList> EraseListList; -class GfxCoordAdjuster32; -class GfxScreen; +class GfxCursor32; +class GfxTransitions32; +struct PlaneShowStyle; /** * Frameout class, kFrameout and relevant functions for SCI32 games. @@ -158,17 +40,16 @@ class GfxScreen; */ class GfxFrameout { private: - bool _isHiRes; - GfxCoordAdjuster32 *_coordAdjuster; + GfxCursor32 *_cursor; GfxPalette32 *_palette; - ResourceManager *_resMan; - GfxScreen *_screen; SegManager *_segMan; public: - GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette32 *palette); + GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor); ~GfxFrameout(); + bool _isHiRes; + void clear(); void syncWithScripts(bool addElements); // this is what Game::restore does, only needed when our ScummVM dialogs are patched in void run(); @@ -229,7 +110,7 @@ public: void kernelAddScreenItem(const reg_t object); void kernelUpdateScreenItem(const reg_t object); void kernelDeleteScreenItem(const reg_t object); - void kernelSetNowSeen(const reg_t screenItemObject) const; + bool kernelSetNowSeen(const reg_t screenItemObject) const; #pragma mark - #pragma mark Planes @@ -284,40 +165,13 @@ public: #pragma mark - #pragma mark Pics public: - void kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 pictureX, const int16 pictureY, const bool mirrorX); - -#pragma mark - - - // TODO: Remap-related? - void kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor); - -#pragma mark - -#pragma mark Transitions -private: - int *_dissolveSequenceSeeds; - int16 *_defaultDivisions; - int16 *_defaultUnknownC; - - /** - * TODO: Documentation - */ - ShowStyleEntry *_showStyles; - - inline ShowStyleEntry *findShowStyleForPlane(const reg_t planeObj) const; - inline ShowStyleEntry *deleteShowStyleInternal(ShowStyleEntry *const showStyle); - void processShowStyles(); - bool processShowStyleNone(ShowStyleEntry *showStyle); - bool processShowStyleMorph(ShowStyleEntry *showStyle); - bool processShowStyleFade(const int direction, ShowStyleEntry *showStyle); - -public: - // NOTE: This signature is taken from SCI3 Phantasmagoria 2 - // and is valid for all implementations of SCI32 - void kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 direction, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen); + void kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 pictureX, const int16 pictureY, const bool mirrorX, const bool deleteDuplicate); #pragma mark - #pragma mark Rendering private: + GfxTransitions32 *_transitions; + /** * State tracker to provide more accurate 60fps * video throttling. @@ -325,11 +179,6 @@ private: uint8 _throttleState; /** - * TODO: Documentation - */ - int8 _styleRanges[256]; - - /** * The internal display pixel buffer. During frameOut, * this buffer is drawn into according to the draw and * erase rects calculated by `calcLists`, then drawn out @@ -346,13 +195,6 @@ private: bool _remapOccurred; /** - * Whether or not the data in the current buffer is what - * is visible to the user. During rendering updates, - * this flag is set to false. - */ - bool _frameNowVisible; - - /** * TODO: Document * TODO: Depending upon if the engine ever modifies this * rect, it may be stupid to store it separately instead @@ -428,18 +270,44 @@ private: void mergeToShowList(const Common::Rect &drawRect, RectList &showList, const int overdrawThreshold); /** - * TODO: Documentation - */ - void palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle); - - /** * Writes the internal frame buffer out to hardware and * clears the show list. */ void showBits(); + /** + * Validates whether the given palette index in the + * style range should copy a color from the next + * palette to the source palette during a palette + * morph operation. + */ + inline bool validZeroStyle(const uint8 style, const int i) const { + if (style != 0) { + return false; + } + + // TODO: Cannot check Shivers or MGDX until those executables can be + // unwrapped + switch (g_sci->getGameId()) { + case GID_KQ7: + case GID_PHANTASMAGORIA: + case GID_SQ6: + return (i > 71 && i < 104); + break; + default: + return true; + } + } + public: /** + * Whether or not the data in the current buffer is what + * is visible to the user. During rendering updates, + * this flag is set to false. + */ + bool _frameNowVisible; + + /** * Whether palMorphFrameOut should be used instead of * frameOut for rendering. Used by kMorphOn to * explicitly enable palMorphFrameOut for one frame. @@ -467,6 +335,11 @@ public: void frameOut(const bool shouldShowBits, const Common::Rect &eraseRect = Common::Rect()); /** + * TODO: Documentation + */ + void palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *showStyle); + + /** * Modifies the raw pixel data for the next frame with * new palette indexes based on matched style ranges. */ @@ -484,6 +357,17 @@ public: return 1; }; + /** + * Draws a portion of the current screen buffer to + * hardware. Used to display show styles in SCI2.1mid+. + */ + void showRect(const Common::Rect &rect); + + /** + * Shakes the screen. + */ + void shakeScreen(const int16 numShakes, const ShakeDirection direction); + #pragma mark - #pragma mark Mouse cursor private: diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h index 3fcc83c5e2..1da3749c90 100644 --- a/engines/sci/graphics/helpers.h +++ b/engines/sci/graphics/helpers.h @@ -40,8 +40,10 @@ namespace Sci { #define MAX_CACHED_FONTS 20 #define MAX_CACHED_VIEWS 50 -#define SCI_SHAKE_DIRECTION_VERTICAL 1 -#define SCI_SHAKE_DIRECTION_HORIZONTAL 2 +enum ShakeDirection { + kShakeVertical = 1, + kShakeHorizontal = 2 +}; typedef int GuiResourceId; // is a resource-number and -1 means no parameter given diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 6004e9ce7a..91817d4060 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -41,7 +41,7 @@ namespace Sci { -GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio) +GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster16 *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio) : _resMan(resMan), _segMan(segMan), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions), _audio(audio), _EGAdrawingVisualize(false) { diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 317388b2df..6fc9cbbdfc 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -36,7 +36,7 @@ class GfxView; */ class GfxPaint16 { public: - GfxPaint16(ResourceManager *resMan, SegManager *segMan, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); + GfxPaint16(ResourceManager *resMan, SegManager *segMan, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster16 *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); ~GfxPaint16(); void init(GfxAnimate *animate, GfxText16 *text16); @@ -91,7 +91,7 @@ private: GfxAnimate *_animate; GfxCache *_cache; GfxPorts *_ports; - GfxCoordAdjuster *_coordAdjuster; + GfxCoordAdjuster16 *_coordAdjuster; GfxScreen *_screen; GfxPalette *_palette; GfxText16 *_text16; diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index 74eb1629d0..338b70901e 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -37,11 +37,12 @@ reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &st } Common::Rect gameRect; - BitmapResource bitmap = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + reg_t bitmapId = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + SciBitmap &bitmap = *_segMan->lookupBitmap(bitmapId); CelInfo32 celInfo; celInfo.type = kCelTypeMem; - celInfo.bitmap = bitmap.getObject(); + celInfo.bitmap = bitmapId; // SSCI stores the line color on `celInfo`, even though // this is not a `kCelTypeColor`, as a hack so that // `kUpdateLine` can get the originally used color @@ -59,10 +60,10 @@ reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &st void GfxPaint32::kernelUpdateLine(ScreenItem *screenItem, Plane *plane, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness) { Common::Rect gameRect; - BitmapResource bitmap = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + reg_t bitmapId = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); - _segMan->freeHunkEntry(screenItem->_celInfo.bitmap); - screenItem->_celInfo.bitmap = bitmap.getObject(); + _segMan->freeBitmap(screenItem->_celInfo.bitmap); + screenItem->_celInfo.bitmap = bitmapId; screenItem->_celInfo.color = color; screenItem->_position = startPoint; screenItem->_priority = priority; @@ -80,7 +81,7 @@ void GfxPaint32::kernelDeleteLine(const reg_t screenItemObject, const reg_t plan return; } - _segMan->freeHunkEntry(screenItem->_celInfo.bitmap); + _segMan->freeBitmap(screenItem->_celInfo.bitmap); g_sci->_gfxFrameout->deleteScreenItem(*screenItem, *plane); } @@ -116,8 +117,8 @@ void GfxPaint32::plotter(int x, int y, int color, void *data) { } } -BitmapResource GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, uint16 pattern, uint8 thickness, Common::Rect &outRect) { - const uint8 skipColor = color != 250 ? 250 : 0; +reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, uint16 pattern, uint8 thickness, Common::Rect &outRect) { + const uint8 skipColor = color != kDefaultSkipColor ? kDefaultSkipColor : 0; // Thickness is expected to be 2n+1 thickness = ((MAX((uint8)1, thickness) - 1) | 1); @@ -128,7 +129,8 @@ BitmapResource GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const outRect.right = (startPoint.x > endPoint.x ? startPoint.x : endPoint.x) + halfThickness + 1; outRect.bottom = (startPoint.y > endPoint.y ? startPoint.y : endPoint.y) + halfThickness + 1; - BitmapResource bitmap(_segMan, outRect.width(), outRect.height(), skipColor, 0, 0, g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, 0, false); + reg_t bitmapId; + SciBitmap &bitmap = *_segMan->allocateBitmap(&bitmapId, outRect.width(), outRect.height(), skipColor, 0, 0, g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, 0, false, true); byte *pixels = bitmap.getPixels(); memset(pixels, skipColor, bitmap.getWidth() * bitmap.getHeight()); @@ -174,7 +176,7 @@ BitmapResource GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Graphics::drawThickLine2(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, thickness, color, plotter, &properties); } - return bitmap; + return bitmapId; } diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h index 6d5a957fcd..3c3b7b4343 100644 --- a/engines/sci/graphics/paint32.h +++ b/engines/sci/graphics/paint32.h @@ -24,8 +24,8 @@ #define SCI_GRAPHICS_PAINT32_H namespace Sci { -class BitmapResource; class Plane; +class SciBitmap; class ScreenItem; class SegManager; @@ -54,7 +54,7 @@ public: private: typedef struct { - BitmapResource *bitmap; + SciBitmap *bitmap; bool pattern[16]; uint8 patternIndex; bool solid; @@ -64,7 +64,7 @@ private: static void plotter(int x, int y, int color, void *data); - BitmapResource makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness, Common::Rect &outRect); + reg_t makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness, Common::Rect &outRect); }; } // End of namespace Sci diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp index 2a98c237b0..c7098bc3e4 100644 --- a/engines/sci/graphics/palette32.cpp +++ b/engines/sci/graphics/palette32.cpp @@ -282,10 +282,16 @@ void GfxPalette32::updateHardware(const bool updateScreen) { bpal[i * 3 + 2] = _currentPalette.colors[i].b; } - // The last color must always be white - bpal[255 * 3 ] = 255; - bpal[255 * 3 + 1] = 255; - bpal[255 * 3 + 2] = 255; + if (g_sci->getPlatform() != Common::kPlatformMacintosh) { + // The last color must always be white + bpal[255 * 3 ] = 255; + bpal[255 * 3 + 1] = 255; + bpal[255 * 3 + 2] = 255; + } else { + bpal[255 * 3 ] = 0; + bpal[255 * 3 + 1] = 0; + bpal[255 * 3 + 2] = 0; + } g_system->getPaletteManager()->setPalette(bpal, 0, 256); if (updateScreen) { diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index 2eab391afd..0025b24476 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -35,7 +35,7 @@ namespace Sci { //#define DEBUG_PICTURE_DRAW -GfxPicture::GfxPicture(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize) +GfxPicture::GfxPicture(ResourceManager *resMan, GfxCoordAdjuster16 *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize) : _resMan(resMan), _coordAdjuster(coordAdjuster), _ports(ports), _screen(screen), _palette(palette), _resourceId(resourceId), _EGAdrawingVisualize(EGAdrawingVisualize) { assert(resourceId != -1); initData(resourceId); diff --git a/engines/sci/graphics/picture.h b/engines/sci/graphics/picture.h index 942fa0f107..1be1ae3004 100644 --- a/engines/sci/graphics/picture.h +++ b/engines/sci/graphics/picture.h @@ -38,7 +38,7 @@ enum { class GfxPorts; class GfxScreen; class GfxPalette; -class GfxCoordAdjuster; +class GfxCoordAdjuster16; class ResourceManager; class Resource; @@ -48,7 +48,7 @@ class Resource; */ class GfxPicture { public: - GfxPicture(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize = false); + GfxPicture(ResourceManager *resMan, GfxCoordAdjuster16 *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize = false); ~GfxPicture(); GuiResourceId getResourceId(); @@ -84,7 +84,7 @@ private: void vectorPatternTexturedCircle(Common::Rect box, byte size, byte color, byte prio, byte control, byte texture); ResourceManager *_resMan; - GfxCoordAdjuster *_coordAdjuster; + GfxCoordAdjuster16 *_coordAdjuster; GfxPorts *_ports; GfxScreen *_screen; GfxPalette *_palette; diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp index aa629e4081..1cd88d667b 100644 --- a/engines/sci/graphics/plane32.cpp +++ b/engines/sci/graphics/plane32.cpp @@ -194,11 +194,12 @@ void Plane::addPicInternal(const GuiResourceId pictureId, const Common::Point *p _type = transparent ? kPlaneTypeTransparentPicture : kPlaneTypePicture; } -void Plane::addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX) { - deletePic(pictureId); +GuiResourceId Plane::addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX, const bool deleteDuplicate) { + if (deleteDuplicate) { + deletePic(pictureId); + } addPicInternal(pictureId, &position, mirrorX); - // NOTE: In SCI engine this method returned the pictureId of the - // plane, but this return value was never used + return _pictureId; } void Plane::changePic() { @@ -247,6 +248,8 @@ void Plane::deleteAllPics() { #pragma mark - #pragma mark Plane - Rendering +extern int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]); + void Plane::breakDrawListByPlanes(DrawList &drawList, const PlaneList &planeList) const { const int nextPlaneIndex = planeList.findIndexByObject(_object) + 1; const PlaneList::size_type planeCount = planeList.size(); diff --git a/engines/sci/graphics/plane32.h b/engines/sci/graphics/plane32.h index 3981a2b319..964d20ca12 100644 --- a/engines/sci/graphics/plane32.h +++ b/engines/sci/graphics/plane32.h @@ -336,14 +336,6 @@ private: /** * Marks all screen items to be deleted that are within - * this plane and match the given picture ID, then sets - * the picture ID of the plane to the new picture ID - * without adding any screen items. - */ - void deletePic(const GuiResourceId oldPictureId, const GuiResourceId newPictureId); - - /** - * Marks all screen items to be deleted that are within * this plane and are picture cels. */ void deleteAllPics(); @@ -355,7 +347,7 @@ public: * new picture resource to the plane at the given * position. */ - void addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX); + GuiResourceId addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX, const bool deleteDuplicate = true); /** * If the plane is a picture plane, re-adds all cels @@ -364,6 +356,14 @@ public: */ void changePic(); + /** + * Marks all screen items to be deleted that are within + * this plane and match the given picture ID, then sets + * the picture ID of the plane to the new picture ID + * without adding any screen items. + */ + void deletePic(const GuiResourceId oldPictureId, const GuiResourceId newPictureId); + #pragma mark - #pragma mark Plane - Rendering private: diff --git a/engines/sci/graphics/remap32.h b/engines/sci/graphics/remap32.h index 5f629d733e..1b9628c7be 100644 --- a/engines/sci/graphics/remap32.h +++ b/engines/sci/graphics/remap32.h @@ -325,7 +325,12 @@ public: */ inline bool remapEnabled(uint8 color) const { const uint8 index = _remapEndColor - color; - assert(index < _remaps.size()); + // At least KQ7 DOS uses remap colors that are outside the valid remap + // range; in these cases, just treat those pixels as skip pixels (which + // is how they would be treated in SSCI) + if (index >= _remaps.size()) { + return false; + } return (_remaps[index]._type != kRemapNone); } diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index c977a93817..601ab9f09f 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -53,12 +53,6 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { if ((g_sci->getPlatform() == Common::kPlatformWindows) || (g_sci->forceHiresGraphics())) { if (g_sci->getGameId() == GID_KQ6) _upscaledHires = GFX_SCREEN_UPSCALED_640x440; -#ifdef ENABLE_SCI32 - if (g_sci->getGameId() == GID_GK1) - _upscaledHires = GFX_SCREEN_UPSCALED_640x480; - if (g_sci->getGameId() == GID_PQ4) - _upscaledHires = GFX_SCREEN_UPSCALED_640x480; -#endif } // Japanese versions of games use hi-res font on upscaled version of the game. @@ -90,28 +84,11 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { } } -#ifdef ENABLE_SCI32 - // GK1 Mac uses a 640x480 resolution too - if (g_sci->getPlatform() == Common::kPlatformMacintosh) { - if (g_sci->getGameId() == GID_GK1) - _upscaledHires = GFX_SCREEN_UPSCALED_640x480; - } -#endif - if (_resMan->detectHires()) { _scriptWidth = 640; _scriptHeight = 480; } -#ifdef ENABLE_SCI32 - // Phantasmagoria 1 effectively outputs 630x450 - // Coordinate translation has to use this resolution as well - if (g_sci->getGameId() == GID_PHANTASMAGORIA) { - _width = 630; - _height = 450; - } -#endif - // if not yet set, set those to script-width/height if (!_width) _width = _scriptWidth; @@ -632,13 +609,13 @@ void GfxScreen::setVerticalShakePos(uint16 shakePos) { void GfxScreen::kernelShakeScreen(uint16 shakeCount, uint16 directions) { while (shakeCount--) { - if (directions & SCI_SHAKE_DIRECTION_VERTICAL) + if (directions & kShakeVertical) setVerticalShakePos(10); // TODO: horizontal shakes g_system->updateScreen(); g_sci->getEngineState()->wait(3); - if (directions & SCI_SHAKE_DIRECTION_VERTICAL) + if (directions & kShakeVertical) setVerticalShakePos(0); g_system->updateScreen(); diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp index 7383dc222e..f4ed269265 100644 --- a/engines/sci/graphics/screen_item32.cpp +++ b/engines/sci/graphics/screen_item32.cpp @@ -178,7 +178,9 @@ void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const boo const uint8 loopCount = view->data[2]; const uint8 loopSize = view->data[12]; - if (_celInfo.loopNo >= loopCount) { + // loopNo is set to be an unsigned integer in SSCI, so if it's a + // negative value, it'll be fixed accordingly + if ((uint16)_celInfo.loopNo >= loopCount) { const int maxLoopNo = loopCount - 1; _celInfo.loopNo = maxLoopNo; writeSelectorValue(segMan, object, SELECTOR(loop), maxLoopNo); @@ -189,8 +191,11 @@ void ScreenItem::setFromObject(SegManager *segMan, const reg_t object, const boo if (seekEntry != -1) { loopData = view->data + headerSize + (seekEntry * loopSize); } + + // celNo is set to be an unsigned integer in SSCI, so if it's a + // negative value, it'll be fixed accordingly const uint8 celCount = loopData[2]; - if (_celInfo.celNo >= celCount) { + if ((uint16)_celInfo.celNo >= celCount) { const int maxCelNo = celCount - 1; _celInfo.celNo = maxCelNo; writeSelectorValue(segMan, object, SELECTOR(cel), maxCelNo); diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h index 3d9d5ef3d7..4221c0ea52 100644 --- a/engines/sci/graphics/screen_item32.h +++ b/engines/sci/graphics/screen_item32.h @@ -31,6 +31,7 @@ namespace Sci { enum ScaleSignals32 { kScaleSignalNone = 0, + // TODO: rename to 'manual' kScaleSignalDoScaling32 = 1, // enables scaling when drawing that cel (involves scaleX and scaleY) kScaleSignalUseVanishingPoint = 2, // TODO: Is this actually a thing? I have not seen it and diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index b0f2c52791..cb6e614657 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -633,7 +633,7 @@ reg_t GfxText16::allocAndFillReferenceRectArray() { if (rectCount) { reg_t rectArray; byte *rectArrayPtr = g_sci->getEngineState()->_segMan->allocDynmem(4 * 2 * (rectCount + 1), "text code reference rects", &rectArray); - GfxCoordAdjuster *coordAdjuster = g_sci->_gfxCoordAdjuster; + GfxCoordAdjuster16 *coordAdjuster = g_sci->_gfxCoordAdjuster; for (uint curRect = 0; curRect < rectCount; curRect++) { coordAdjuster->kernelLocalToGlobal(_codeRefRects[curRect].left, _codeRefRects[curRect].top); coordAdjuster->kernelLocalToGlobal(_codeRefRects[curRect].right, _codeRefRects[curRect].bottom); diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 277e6e93d0..f81d50946b 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -59,7 +59,7 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts) : } } -reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const bool dimmed, const bool doScaling) { +reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const bool dimmed, const bool doScaling, const bool gc) { _borderColor = borderColor; _text = text; @@ -96,8 +96,7 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect _textRect = Common::Rect(); } - BitmapResource bitmap(_segMan, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false); - _bitmap = bitmap.getObject(); + _segMan->allocateBitmap(&_bitmap, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false, gc); erase(bitmapRect, false); @@ -109,7 +108,7 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect return _bitmap; } -reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed) { +reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, const bool gc) { _borderColor = borderColor; _text = text; _textRect = rect; @@ -135,8 +134,7 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect & _textRect = Common::Rect(); } - BitmapResource bitmap(_segMan, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false); - _bitmap = bitmap.getObject(); + SciBitmap &bitmap = *_segMan->allocateBitmap(&_bitmap, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false, gc); // NOTE: The engine filled the bitmap pixels with 11 here, which is silly // because then it just erased the bitmap using the skip color. So we don't @@ -180,8 +178,8 @@ void GfxText32::setFont(const GuiResourceId fontId) { void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling) { Common::Rect targetRect = doScaling ? scaleRect(rect) : rect; - byte *bitmap = _segMan->getHunkPointer(_bitmap); - byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28) + rect.top * _width + rect.left; + SciBitmap &bitmap = *_segMan->lookupBitmap(_bitmap); + byte *pixels = bitmap.getPixels() + rect.top * _width + rect.left; // NOTE: Not fully disassembled, but this should be right int16 rectWidth = targetRect.width(); @@ -210,8 +208,8 @@ void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint } void GfxText32::drawChar(const char charIndex) { - byte *bitmap = _segMan->getHunkPointer(_bitmap); - byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28); + SciBitmap &bitmap = *_segMan->lookupBitmap(_bitmap); + byte *pixels = bitmap.getPixels(); _font->drawToBuffer(charIndex, _drawPosition.y, _drawPosition.x, _foreColor, _dimmed, pixels, _width, _height); _drawPosition.x += _font->getCharWidth(charIndex); @@ -328,14 +326,14 @@ void GfxText32::drawText(const uint index, uint length) { } } -void GfxText32::invertRect(const reg_t bitmap, int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling) { +void GfxText32::invertRect(const reg_t bitmapId, int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling) { Common::Rect targetRect = rect; if (doScaling) { bitmapStride = bitmapStride * _scaledWidth / g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; targetRect = scaleRect(rect); } - byte *bitmapData = _segMan->getHunkPointer(bitmap); + SciBitmap &bitmap = *_segMan->lookupBitmap(bitmapId); // NOTE: SCI code is super weird here; it seems to be trying to look at the // entire size of the bitmap including the header, instead of just the pixel @@ -345,14 +343,14 @@ void GfxText32::invertRect(const reg_t bitmap, int16 bitmapStride, const Common: // function was never updated to match? Or maybe they exploit the // configurable stride length somewhere else to do stair stepping inverts... uint32 invertSize = targetRect.height() * bitmapStride + targetRect.width(); - uint32 bitmapSize = READ_SCI11ENDIAN_UINT32(bitmapData + 12); + uint32 bitmapSize = bitmap.getDataSize(); if (invertSize >= bitmapSize) { error("InvertRect too big: %u >= %u", invertSize, bitmapSize); } // NOTE: Actual engine just added the bitmap header size hardcoded here - byte *pixel = bitmapData + READ_SCI11ENDIAN_UINT32(bitmapData + 28) + bitmapStride * targetRect.top + targetRect.left; + byte *pixel = bitmap.getPixels() + bitmapStride * targetRect.top + targetRect.left; int16 stride = bitmapStride - targetRect.width(); int16 targetHeight = targetRect.height(); @@ -615,7 +613,7 @@ Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth, void GfxText32::erase(const Common::Rect &rect, const bool doScaling) { Common::Rect targetRect = doScaling ? scaleRect(rect) : rect; - BitmapResource bitmap(_bitmap); + SciBitmap &bitmap = *_segMan->lookupBitmap(_bitmap); bitmap.getBuffer().fillRect(targetRect, _backColor); } @@ -652,7 +650,7 @@ int16 GfxText32::getTextCount(const Common::String &text, const uint index, cons } void GfxText32::scrollLine(const Common::String &lineText, int numLines, uint8 color, TextAlign align, GuiResourceId fontId, ScrollDirection dir) { - BitmapResource bmr(_bitmap); + SciBitmap &bmr = *_segMan->lookupBitmap(_bitmap); byte *pixels = bmr.getPixels(); int h = _font->getHeight(); diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index a61760dd87..44bd48afd5 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -42,206 +42,6 @@ enum ScrollDirection { kScrollDown }; -enum BitmapFlags { - kBitmapRemap = 2 -}; - -#define BITMAP_PROPERTY(size, property, offset)\ -inline uint##size get##property() const {\ - return READ_SCI11ENDIAN_UINT##size(_bitmap + (offset));\ -}\ -inline void set##property(uint##size value) {\ - WRITE_SCI11ENDIAN_UINT##size(_bitmap + (offset), (value));\ -} - -/** - * A convenience class for creating and modifying in-memory - * bitmaps. - */ -class BitmapResource { - byte *_bitmap; - reg_t _object; - Buffer _buffer; - - /** - * Gets the size of the bitmap header for the current - * engine version. - */ - static inline uint16 getBitmapHeaderSize() { - // TODO: These values are accurate for each engine, but there may be no reason - // to not simply just always use size 40, since SCI2.1mid does not seem to - // actually store any data above byte 40, and SCI2 did not allow bitmaps with - // scaling resolutions other than the default (320x200). Perhaps SCI3 used - // the extra bytes, or there is some reason why they tried to align the header - // size with other headers like pic headers? -// uint32 bitmapHeaderSize; -// if (getSciVersion() >= SCI_VERSION_2_1_MIDDLE) { -// bitmapHeaderSize = 46; -// } else if (getSciVersion() == SCI_VERSION_2_1_EARLY) { -// bitmapHeaderSize = 40; -// } else { -// bitmapHeaderSize = 36; -// } -// return bitmapHeaderSize; - return 46; - } - - /** - * Gets the byte size of a bitmap with the given width - * and height. - */ - static inline uint32 getBitmapSize(const uint16 width, const uint16 height) { - return width * height + getBitmapHeaderSize(); - } - -public: - /** - * Create a bitmap resource for an existing bitmap. - * Ownership of the bitmap is retained by the caller. - */ - inline BitmapResource(reg_t bitmap) : - _bitmap(g_sci->getEngineState()->_segMan->getHunkPointer(bitmap)), - _object(bitmap) { - if (_bitmap == nullptr || getUncompressedDataOffset() != getBitmapHeaderSize()) { - error("Invalid Text bitmap %04x:%04x", PRINT_REG(bitmap)); - } - - _buffer = Buffer(getWidth(), getHeight(), getPixels()); - } - - /** - * Allocates and initialises a new bitmap in the given - * segment manager. - */ - inline BitmapResource(SegManager *segMan, const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 hunkPaletteOffset, const bool remap) { - _object = segMan->allocateHunkEntry("Bitmap()", getBitmapSize(width, height)); - _bitmap = segMan->getHunkPointer(_object); - - const uint16 bitmapHeaderSize = getBitmapHeaderSize(); - - setWidth(width); - setHeight(height); - setDisplace(Common::Point(displaceX, displaceY)); - setSkipColor(skipColor); - _bitmap[9] = 0; - WRITE_SCI11ENDIAN_UINT16(_bitmap + 10, 0); - setRemap(remap); - setDataSize(width * height); - WRITE_SCI11ENDIAN_UINT32(_bitmap + 16, 0); - setHunkPaletteOffset(hunkPaletteOffset); - setDataOffset(bitmapHeaderSize); - setUncompressedDataOffset(bitmapHeaderSize); - setControlOffset(0); - setScaledWidth(scaledWidth); - setScaledHeight(scaledHeight); - - _buffer = Buffer(getWidth(), getHeight(), getPixels()); - } - - inline reg_t getObject() const { - return _object; - } - - inline Buffer &getBuffer() { - return _buffer; - } - - BITMAP_PROPERTY(16, Width, 0); - BITMAP_PROPERTY(16, Height, 2); - - inline Common::Point getDisplace() const { - return Common::Point( - (int16)READ_SCI11ENDIAN_UINT16(_bitmap + 4), - (int16)READ_SCI11ENDIAN_UINT16(_bitmap + 6) - ); - } - - inline void setDisplace(const Common::Point &displace) { - WRITE_SCI11ENDIAN_UINT16(_bitmap + 4, (uint16)displace.x); - WRITE_SCI11ENDIAN_UINT16(_bitmap + 6, (uint16)displace.y); - } - - inline uint8 getSkipColor() const { - return _bitmap[8]; - } - - inline void setSkipColor(const uint8 skipColor) { - _bitmap[8] = skipColor; - } - - inline bool getRemap() const { - return READ_SCI11ENDIAN_UINT16(_bitmap + 10) & kBitmapRemap; - } - - inline void setRemap(const bool remap) { - uint16 flags = READ_SCI11ENDIAN_UINT16(_bitmap + 10); - if (remap) { - flags |= kBitmapRemap; - } else { - flags &= ~kBitmapRemap; - } - WRITE_SCI11ENDIAN_UINT16(_bitmap + 10, flags); - } - - BITMAP_PROPERTY(32, DataSize, 12); - - inline uint32 getHunkPaletteOffset() const { - return READ_SCI11ENDIAN_UINT32(_bitmap + 20); - } - - inline void setHunkPaletteOffset(uint32 hunkPaletteOffset) { - if (hunkPaletteOffset) { - hunkPaletteOffset += getBitmapHeaderSize(); - } - - WRITE_SCI11ENDIAN_UINT32(_bitmap + 20, hunkPaletteOffset); - } - - BITMAP_PROPERTY(32, DataOffset, 24); - - // NOTE: This property is used as a "magic number" for - // validating that a block of memory is a valid bitmap, - // and so is always set to the size of the header. - BITMAP_PROPERTY(32, UncompressedDataOffset, 28); - - // NOTE: This property always seems to be zero - BITMAP_PROPERTY(32, ControlOffset, 32); - - inline uint16 getScaledWidth() const { - if (getDataOffset() >= 40) { - return READ_SCI11ENDIAN_UINT16(_bitmap + 36); - } - - // SCI2 bitmaps did not have scaling ability - return 320; - } - - inline void setScaledWidth(uint16 scaledWidth) { - if (getDataOffset() >= 40) { - WRITE_SCI11ENDIAN_UINT16(_bitmap + 36, scaledWidth); - } - } - - inline uint16 getScaledHeight() const { - if (getDataOffset() >= 40) { - return READ_SCI11ENDIAN_UINT16(_bitmap + 38); - } - - // SCI2 bitmaps did not have scaling ability - return 200; - } - - inline void setScaledHeight(uint16 scaledHeight) { - if (getDataOffset() >= 40) { - WRITE_SCI11ENDIAN_UINT16(_bitmap + 38, scaledHeight); - } - } - - inline byte *getPixels() { - return _bitmap + getUncompressedDataOffset(); - } -}; - class GfxFont; /** @@ -390,12 +190,12 @@ public: * Creates a plain font bitmap with a flat color * background. */ - reg_t createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, TextAlign alignment, const int16 borderColor, bool dimmed, const bool doScaling); + reg_t createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, TextAlign alignment, const int16 borderColor, bool dimmed, const bool doScaling, const bool gc); /** * Creates a font bitmap with a view background. */ - reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed); + reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, const bool gc); inline int scaleUpWidth(int value) const { const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; diff --git a/engines/sci/graphics/transitions32.cpp b/engines/sci/graphics/transitions32.cpp new file mode 100644 index 0000000000..37f608da85 --- /dev/null +++ b/engines/sci/graphics/transitions32.cpp @@ -0,0 +1,978 @@ +/* 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 "sci/engine/segment.h" +#include "sci/engine/seg_manager.h" +#include "sci/engine/state.h" +#include "sci/graphics/frameout.h" +#include "sci/graphics/palette32.h" +#include "sci/graphics/text32.h" +#include "sci/graphics/transitions32.h" +#include "sci/sci.h" + +namespace Sci { +static int dissolveSequences[2][20] = { + /* SCI2.1early- */ { 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080 }, + /* SCI2.1mid+ */ { 0, 0, 3, 6, 12, 20, 48, 96, 184, 272, 576, 1280, 3232, 6912, 13568, 24576, 46080, 73728, 132096, 466944 } +}; +static int16 divisionsDefaults[2][16] = { + /* SCI2.1early- */ { 1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 40, 40, 101, 101 }, + /* SCI2.1mid+ */ { 1, 20, 20, 20, 20, 10, 10, 10, 10, 20, 20, 6, 10, 101, 101, 2 } +}; + +GfxTransitions32::GfxTransitions32(SegManager *segMan) : + _segMan(segMan), + _throttleState(0) { + for (int i = 0; i < 236; i += 2) { + _styleRanges[i] = 0; + _styleRanges[i + 1] = -1; + } + for (int i = 236; i < ARRAYSIZE(_styleRanges); ++i) { + _styleRanges[i] = 0; + } + + if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { + _dissolveSequenceSeeds = dissolveSequences[0]; + _defaultDivisions = divisionsDefaults[0]; + } else { + _dissolveSequenceSeeds = dissolveSequences[1]; + _defaultDivisions = divisionsDefaults[1]; + } +} + +GfxTransitions32::~GfxTransitions32() { + for (ShowStyleList::iterator it = _showStyles.begin(); + it != _showStyles.end(); + it = deleteShowStyle(it)); + _scrolls.clear(); +} + +void GfxTransitions32::throttle() { + uint8 throttleTime; + if (_throttleState == 2) { + throttleTime = 34; + _throttleState = 0; + } else { + throttleTime = 33; + ++_throttleState; + } + + g_sci->getEngineState()->speedThrottler(throttleTime); + g_sci->getEngineState()->_throttleTrigger = true; +} + +#pragma mark - +#pragma mark Show styles + +void GfxTransitions32::processShowStyles() { + uint32 now = g_sci->getTickCount(); + + bool continueProcessing; + bool doFrameOut; + do { + continueProcessing = false; + doFrameOut = false; + ShowStyleList::iterator showStyle = _showStyles.begin(); + while (showStyle != _showStyles.end()) { + bool finished = false; + + if (!showStyle->animate) { + doFrameOut = true; + } + + finished = processShowStyle(*showStyle, now); + + if (!finished) { + continueProcessing = true; + } + + if (finished && showStyle->processed) { + showStyle = deleteShowStyle(showStyle); + } else { + showStyle = ++showStyle; + } + } + + if (g_engine->shouldQuit()) { + return; + } + + if (doFrameOut) { + g_sci->_gfxFrameout->frameOut(true); + throttle(); + } + } while(continueProcessing && doFrameOut); +} + +void GfxTransitions32::processEffects(PlaneShowStyle &showStyle) { + switch(showStyle.type) { + case kShowStyleHShutterOut: + processHShutterOut(showStyle); + break; + case kShowStyleHShutterIn: + processHShutterIn(showStyle); + break; + case kShowStyleVShutterOut: + processVShutterOut(showStyle); + break; + case kShowStyleVShutterIn: + processVShutterIn(showStyle); + break; + case kShowStyleWipeLeft: + processWipeLeft(showStyle); + break; + case kShowStyleWipeRight: + processWipeRight(showStyle); + break; + case kShowStyleWipeUp: + processWipeUp(showStyle); + break; + case kShowStyleWipeDown: + processWipeDown(showStyle); + break; + case kShowStyleIrisOut: + processIrisOut(showStyle); + break; + case kShowStyleIrisIn: + processIrisIn(showStyle); + break; + case kShowStyleDissolveNoMorph: + case kShowStyleDissolve: + processPixelDissolve(showStyle); + break; + case kShowStyleNone: + case kShowStyleFadeOut: + case kShowStyleFadeIn: + case kShowStyleMorph: + break; + } +} + +// TODO: 10-argument version is only in SCI3; argc checks are currently wrong for this version +// and need to be fixed in future +void GfxTransitions32::kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 back, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen) { + + bool hasDivisions = false; + bool hasFadeArray = false; + + // KQ7 2.0b uses a mismatched version of the Styler script (SCI2.1early script + // for SCI2.1mid engine), so the calls it makes to kSetShowStyle are wrong and + // put `divisions` where `pFadeArray` is supposed to be + if (getSciVersion() == SCI_VERSION_2_1_MIDDLE && g_sci->getGameId() == GID_KQ7) { + hasDivisions = argc > 7; + hasFadeArray = false; + divisions = argc > 7 ? pFadeArray.toSint16() : -1; + pFadeArray = NULL_REG; + } else if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { + hasDivisions = argc > 7; + hasFadeArray = false; + } else if (getSciVersion() < SCI_VERSION_3) { + hasDivisions = argc > 8; + hasFadeArray = argc > 7; + } else { + hasDivisions = argc > 9; + hasFadeArray = argc > 8; + } + + bool isFadeUp; + int16 color; + if (back != -1) { + isFadeUp = false; + color = back; + } else { + isFadeUp = true; + color = 0; + } + + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObj); + if (plane == nullptr) { + error("Plane %04x:%04x is not present in active planes list", PRINT_REG(planeObj)); + } + + bool createNewEntry = true; + PlaneShowStyle *entry = findShowStyleForPlane(planeObj); + if (entry != nullptr) { + bool useExisting = true; + + if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { + useExisting = plane->_gameRect.width() == entry->width && plane->_gameRect.height() == entry->height; + } + + if (useExisting) { + useExisting = entry->divisions == (hasDivisions ? divisions : _defaultDivisions[type]); + } + + if (useExisting) { + createNewEntry = false; + isFadeUp = true; + entry->currentStep = 0; + } else { + isFadeUp = true; + color = entry->color; + deleteShowStyle(findIteratorForPlane(planeObj)); + entry = nullptr; + } + } + + if (type > 0) { + if (createNewEntry) { + entry = new PlaneShowStyle; + // NOTE: SCI2.1 engine tests if allocation returned a null pointer + // but then only avoids setting currentStep if this is so. Since + // this is a nonsensical approach, we do not do that here + entry->currentStep = 0; + entry->processed = false; + entry->divisions = hasDivisions ? divisions : _defaultDivisions[type]; + entry->plane = planeObj; + entry->fadeColorRangesCount = 0; + + if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { + // for pixel dissolve + entry->bitmap = NULL_REG; + entry->bitmapScreenItem = nullptr; + + // for wipe + entry->screenItems.clear(); + entry->width = plane->_gameRect.width(); + entry->height = plane->_gameRect.height(); + } else { + entry->fadeColorRanges = nullptr; + if (hasFadeArray) { + // NOTE: SCI2.1mid engine does no check to verify that an array is + // successfully retrieved, and SegMan will cause a fatal error + // if we try to use a memory segment that is not an array + SciArray<reg_t> *table = _segMan->lookupArray(pFadeArray); + + uint32 rangeCount = table->getSize(); + entry->fadeColorRangesCount = rangeCount; + + // NOTE: SCI engine code always allocates memory even if the range + // table has no entries, but this does not really make sense, so + // we avoid the allocation call in this case + if (rangeCount > 0) { + entry->fadeColorRanges = new uint16[rangeCount]; + for (size_t i = 0; i < rangeCount; ++i) { + entry->fadeColorRanges[i] = table->getValue(i).toUint16(); + } + } + } + } + } + + // NOTE: The original engine had no nullptr check and would just crash + // if it got to here + if (entry == nullptr) { + error("Cannot edit non-existing ShowStyle entry"); + } + + entry->fadeUp = isFadeUp; + entry->color = color; + entry->nextTick = g_sci->getTickCount(); + entry->type = type; + entry->animate = animate; + entry->delay = (seconds * 60 + entry->divisions - 1) / entry->divisions; + + if (entry->delay == 0) { + error("ShowStyle has no duration"); + } + + if (frameOutNow) { + // Creates a reference frame for the pixel dissolves to use + g_sci->_gfxFrameout->frameOut(false); + } + + if (createNewEntry) { + if (getSciVersion() <= SCI_VERSION_2_1_EARLY) { + switch (entry->type) { + case kShowStyleIrisOut: + case kShowStyleIrisIn: + configure21EarlyIris(*entry, priority); + break; + case kShowStyleDissolve: + configure21EarlyDissolve(*entry, priority, plane->_gameRect); + break; + default: + // do nothing + break; + } + } + + _showStyles.push_back(*entry); + delete entry; + } + } +} + +void GfxTransitions32::kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor) { + if (toColor > fromColor) { + return; + } + + for (int i = fromColor; i <= toColor; ++i) { + _styleRanges[i] = 0; + } +} + +PlaneShowStyle *GfxTransitions32::findShowStyleForPlane(const reg_t planeObj) { + for (ShowStyleList::iterator it = _showStyles.begin(); it != _showStyles.end(); ++it) { + if (it->plane == planeObj) { + return &*it; + } + } + + return nullptr; +} + +ShowStyleList::iterator GfxTransitions32::findIteratorForPlane(const reg_t planeObj) { + ShowStyleList::iterator it; + for (it = _showStyles.begin(); it != _showStyles.end(); ++it) { + if (it->plane == planeObj) { + break; + } + } + + return it; +} + +ShowStyleList::iterator GfxTransitions32::deleteShowStyle(const ShowStyleList::iterator &showStyle) { + switch (showStyle->type) { + case kShowStyleDissolveNoMorph: + case kShowStyleDissolve: + if (getSciVersion() <= SCI_VERSION_2_1_EARLY) { + _segMan->freeBitmap(showStyle->bitmap); + g_sci->_gfxFrameout->deleteScreenItem(*showStyle->bitmapScreenItem); + } + break; + case kShowStyleIrisOut: + case kShowStyleIrisIn: + if (getSciVersion() <= SCI_VERSION_2_1_EARLY) { + for (uint i = 0; i < showStyle->screenItems.size(); ++i) { + ScreenItem *screenItem = showStyle->screenItems[i]; + if (screenItem != nullptr) { + g_sci->_gfxFrameout->deleteScreenItem(*screenItem); + } + } + } + break; + case kShowStyleFadeIn: + case kShowStyleFadeOut: + if (getSciVersion() > SCI_VERSION_2_1_EARLY && showStyle->fadeColorRangesCount > 0) { + delete[] showStyle->fadeColorRanges; + } + break; + case kShowStyleNone: + case kShowStyleMorph: + // do nothing + break; + default: + error("Unknown delete transition type %d", showStyle->type); + } + + return _showStyles.erase(showStyle); +} + +void GfxTransitions32::configure21EarlyIris(PlaneShowStyle &showStyle, const int16 priority) { + showStyle.numEdges = 4; + const int numScreenItems = showStyle.numEdges * showStyle.divisions; + showStyle.screenItems.reserve(numScreenItems); + + CelInfo32 celInfo; + celInfo.type = kCelTypeColor; + celInfo.color = showStyle.color; + + const int width = showStyle.width; + const int height = showStyle.height; + const int divisions = showStyle.divisions; + + for (int i = 0; i < divisions; ++i) { + Common::Rect rect; + + // Top + rect.left = (width * i) / (2 * divisions); + rect.top = (height * i) / (2 * divisions); + rect.right = width - rect.left; + rect.bottom = (height + 1) * (i + 1) / (2 * divisions); + const int16 topTop = rect.top; + const int16 topBottom = rect.bottom; + + showStyle.screenItems.push_back(new ScreenItem(showStyle.plane, celInfo, rect)); + showStyle.screenItems.back()->_priority = priority; + showStyle.screenItems.back()->_fixedPriority = true; + + // Bottom + rect.top = height - rect.bottom; + rect.bottom = height - topTop; + const int16 bottomTop = rect.top; + + showStyle.screenItems.push_back(new ScreenItem(showStyle.plane, celInfo, rect)); + showStyle.screenItems.back()->_priority = priority; + showStyle.screenItems.back()->_fixedPriority = true; + + // Left + rect.top = topBottom; + rect.right = (width + 1) * (i + 1) / (2 * divisions); + rect.bottom = bottomTop; + const int16 leftLeft = rect.left; + + showStyle.screenItems.push_back(new ScreenItem(showStyle.plane, celInfo, rect)); + showStyle.screenItems.back()->_priority = priority; + showStyle.screenItems.back()->_fixedPriority = true; + + // Right + rect.left = width - rect.right; + rect.right = width - leftLeft; + + showStyle.screenItems.push_back(new ScreenItem(showStyle.plane, celInfo, rect)); + showStyle.screenItems.back()->_priority = priority; + showStyle.screenItems.back()->_fixedPriority = true; + } + + if (showStyle.fadeUp) { + for (int i = 0; i < numScreenItems; ++i) { + g_sci->_gfxFrameout->addScreenItem(*showStyle.screenItems[i]); + } + } +} + +void GfxTransitions32::configure21EarlyDissolve(PlaneShowStyle &showStyle, const int16 priority, const Common::Rect &gameRect) { + + reg_t bitmapId; + SciBitmap &bitmap = *_segMan->allocateBitmap(&bitmapId, showStyle.width, showStyle.height, kDefaultSkipColor, 0, 0, kLowResX, kLowResY, 0, false, false); + + showStyle.bitmap = bitmapId; + + const Buffer &source = g_sci->_gfxFrameout->getCurrentBuffer(); + Buffer target(showStyle.width, showStyle.height, bitmap.getPixels()); + + target.fillRect(Common::Rect(bitmap.getWidth(), bitmap.getHeight()), kDefaultSkipColor); + target.copyRectToSurface(source, 0, 0, gameRect); + + CelInfo32 celInfo; + celInfo.type = kCelTypeMem; + celInfo.bitmap = bitmapId; + + showStyle.bitmapScreenItem = new ScreenItem(showStyle.plane, celInfo, Common::Point(0, 0), ScaleInfo()); + showStyle.bitmapScreenItem->_priority = priority; + showStyle.bitmapScreenItem->_fixedPriority = true; + + g_sci->_gfxFrameout->addScreenItem(*showStyle.bitmapScreenItem); +} + +bool GfxTransitions32::processShowStyle(PlaneShowStyle &showStyle, uint32 now) { + if (showStyle.nextTick >= now && showStyle.animate) { + return false; + } + + switch (showStyle.type) { + default: + case kShowStyleNone: + return processNone(showStyle); + case kShowStyleHShutterOut: + case kShowStyleHShutterIn: + case kShowStyleVShutterOut: + case kShowStyleVShutterIn: + case kShowStyleWipeLeft: + case kShowStyleWipeRight: + case kShowStyleWipeUp: + case kShowStyleWipeDown: + case kShowStyleDissolveNoMorph: + case kShowStyleMorph: + return processMorph(showStyle); + case kShowStyleDissolve: + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + return processMorph(showStyle); + } else { + return processPixelDissolve(showStyle); + } + case kShowStyleIrisOut: + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + return processMorph(showStyle); + } else { + return processIrisOut(showStyle); + } + case kShowStyleIrisIn: + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + return processMorph(showStyle); + } else { + return processIrisIn(showStyle); + } + case kShowStyleFadeOut: + return processFade(-1, showStyle); + case kShowStyleFadeIn: + return processFade(1, showStyle); + } +} + +bool GfxTransitions32::processNone(PlaneShowStyle &showStyle) { + if (showStyle.fadeUp) { + g_sci->_gfxPalette32->setFade(100, 0, 255); + } else { + g_sci->_gfxPalette32->setFade(0, 0, 255); + } + + showStyle.processed = true; + return true; +} + +void GfxTransitions32::processHShutterOut(PlaneShowStyle &showStyle) { + error("HShutterOut is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processHShutterIn(PlaneShowStyle &showStyle) { + error("HShutterIn is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processVShutterOut(PlaneShowStyle &showStyle) { + error("VShutterOut is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processVShutterIn(PlaneShowStyle &showStyle) { + error("VShutterIn is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processWipeLeft(PlaneShowStyle &showStyle) { + error("WipeLeft is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processWipeRight(PlaneShowStyle &showStyle) { + error("WipeRight is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processWipeUp(PlaneShowStyle &showStyle) { + error("WipeUp is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +void GfxTransitions32::processWipeDown(PlaneShowStyle &showStyle) { + error("WipeDown is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +bool GfxTransitions32::processIrisOut(PlaneShowStyle &showStyle) { + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + error("IrisOut is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); + } + + return processWipe(-1, showStyle); +} + +bool GfxTransitions32::processIrisIn(PlaneShowStyle &showStyle) { + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + error("IrisIn is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); + } + + return processWipe(1, showStyle); +} + +void GfxTransitions32::processDissolveNoMorph(PlaneShowStyle &showStyle) { + error("DissolveNoMorph is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks!"); +} + +inline int bitWidth(int number) { + int width = 0; + while (number != 0) { + number >>= 1; + width += 1; + } + return width; +} + +bool GfxTransitions32::processPixelDissolve(PlaneShowStyle &showStyle) { + if (getSciVersion() > SCI_VERSION_2_1_EARLY) { + return processPixelDissolve21Mid(showStyle); + } else { + return processPixelDissolve21Early(showStyle); + } +} + +bool GfxTransitions32::processPixelDissolve21Early(PlaneShowStyle &showStyle) { + bool unchanged = true; + + SciBitmap &bitmap = *_segMan->lookupBitmap(showStyle.bitmap); + Buffer buffer(showStyle.width, showStyle.height, bitmap.getPixels()); + + uint32 numPixels = showStyle.width * showStyle.height; + uint32 numPixelsPerDivision = (numPixels + showStyle.divisions) / showStyle.divisions; + + uint32 index; + if (showStyle.currentStep == 0) { + int i = 0; + index = numPixels; + if (index != 1) { + for (;;) { + index >>= 1; + if (index == 1) { + break; + } + i++; + } + } + + showStyle.dissolveMask = _dissolveSequenceSeeds[i]; + index = 53427; + + showStyle.firstPixel = index; + showStyle.pixel = index; + } else { + index = showStyle.pixel; + for (;;) { + if (index & 1) { + index >>= 1; + index ^= showStyle.dissolveMask; + } else { + index >>= 1; + } + + if (index < numPixels) { + break; + } + } + + if (index == showStyle.firstPixel) { + index = 0; + } + } + + if (showStyle.currentStep < showStyle.divisions) { + for (uint32 i = 0; i < numPixelsPerDivision; ++i) { + *(byte *)buffer.getBasePtr(index % showStyle.width, index / showStyle.width) = showStyle.color; + + for (;;) { + if (index & 1) { + index >>= 1; + index ^= showStyle.dissolveMask; + } else { + index >>= 1; + } + + if (index < numPixels) { + break; + } + } + + if (index == showStyle.firstPixel) { + buffer.fillRect(Common::Rect(0, 0, showStyle.width, showStyle.height), showStyle.color); + break; + } + } + + showStyle.pixel = index; + showStyle.nextTick += showStyle.delay; + ++showStyle.currentStep; + unchanged = false; + if (showStyle.bitmapScreenItem->_created == 0) { + showStyle.bitmapScreenItem->_updated = g_sci->_gfxFrameout->getScreenCount(); + } + } + + if ((showStyle.currentStep >= showStyle.divisions) && unchanged) { + if (showStyle.fadeUp) { + showStyle.processed = true; + } + + return true; + } + + return false; +} + +bool GfxTransitions32::processPixelDissolve21Mid(PlaneShowStyle &showStyle) { + // SQ6 room 530 + + Plane* plane = g_sci->_gfxFrameout->getVisiblePlanes().findByObject(showStyle.plane); + const Common::Rect &screenRect = plane->_screenRect; + Common::Rect rect; + + const int planeWidth = screenRect.width(); + const int planeHeight = screenRect.height(); + const int divisions = showStyle.divisions; + const int width = planeWidth / divisions + ((planeWidth % divisions) ? 1 : 0); + const int height = planeHeight / divisions + ((planeHeight % divisions) ? 1 : 0); + + const uint32 mask = _dissolveSequenceSeeds[bitWidth(width * height - 1)]; + int seq = 1; + + uint iteration = 0; + const uint numIterationsPerTick = (width * height + divisions) / divisions; + + do { + int row = seq / width; + int col = seq % width; + + if (row < height) { + if (row == height && (planeHeight % divisions)) { + if (col == width && (planeWidth % divisions)) { + rect.left = col * divisions; + rect.top = row * divisions; + rect.right = col * divisions + (planeWidth % divisions); + rect.bottom = row * divisions + (planeHeight % divisions); + rect.clip(screenRect); + g_sci->_gfxFrameout->showRect(rect); + } else { + rect.left = col * divisions; + rect.top = row * divisions; + rect.right = col * divisions * 2; + rect.bottom = row * divisions + (planeHeight % divisions); + rect.clip(screenRect); + g_sci->_gfxFrameout->showRect(rect); + } + } else { + if (col == width && (planeWidth % divisions)) { + rect.left = col * divisions; + rect.top = row * divisions; + rect.right = col * divisions + (planeWidth % divisions) + 1; + rect.bottom = row * divisions * 2 + 1; + rect.clip(screenRect); + g_sci->_gfxFrameout->showRect(rect); + } else { + rect.left = col * divisions; + rect.top = row * divisions; + rect.right = col * divisions * 2 + 1; + rect.bottom = row * divisions * 2 + 1; + rect.clip(screenRect); + g_sci->_gfxFrameout->showRect(rect); + } + } + } + + if (seq & 1) { + seq = (seq >> 1) ^ mask; + } else { + seq >>= 1; + } + + if (++iteration == numIterationsPerTick) { + throttle(); + iteration = 0; + } + } while(seq != 1 && !g_engine->shouldQuit()); + + rect.left = screenRect.left; + rect.top = screenRect.top; + rect.right = divisions + screenRect.left; + rect.bottom = divisions + screenRect.bottom; + rect.clip(screenRect); + g_sci->_gfxFrameout->showRect(rect); + throttle(); + + g_sci->_gfxFrameout->showRect(screenRect); + return true; +} + +bool GfxTransitions32::processFade(const int8 direction, PlaneShowStyle &showStyle) { + bool unchanged = true; + if (showStyle.currentStep < showStyle.divisions) { + int percent; + if (direction <= 0) { + percent = showStyle.divisions - showStyle.currentStep - 1; + } else { + percent = showStyle.currentStep; + } + + percent *= 100; + percent /= showStyle.divisions - 1; + + if (showStyle.fadeColorRangesCount > 0) { + for (int i = 0, len = showStyle.fadeColorRangesCount; i < len; i += 2) { + g_sci->_gfxPalette32->setFade(percent, showStyle.fadeColorRanges[i], showStyle.fadeColorRanges[i + 1]); + } + } else { + g_sci->_gfxPalette32->setFade(percent, 0, 255); + } + + ++showStyle.currentStep; + showStyle.nextTick += showStyle.delay; + unchanged = false; + } + + if (showStyle.currentStep >= showStyle.divisions && unchanged) { + if (direction > 0) { + showStyle.processed = true; + } + + return true; + } + + return false; +} + +bool GfxTransitions32::processMorph(PlaneShowStyle &showStyle) { + g_sci->_gfxFrameout->palMorphFrameOut(_styleRanges, &showStyle); + showStyle.processed = true; + return true; +} + +bool GfxTransitions32::processWipe(const int8 direction, PlaneShowStyle &showStyle) { + bool unchanged = true; + if (showStyle.currentStep < showStyle.divisions) { + int index; + if (direction > 0) { + index = showStyle.currentStep; + } else { + index = showStyle.divisions - showStyle.currentStep - 1; + } + + index *= showStyle.numEdges; + for (int i = 0; i < showStyle.numEdges; ++i) { + ScreenItem *screenItem = showStyle.screenItems[index + i]; + if (showStyle.fadeUp) { + g_sci->_gfxFrameout->deleteScreenItem(*screenItem); + showStyle.screenItems[index + i] = nullptr; + } else { + g_sci->_gfxFrameout->addScreenItem(*screenItem); + } + } + + ++showStyle.currentStep; + showStyle.nextTick += showStyle.delay; + unchanged = false; + } + + if (showStyle.currentStep >= showStyle.divisions && unchanged) { + if (showStyle.fadeUp) { + showStyle.processed = true; + } + + return true; + } + + return false; +} + +#pragma mark - +#pragma mark Scrolls + +void GfxTransitions32::processScrolls() { + for (ScrollList::iterator it = _scrolls.begin(); it != _scrolls.end(); ) { + bool finished = processScroll(*it); + if (finished) { + it = _scrolls.erase(it); + } else { + ++it; + } + } + + throttle(); +} + +void GfxTransitions32::kernelSetScroll(const reg_t planeId, const int16 deltaX, const int16 deltaY, const GuiResourceId pictureId, const bool animate, const bool mirrorX) { + + for (ScrollList::const_iterator it = _scrolls.begin(); it != _scrolls.end(); ++it) { + if (it->plane == planeId) { + error("Scroll already exists on plane %04x:%04x", PRINT_REG(planeId)); + } + } + + if (!deltaX && !deltaY) { + error("kSetScroll: Scroll has no movement"); + } + + if (deltaX && deltaY) { + error("kSetScroll: Cannot scroll in two dimensions"); + } + + PlaneScroll *scroll = new PlaneScroll; + scroll->plane = planeId; + scroll->x = 0; + scroll->y = 0; + scroll->deltaX = deltaX; + scroll->deltaY = deltaY; + scroll->newPictureId = pictureId; + scroll->animate = animate; + scroll->startTick = g_sci->getTickCount(); + + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeId); + if (plane == nullptr) { + error("kSetScroll: Plane %04x:%04x not found", PRINT_REG(planeId)); + } + + Plane *visiblePlane = g_sci->_gfxFrameout->getPlanes().findByObject(planeId); + if (visiblePlane == nullptr) { + error("kSetScroll: Visible plane %04x:%04x not found", PRINT_REG(planeId)); + } + + const Common::Rect &gameRect = visiblePlane->_gameRect; + Common::Point picOrigin; + + if (deltaX) { + picOrigin.y = 0; + + if (deltaX > 0) { + scroll->x = picOrigin.x = -gameRect.width(); + } else { + scroll->x = picOrigin.x = gameRect.width(); + } + } else { + picOrigin.x = 0; + + if (deltaY > 0) { + scroll->y = picOrigin.y = -gameRect.height(); + } else { + scroll->y = picOrigin.y = gameRect.height(); + } + } + + scroll->oldPictureId = plane->addPic(pictureId, picOrigin, mirrorX); + + if (animate) { + _scrolls.push_front(*scroll); + } else { + bool finished = false; + while (!finished && !g_engine->shouldQuit()) { + finished = processScroll(*scroll); + g_sci->_gfxFrameout->frameOut(true); + throttle(); + } + delete scroll; + } +} + +bool GfxTransitions32::processScroll(PlaneScroll &scroll) { + bool finished = false; + uint32 now = g_sci->getTickCount(); + if (scroll.startTick >= now) { + return false; + } + + int deltaX = scroll.deltaX; + int deltaY = scroll.deltaY; + if (((scroll.x + deltaX) * scroll.y) <= 0) { + deltaX = -scroll.x; + } + if (((scroll.y + deltaY) * scroll.y) <= 0) { + deltaY = -scroll.y; + } + + scroll.x += deltaX; + scroll.y += deltaY; + + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(scroll.plane); + + if ((scroll.x == 0) && (scroll.y == 0)) { + plane->deletePic(scroll.oldPictureId, scroll.newPictureId); + finished = true; + } + + plane->scrollScreenItems(deltaX, deltaY, true); + + return finished; +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/transitions32.h b/engines/sci/graphics/transitions32.h new file mode 100644 index 0000000000..3968378a3c --- /dev/null +++ b/engines/sci/graphics/transitions32.h @@ -0,0 +1,476 @@ +/* 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 SCI_GRAPHICS_TRANSITIONS32_H +#define SCI_GRAPHICS_TRANSITIONS32_H + +#include "common/list.h" +#include "common/scummsys.h" +#include "sci/engine/vm_types.h" + +namespace Sci { +enum ShowStyleType /* : uint8 */ { + kShowStyleNone = 0, + kShowStyleHShutterOut = 1, + kShowStyleHShutterIn = 2, + kShowStyleVShutterOut = 3, + kShowStyleVShutterIn = 4, + kShowStyleWipeLeft = 5, + kShowStyleWipeRight = 6, + kShowStyleWipeUp = 7, + kShowStyleWipeDown = 8, + kShowStyleIrisOut = 9, + kShowStyleIrisIn = 10, + kShowStyleDissolveNoMorph = 11, + kShowStyleDissolve = 12, + kShowStyleFadeOut = 13, + kShowStyleFadeIn = 14, + kShowStyleMorph = 15 +}; + +/** + * Show styles represent transitions applied to draw planes. + * One show style per plane can be active at a time. + */ +struct PlaneShowStyle { + /** + * The ID of the plane this show style belongs to. + * In SCI2.1mid (at least SQ6), per-plane transitions + * were removed and a single plane ID is used. + */ + reg_t plane; + + /** + * The type of the transition. + */ + ShowStyleType type; + + /** + * When true, the show style is an entry transition + * to a new room. When false, it is an exit + * transition away from an old room. + */ + bool fadeUp; + + /** + * The number of steps for the show style. + */ + int16 divisions; + + /** + * The color used by transitions that draw CelObjColor + * screen items. -1 for transitions that do not draw + * screen items. + */ + int16 color; + + // TODO: Probably uint32 + // TODO: This field probably should be used in order to + // provide time-accurate processing of show styles. In the + // actual SCI engine (at least 2–2.1mid) it appears that + // style transitions are drawn “as fast as possibleâ€, one + // step per loop, even though this delay field exists + int delay; + + // TODO: Probably bool, but never seems to be true? + bool animate; + + /** + * The wall time at which the next step of the animation + * should execute. + */ + uint32 nextTick; + + /** + * During playback of the show style, the current step + * (out of divisions). + */ + int currentStep; + + /** + * Whether or not this style has finished running and + * is ready for disposal. + */ + bool processed; + + // + // Engine specific properties for SCI2.1early + // + + /** + * A list of screen items, each representing one + * block of a wipe transition. + */ + Common::Array<ScreenItem *> screenItems; + + /** + * For wipe transitions, the number of edges with a + * moving wipe (1, 2, or 4). + */ + uint8 numEdges; + + /** + * The dimensions of the plane, in game script + * coordinates. + */ + int16 width, height; + + /** + * For pixel dissolve transitions, the screen item + * used to render the transition. + */ + ScreenItem *bitmapScreenItem; + + /** + * For pixel dissolve transitions, the bitmap used + * to render the transition. + */ + reg_t bitmap; + + /** + * The bit mask used by pixel dissolve transitions. + */ + uint32 dissolveMask; + + /** + * The first pixel that was dissolved in a pixel + * dissolve transition. + */ + uint32 firstPixel; + + /** + * The last pixel that was dissolved. Once all + * pixels have been dissolved, `pixel` will once + * again equal `firstPixel`. + */ + uint32 pixel; + + // + // Engine specific properties for SCI2.1mid through SCI3 + // + + /** + * The number of entries in the fadeColorRanges array. + */ + uint8 fadeColorRangesCount; + + /** + * A pointer to an dynamically sized array of palette + * indexes, in the order [ fromColor, toColor, ... ]. + * Only colors within this range are transitioned. + */ + uint16 *fadeColorRanges; +}; + +/** + * PlaneScroll describes a transition between two different + * pictures within a single plane. + */ +struct PlaneScroll { + /** + * The ID of the plane to be scrolled. + */ + reg_t plane; + + /** + * The current position of the scroll. + */ + int16 x, y; + + /** + * The distance that should be scrolled. Only one of + * `deltaX` or `deltaY` may be set. + */ + int16 deltaX, deltaY; + + /** + * The pic that should be created and scrolled into + * view inside the plane. + */ + GuiResourceId newPictureId; + + /** + * The picture that should be scrolled out of view + * and deleted from the plane. + */ + GuiResourceId oldPictureId; + + /** + * If true, the scroll animation is interleaved + * with other updates to the graphics. If false, + * the scroll will be exclusively animated until + * it is finished. + */ + bool animate; + + /** + * The tick after which the animation will start. + */ + uint32 startTick; +}; + +typedef Common::List<PlaneShowStyle> ShowStyleList; +typedef Common::List<PlaneScroll> ScrollList; + +class GfxTransitions32 { +public: + GfxTransitions32(SegManager *_segMan); + ~GfxTransitions32(); +private: + SegManager *_segMan; + + /** + * Throttles transition playback to prevent + * transitions from being instant on fast + * computers. + */ + void throttle(); + int8 _throttleState; + +#pragma mark - +#pragma mark Show styles +public: + inline bool hasShowStyles() const { return !_showStyles.empty(); } + + /** + * Processes all active show styles in a loop + * until they are finished. + */ + void processShowStyles(); + + /** + * Processes show styles that are applied + * through `GfxFrameout::palMorphFrameOut`. + */ + void processEffects(PlaneShowStyle &showStyle); + + // NOTE: This signature is taken from SCI3 Phantasmagoria 2 + // and is valid for all implementations of SCI32 + void kernelSetShowStyle(const uint16 argc, const reg_t planeObj, const ShowStyleType type, const int16 seconds, const int16 direction, const int16 priority, const int16 animate, const int16 frameOutNow, reg_t pFadeArray, int16 divisions, const int16 blackScreen); + + /** + * Sets the range that will be used by + * `GfxFrameout::palMorphFrameOut` to alter + * palette entries. + */ + void kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor); + + /** + * A map of palette entries that can be morphed + * by the Morph show style. + */ + int8 _styleRanges[256]; + +private: + /** + * Default sequence values for pixel dissolve + * transition bit masks. + */ + int *_dissolveSequenceSeeds; + + /** + * Default values for `PlaneShowStyle::divisions` + * for the current SCI version. + */ + int16 *_defaultDivisions; + + /** + * The list of PlaneShowStyles that are + * currently active. + */ + ShowStyleList _showStyles; + + /** + * Finds a show style that applies to the given + * plane. + */ + PlaneShowStyle *findShowStyleForPlane(const reg_t planeObj); + + /** + * Finds the iterator for a show style that + * applies to the given plane. + */ + ShowStyleList::iterator findIteratorForPlane(const reg_t planeObj); + + /** + * Deletes the given PlaneShowStyle and returns + * the next PlaneShowStyle from the list of + * styles. + */ + ShowStyleList::iterator deleteShowStyle(const ShowStyleList::iterator &showStyle); + + /** + * Initializes the given PlaneShowStyle for an + * iris effect for SCI2 to 2.1early. + */ + void configure21EarlyIris(PlaneShowStyle &showStyle, const int16 priority); + + /** + * Initializes the given PlaneShowStyle for a + * pixel dissolve effect for SCI2 to 2.1early. + */ + void configure21EarlyDissolve(PlaneShowStyle &showStyle, const int16 priority, const Common::Rect &gameRect); + + /** + * Processes one tick of the given + * PlaneShowStyle. + */ + bool processShowStyle(PlaneShowStyle &showStyle, uint32 now); + + /** + * Performs an instant transition between two + * rooms. + */ + bool processNone(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders into a room + * with a horizontal shutter effect. + */ + void processHShutterOut(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders to black + * with a horizontal shutter effect. + */ + void processHShutterIn(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders into a room + * with a vertical shutter effect. + */ + void processVShutterOut(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders to black + * with a vertical shutter effect. + */ + void processVShutterIn(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders into a room + * with a wipe to the left. + */ + void processWipeLeft(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders to black + * with a wipe to the right. + */ + void processWipeRight(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders into a room + * with a wipe upwards. + */ + void processWipeUp(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders to black + * with a wipe downwards. + */ + void processWipeDown(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders into a room + * with an iris effect. + */ + bool processIrisOut(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders to black + * with an iris effect. + */ + bool processIrisIn(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders between + * rooms using a block dissolve effect. + */ + void processDissolveNoMorph(PlaneShowStyle &showStyle); + + /** + * Performs a transition that renders between + * rooms with a pixel dissolve effect. + */ + bool processPixelDissolve(PlaneShowStyle &showStyle); + + /** + * SCI2 to 2.1early implementation of pixel + * dissolve. + */ + bool processPixelDissolve21Early(PlaneShowStyle &showStyle); + + /** + * SCI2.1mid and later implementation of + * pixel dissolve. + */ + bool processPixelDissolve21Mid(PlaneShowStyle &showStyle); + + /** + * Performs a transition that fades to black + * between rooms. + */ + bool processFade(const int8 direction, PlaneShowStyle &showStyle); + + /** + * Morph transition calls back into the + * transition system's `processEffects` + * method, which then applies transitions + * other than None, Fade, or Morph. + */ + bool processMorph(PlaneShowStyle &showStyle); + + /** + * Performs a generic transition for any of + * the wipe/shutter/iris effects. + */ + bool processWipe(const int8 direction, PlaneShowStyle &showStyle); + +#pragma mark - +#pragma mark Scrolls +public: + inline bool hasScrolls() const { return !_scrolls.empty(); } + + /** + * Processes all active plane scrolls + * in a loop until they are finished. + */ + void processScrolls(); + + void kernelSetScroll(const reg_t plane, const int16 deltaX, const int16 deltaY, const GuiResourceId pictureId, const bool animate, const bool mirrorX); + +private: + /** + * A list of active plane scrolls. + */ + ScrollList _scrolls; + + /** + * Performs a scroll of the content of + * a plane. + */ + bool processScroll(PlaneScroll &scroll); +}; + +} // End of namespace Sci +#endif diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp index dd841f5b4c..8b1d4ef32b 100644 --- a/engines/sci/graphics/video32.cpp +++ b/engines/sci/graphics/video32.cpp @@ -20,20 +20,484 @@ * */ -#include "audio/mixer.h" -#include "common/config-manager.h" -#include "sci/console.h" -#include "sci/event.h" -#include "sci/graphics/cursor.h" -#include "sci/graphics/frameout.h" -#include "sci/graphics/palette32.h" -#include "sci/graphics/text32.h" +#include "audio/mixer.h" // for Audio::Mixer::kSFXSoundType +#include "common/config-manager.h" // for ConfMan +#include "common/textconsole.h" // for warning, error +#include "common/util.h" // for ARRAYSIZE +#include "common/system.h" // for g_system +#include "engine.h" // for Engine, g_engine +#include "engines/util.h" // for initGraphics +#include "sci/console.h" // for Console +#include "sci/engine/state.h" // for EngineState +#include "sci/engine/vm_types.h" // for reg_t +#include "sci/event.h" // for SciEvent, EventManager, SCI_... +#include "sci/graphics/celobj32.h" // for CelInfo32, ::kLowResX, ::kLo... +#include "sci/graphics/cursor32.h" // for GfxCursor32 +#include "sci/graphics/frameout.h" // for GfxFrameout +#include "sci/graphics/helpers.h" // for Color, Palette +#include "sci/graphics/palette32.h" // for GfxPalette32 +#include "sci/graphics/plane32.h" // for Plane, PlanePictureCodes::kP... +#include "sci/graphics/screen_item32.h" // for ScaleInfo, ScreenItem, Scale... +#include "sci/sci.h" // for SciEngine, g_sci, getSciVersion #include "sci/graphics/video32.h" -#include "sci/sci.h" -#include "video/coktel_decoder.h" +#include "sci/video/seq_decoder.h" // for SEQDecoder +#include "video/avi_decoder.h" // for AVIDecoder +#include "video/coktel_decoder.h" // for AdvancedVMDDecoder +namespace Graphics { struct Surface; } namespace Sci { +#pragma mark SEQPlayer + +SEQPlayer::SEQPlayer(SegManager *segMan) : + _segMan(segMan), + _decoder(nullptr), + _plane(nullptr), + _screenItem(nullptr) {} + +void SEQPlayer::play(const Common::String &fileName, const int16 numTicks, const int16 x, const int16 y) { + delete _decoder; + _decoder = new SEQDecoder(numTicks); + _decoder->loadFile(fileName); + + // NOTE: In the original engine, video was output directly to the hardware, + // bypassing the game's rendering engine. Instead of doing this, we use a + // mechanism that is very similar to that used by the VMD player, which + // allows the SEQ to be drawn into a bitmap ScreenItem and displayed using + // the normal graphics system. + _segMan->allocateBitmap(&_bitmap, _decoder->getWidth(), _decoder->getHeight(), kDefaultSkipColor, 0, 0, kLowResX, kLowResY, 0, false, false); + + CelInfo32 celInfo; + celInfo.type = kCelTypeMem; + celInfo.bitmap = _bitmap; + + _plane = new Plane(Common::Rect(kLowResX, kLowResY), kPlanePicColored); + g_sci->_gfxFrameout->addPlane(*_plane); + + // Normally we would use the x, y coordinates passed into the play function + // to position the screen item, but because the video frame bitmap is + // drawn in low-resolution coordinates, it gets automatically scaled up by + // the engine (pixel doubling with aspect ratio correction). As a result, + // the animation does not need the extra offsets from the game in order to + // be correctly positioned in the middle of the window, so we ignore them. + _screenItem = new ScreenItem(_plane->_object, celInfo, Common::Point(0, 0), ScaleInfo()); + g_sci->_gfxFrameout->addScreenItem(*_screenItem); + g_sci->_gfxFrameout->frameOut(true); + _decoder->start(); + + while (!g_engine->shouldQuit() && !_decoder->endOfVideo()) { + renderFrame(); + g_sci->getEngineState()->speedThrottler(_decoder->getTimeToNextFrame()); + g_sci->getEngineState()->_throttleTrigger = true; + } + + _segMan->freeBitmap(_screenItem->_celInfo.bitmap); + g_sci->_gfxFrameout->deletePlane(*_plane); + g_sci->_gfxFrameout->frameOut(true); + _screenItem = nullptr; + _plane = nullptr; +} + +void SEQPlayer::renderFrame() const { + const Graphics::Surface *surface = _decoder->decodeNextFrame(); + + SciBitmap &bitmap = *_segMan->lookupBitmap(_bitmap); + bitmap.getBuffer().copyRectToSurface(*surface, 0, 0, Common::Rect(surface->w, surface->h)); + + const bool dirtyPalette = _decoder->hasDirtyPalette(); + if (dirtyPalette) { + Palette palette; + const byte *rawPalette = _decoder->getPalette(); + for (int i = 0; i < ARRAYSIZE(palette.colors); ++i) { + palette.colors[i].r = *rawPalette++; + palette.colors[i].g = *rawPalette++; + palette.colors[i].b = *rawPalette++; + palette.colors[i].used = true; + } + + g_sci->_gfxPalette32->submit(palette); + } + + g_sci->_gfxFrameout->updateScreenItem(*_screenItem); + g_sci->getSciDebugger()->onFrame(); + g_sci->_gfxFrameout->frameOut(true); +} + +#pragma mark - +#pragma mark AVIPlayer + +AVIPlayer::AVIPlayer(SegManager *segMan, EventManager *eventMan) : + _segMan(segMan), + _eventMan(eventMan), + _decoder(new Video::AVIDecoder(Audio::Mixer::kSFXSoundType)), + _scaleBuffer(nullptr), + _plane(nullptr), + _screenItem(nullptr), + _status(kAVINotOpen) {} + +AVIPlayer::~AVIPlayer() { + close(); + delete _decoder; +} + +AVIPlayer::IOStatus AVIPlayer::open(const Common::String &fileName) { + if (_status != kAVINotOpen) { + close(); + } + + if (!_decoder->loadFile(fileName)) { + return kIOFileNotFound; + } + + _status = kAVIOpen; + return kIOSuccess; +} + +AVIPlayer::IOStatus AVIPlayer::init1x(const int16 x, const int16 y, int16 width, int16 height) { + if (_status == kAVINotOpen) { + return kIOFileNotFound; + } + + _pixelDouble = false; + + if (!width || !height) { + width = _decoder->getWidth(); + height = _decoder->getHeight(); + } else if (getSciVersion() == SCI_VERSION_2_1_EARLY && g_sci->getGameId() == GID_KQ7) { + // KQ7 1.51 provides an explicit width and height when it wants scaling, + // though the width and height it provides are not scaled + _pixelDouble = true; + width *= 2; + height *= 2; + } + + // QFG4CD gives non-multiple-of-2 values for width and height, + // which would normally be OK except the source video is a pixel bigger + // in each dimension + width = (width + 1) & ~1; + height = (height + 1) & ~1; + + _drawRect.left = x; + _drawRect.top = y; + _drawRect.right = x + width; + _drawRect.bottom = y + height; + + // SCI2.1mid uses init2x to draw a pixel-doubled AVI, but SCI2 has only the + // one play routine which automatically pixel-doubles in hi-res mode + if (getSciVersion() == SCI_VERSION_2) { + // This is somewhat of a hack; credits.avi from GK1 is not + // rendered correctly in SSCI because it is a 640x480 video, but the + // game script gives the wrong dimensions. Since this is the only + // high-resolution AVI ever used, just set the draw rectangle to draw + // the entire screen + if (_decoder->getWidth() > 320) { + _drawRect.left = 0; + _drawRect.top = 0; + _drawRect.right = 320; + _drawRect.bottom = 200; + } + + // In hi-res mode, video will be pixel doubled, so the origin (which + // corresponds to the correct position without pixel doubling) needs to + // be corrected + if (g_sci->_gfxFrameout->_isHiRes && _decoder->getWidth() <= 320) { + _drawRect.left /= 2; + _drawRect.top /= 2; + } + } + + init(); + + return kIOSuccess; +} + +AVIPlayer::IOStatus AVIPlayer::init2x(const int16 x, const int16 y) { + if (_status == kAVINotOpen) { + return kIOFileNotFound; + } + + _drawRect.left = x; + _drawRect.top = y; + _drawRect.right = x + _decoder->getWidth() * 2; + _drawRect.bottom = y + _decoder->getHeight() * 2; + + _pixelDouble = true; + init(); + + return kIOSuccess; +} + +void AVIPlayer::init() { + int16 xRes; + int16 yRes; + + bool useScreenDimensions = false; + if (g_sci->_gfxFrameout->_isHiRes && _decoder->getWidth() > 320) { + useScreenDimensions = true; + } + + // KQ7 1.51 gives video position in screen coordinates, not game + // coordinates, because in SSCI they are passed to Video for Windows, which + // renders as an overlay on the game video. Because we put the video into a + // ScreenItem instead of rendering directly to the hardware surface, the + // coordinates need to be converted to game script coordinates + if (g_sci->getGameId() == GID_KQ7 && getSciVersion() == SCI_VERSION_2_1_EARLY) { + useScreenDimensions = !_pixelDouble; + // This y-translation is arbitrary, based on what roughly centers the + // videos in the game window + _drawRect.translate(-_drawRect.left / 2, -_drawRect.top * 2 / 3); + } + + if (useScreenDimensions) { + xRes = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + yRes = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + } else { + xRes = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + yRes = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + } + + _plane = new Plane(_drawRect); + g_sci->_gfxFrameout->addPlane(*_plane); + + if (_decoder->getPixelFormat().bytesPerPixel == 1) { + _segMan->allocateBitmap(&_bitmap, _decoder->getWidth(), _decoder->getHeight(), kDefaultSkipColor, 0, 0, xRes, yRes, 0, false, false); + + CelInfo32 celInfo; + celInfo.type = kCelTypeMem; + celInfo.bitmap = _bitmap; + + _screenItem = new ScreenItem(_plane->_object, celInfo, Common::Point(_drawRect.left, _drawRect.top), ScaleInfo()); + g_sci->_gfxFrameout->addScreenItem(*_screenItem); + g_sci->_gfxFrameout->frameOut(true); + } else { + // Attempting to draw a palettized cursor into a 24bpp surface will + // cause memory corruption, so hide the cursor in this mode (SCI did not + // have a 24bpp mode but just directed VFW to display videos instead) + g_sci->_gfxCursor32->hide(); + + const Buffer ¤tBuffer = g_sci->_gfxFrameout->getCurrentBuffer(); + const Graphics::PixelFormat format = _decoder->getPixelFormat(); + initGraphics(currentBuffer.screenWidth, currentBuffer.screenHeight, g_sci->_gfxFrameout->_isHiRes, &format); + + if (_pixelDouble) { + const int16 width = _drawRect.width(); + const int16 height = _drawRect.height(); + _scaleBuffer = calloc(1, width * height * format.bytesPerPixel); + } + } +} + +AVIPlayer::IOStatus AVIPlayer::play(const int16 from, const int16 to, const int16, const bool async) { + if (_status == kAVINotOpen) { + return kIOFileNotFound; + } + + if (from >= 0 && to > 0 && from <= to) { + _decoder->seekToFrame(from); + _decoder->setEndFrame(to); + } + + if (!async) { + renderVideo(); + } else if (getSciVersion() == SCI_VERSION_2_1_EARLY) { + playUntilEvent((EventFlags)(kEventFlagEnd | kEventFlagEscapeKey)); + } else { + _status = kAVIPlaying; + } + + return kIOSuccess; +} + +void AVIPlayer::renderVideo() const { + _decoder->start(); + while (!g_engine->shouldQuit() && !_decoder->endOfVideo()) { + g_sci->getEngineState()->speedThrottler(_decoder->getTimeToNextFrame()); + g_sci->getEngineState()->_throttleTrigger = true; + if (_decoder->needsUpdate()) { + renderFrame(); + } + } +} + +AVIPlayer::IOStatus AVIPlayer::close() { + if (_status == kAVINotOpen) { + return kIOSuccess; + } + + free(_scaleBuffer); + _scaleBuffer = nullptr; + + if (_decoder->getPixelFormat().bytesPerPixel != 1) { + const bool isHiRes = g_sci->_gfxFrameout->_isHiRes; + const Buffer ¤tBuffer = g_sci->_gfxFrameout->getCurrentBuffer(); + const Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); + initGraphics(currentBuffer.screenWidth, currentBuffer.screenHeight, isHiRes, &format); + g_sci->_gfxCursor32->unhide(); + } + + _decoder->close(); + _status = kAVINotOpen; + g_sci->_gfxFrameout->deletePlane(*_plane); + _plane = nullptr; + _screenItem = nullptr; + return kIOSuccess; +} + +AVIPlayer::IOStatus AVIPlayer::cue(const uint16 frameNo) { + if (!_decoder->seekToFrame(frameNo)) { + return kIOSeekFailed; + } + + _status = kAVIPaused; + return kIOSuccess; +} + +uint16 AVIPlayer::getDuration() const { + if (_status == kAVINotOpen) { + return 0; + } + + return _decoder->getFrameCount(); +} + +void AVIPlayer::renderFrame() const { + const Graphics::Surface *surface = _decoder->decodeNextFrame(); + + if (surface->format.bytesPerPixel == 1) { + SciBitmap &bitmap = *_segMan->lookupBitmap(_bitmap); + if (surface->w > bitmap.getWidth() || surface->h > bitmap.getHeight()) { + warning("Attempted to draw a video frame larger than the destination bitmap"); + return; + } + + // KQ7 1.51 encodes videos with palette entry 0 as white, which makes + // the area around the video turn white too, since it is coded to use + // palette entry 0. This happens to work in the original game because + // the video is rendered by VfW, not in the engine itself. To fix this, + // we just modify the incoming pixel data from the video so if a pixel + // is using entry 0, we change it to use entry 255, which is guaranteed + // to always be white + if (getSciVersion() == SCI_VERSION_2_1_EARLY && g_sci->getGameId() == GID_KQ7) { + uint8 *target = bitmap.getPixels(); + const uint8 *source = (const uint8 *)surface->getPixels(); + const uint8 *end = (const uint8 *)surface->getPixels() + surface->w * surface->h; + + while (source != end) { + uint8 value = *source++; + *target++ = value == 0 ? 255 : value; + } + } else { + bitmap.getBuffer().copyRectToSurface(*surface, 0, 0, Common::Rect(surface->w, surface->h)); + } + + const bool dirtyPalette = _decoder->hasDirtyPalette(); + if (dirtyPalette) { + Palette palette; + const byte *rawPalette = _decoder->getPalette(); + for (int i = 0; i < ARRAYSIZE(palette.colors); ++i) { + palette.colors[i].r = *rawPalette++; + palette.colors[i].g = *rawPalette++; + palette.colors[i].b = *rawPalette++; + palette.colors[i].used = true; + } + + // Prevent KQ7 1.51 from setting entry 0 to white + palette.colors[0].used = false; + + g_sci->_gfxPalette32->submit(palette); + } + + g_sci->_gfxFrameout->updateScreenItem(*_screenItem); + g_sci->getSciDebugger()->onFrame(); + g_sci->_gfxFrameout->frameOut(true); + } else { + assert(surface->format.bytesPerPixel == 4); + + Common::Rect drawRect(_drawRect); + + if (_pixelDouble) { + const uint32 *source = (const uint32 *)surface->getPixels(); + uint32 *target = (uint32 *)_scaleBuffer; + // target pitch here is in uint32s, not bytes + const uint16 pitch = surface->pitch / 2; + for (int y = 0; y < surface->h; ++y) { + for (int x = 0; x < surface->w; ++x) { + const uint32 value = *source++; + + target[0] = value; + target[1] = value; + target[pitch] = value; + target[pitch + 1] = value; + target += 2; + } + target += pitch; + } + + g_system->copyRectToScreen(_scaleBuffer, surface->pitch * 2, _drawRect.left, _drawRect.top, _drawRect.width(), _drawRect.height()); + } else { + const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + + mulinc(drawRect, Ratio(screenWidth, scriptWidth), Ratio(screenHeight, scriptHeight)); + + g_system->copyRectToScreen(surface->getPixels(), surface->pitch, drawRect.left, drawRect.top, surface->w, surface->h); + } + } +} + +AVIPlayer::EventFlags AVIPlayer::playUntilEvent(EventFlags flags) { + _decoder->start(); + + EventFlags stopFlag = kEventFlagNone; + while (!g_engine->shouldQuit()) { + if (_decoder->endOfVideo()) { + stopFlag = kEventFlagEnd; + break; + } + + g_sci->getEngineState()->speedThrottler(_decoder->getTimeToNextFrame()); + g_sci->getEngineState()->_throttleTrigger = true; + if (_decoder->needsUpdate()) { + renderFrame(); + } + + SciEvent event = _eventMan->getSciEvent(SCI_EVENT_MOUSE_PRESS | SCI_EVENT_PEEK); + if ((flags & kEventFlagMouseDown) && event.type == SCI_EVENT_MOUSE_PRESS) { + stopFlag = kEventFlagMouseDown; + break; + } + + event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); + if ((flags & kEventFlagEscapeKey) && event.type == SCI_EVENT_KEYBOARD) { + bool stop = false; + while ((event = _eventMan->getSciEvent(SCI_EVENT_KEYBOARD)), + event.type != SCI_EVENT_NONE) { + if (event.character == SCI_KEY_ESC) { + stop = true; + break; + } + } + + if (stop) { + stopFlag = kEventFlagEscapeKey; + break; + } + } + + // TODO: Hot rectangles + if ((flags & kEventFlagHotRectangle) /* && event.type == SCI_EVENT_HOT_RECTANGLE */) { + warning("Hot rectangles not implemented in VMD player"); + stopFlag = kEventFlagHotRectangle; + break; + } + } + + return stopFlag; +} + +#pragma mark - #pragma mark VMDPlayer VMDPlayer::VMDPlayer(SegManager *segMan, EventManager *eventMan) : @@ -117,6 +581,7 @@ VMDPlayer::IOStatus VMDPlayer::close() { if (!_planeIsOwned && _screenItem != nullptr) { g_sci->_gfxFrameout->deleteScreenItem(*_screenItem); + _segMan->freeBitmap(_screenItem->_celInfo.bitmap); _screenItem = nullptr; } else if (_plane != nullptr) { g_sci->_gfxFrameout->deletePlane(*_plane); @@ -139,7 +604,7 @@ VMDPlayer::IOStatus VMDPlayer::close() { } if (!_showCursor) { - g_sci->_gfxCursor->kernelShow(); + g_sci->_gfxCursor32->unhide(); } _lastYieldedFrameNo = 0; @@ -148,6 +613,22 @@ VMDPlayer::IOStatus VMDPlayer::close() { return kIOSuccess; } +VMDPlayer::VMDStatus VMDPlayer::getStatus() const { + if (!_isOpen) { + return kVMDNotOpen; + } + if (_decoder->isPaused()) { + return kVMDPaused; + } + if (_decoder->isPlaying()) { + return kVMDPlaying; + } + if (_decoder->endOfVideo()) { + return kVMDFinished; + } + return kVMDOpen; +} + VMDPlayer::EventFlags VMDPlayer::kernelPlayUntilEvent(const EventFlags flags, const int16 lastFrameNo, const int16 yieldInterval) { assert(lastFrameNo >= -1); @@ -200,7 +681,7 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { _isInitialized = true; if (!_showCursor) { - g_sci->_gfxCursor->kernelHide(); + g_sci->_gfxCursor32->hide(); } Common::Rect vmdRect(_x, @@ -231,14 +712,15 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) { const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; - BitmapResource vmdBitmap(_segMan, vmdRect.width(), vmdRect.height(), 255, 0, 0, screenWidth, screenHeight, 0, false); + reg_t bitmapId; + SciBitmap &vmdBitmap = *_segMan->allocateBitmap(&bitmapId, vmdRect.width(), vmdRect.height(), 255, 0, 0, screenWidth, screenHeight, 0, false, false); if (screenWidth != scriptWidth || screenHeight != scriptHeight) { mulru(vmdRect, Ratio(scriptWidth, screenWidth), Ratio(scriptHeight, screenHeight), 1); } CelInfo32 vmdCelInfo; - vmdCelInfo.bitmap = vmdBitmap.getObject(); + vmdCelInfo.bitmap = bitmapId; _decoder->setSurfaceMemory(vmdBitmap.getPixels(), vmdBitmap.getWidth(), vmdBitmap.getHeight(), 1); if (_planeIsOwned) { diff --git a/engines/sci/graphics/video32.h b/engines/sci/graphics/video32.h index 7033f7c647..75b8fb2d21 100644 --- a/engines/sci/graphics/video32.h +++ b/engines/sci/graphics/video32.h @@ -23,16 +23,216 @@ #ifndef SCI_GRAPHICS_VIDEO32_H #define SCI_GRAPHICS_VIDEO32_H -namespace Video { class AdvancedVMDDecoder; } +#include "common/rect.h" // for Rect +#include "common/scummsys.h" // for int16, uint8, uint16, int32 +#include "common/str.h" // for String +#include "sci/engine/vm_types.h" // for reg_t +#include "sci/video/robot_decoder.h" // for RobotDecoder + +namespace Video { +class AdvancedVMDDecoder; +class AVIDecoder; +} namespace Sci { +class EventManager; class Plane; class ScreenItem; class SegManager; +class SEQDecoder; +struct Palette; +#pragma mark SEQPlayer + +/** + * SEQPlayer is used to play SEQ animations. + * Used by DOS versions of GK1 and QFG4CD. + */ +class SEQPlayer { +public: + SEQPlayer(SegManager *segMan); + + /** + * Plays a SEQ animation with the given + * file name, with each frame being displayed + * for `numTicks` ticks. + */ + void play(const Common::String &fileName, const int16 numTicks, const int16 x, const int16 y); + +private: + SegManager *_segMan; + SEQDecoder *_decoder; + + /** + * The plane where the SEQ will be drawn. + */ + Plane *_plane; + + /** + * The screen item representing the SEQ surface. + */ + ScreenItem *_screenItem; + + /** + * The bitmap used to render video output. + */ + reg_t _bitmap; + + /** + * Renders a single frame of video. + */ + void renderFrame() const; +}; + +#pragma mark - +#pragma mark AVIPlayer + +/** + * AVIPlayer is used to play AVI videos. Used by + * Windows versions of GK1CD, KQ7, and QFG4CD. + */ +class AVIPlayer { +public: + enum IOStatus { + kIOSuccess = 0, + kIOFileNotFound = 2, + kIOSeekFailed = 12 + }; + + enum AVIStatus { + kAVINotOpen = 0, + kAVIOpen = 1, + kAVIPlaying = 2, + kAVIPaused = 3 + }; + + enum EventFlags { + kEventFlagNone = 0, + kEventFlagEnd = 1, + kEventFlagEscapeKey = 2, + kEventFlagMouseDown = 4, + kEventFlagHotRectangle = 8 + }; + + AVIPlayer(SegManager *segMan, EventManager *eventMan); + ~AVIPlayer(); + + /** + * Opens a stream to an AVI resource. + */ + IOStatus open(const Common::String &fileName); + + /** + * Initializes the AVI rendering parameters for the + * current AVI. This must be called after `open`. + */ + IOStatus init1x(const int16 x, const int16 y, const int16 width, const int16 height); + + /** + * Initializes the AVI rendering parameters for the + * current AVI, in pixel-doubling mode. This must + * be called after `open`. + */ + IOStatus init2x(const int16 x, const int16 y); + + /** + * Begins playback of the current AVI. + */ + IOStatus play(const int16 from, const int16 to, const int16 showStyle, const bool cue); + + /** + * Stops playback and closes the currently open AVI stream. + */ + IOStatus close(); + + /** + * Seeks the currently open AVI stream to the given frame. + */ + IOStatus cue(const uint16 frameNo); + + /** + * Returns the duration of the current video. + */ + uint16 getDuration() const; + + /** + * Plays the AVI until an event occurs (e.g. user + * presses escape, clicks, etc.). + */ + EventFlags playUntilEvent(const EventFlags flags); + +private: + typedef Common::HashMap<uint16, AVIStatus> StatusMap; + + SegManager *_segMan; + EventManager *_eventMan; + Video::AVIDecoder *_decoder; + + /** + * Playback status of the player. + */ + AVIStatus _status; + + /** + * The plane where the AVI will be drawn. + */ + Plane *_plane; + + /** + * The screen item representing the AVI surface, + * in 8bpp mode. In 24bpp mode, video is drawn + * directly to the screen. + */ + ScreenItem *_screenItem; + + /** + * The bitmap used to render video output in + * 8bpp mode. + */ + reg_t _bitmap; + + /** + * The rectangle where the video will be drawn, + * in game script coordinates. + */ + Common::Rect _drawRect; + + /** + * The scale buffer for pixel-doubled videos + * drawn in 24bpp mode. + */ + void *_scaleBuffer; + + /** + * In SCI2.1, whether or not the video should + * be pixel doubled for playback. + */ + bool _pixelDouble; + + /** + * Performs common initialisation for both + * scaled and unscaled videos. + */ + void init(); + + /** + * Renders video without event input until the + * video is complete. + */ + void renderVideo() const; + + /** + * Renders a single frame of video. + */ + void renderFrame() const; +}; + +#pragma mark - #pragma mark VMDPlayer /** * VMDPlayer is used to play VMD videos. + * Used by Phant1, GK2, PQ:SWAT, Shivers, SQ6, + * Torin, and Lighthouse. */ class VMDPlayer { public: @@ -68,6 +268,15 @@ public: kEventFlagReverse = 0x80 }; + enum VMDStatus { + kVMDNotOpen = 0, + kVMDOpen = 1, + kVMDPlaying = 2, + kVMDPaused = 3, + kVMDStopped = 4, + kVMDFinished = 5 + }; + VMDPlayer(SegManager *segMan, EventManager *eventMan); ~VMDPlayer(); @@ -95,6 +304,11 @@ public: */ IOStatus close(); + /** + * Gets the playback status of the VMD player. + */ + VMDStatus getStatus() const; + // NOTE: Was WaitForEvent in SSCI EventFlags kernelPlayUntilEvent(const EventFlags flags, const int16 lastFrameNo, const int16 yieldInterval); @@ -297,15 +511,28 @@ private: bool _showCursor; }; +/** + * Video32 provides facilities for playing back + * video in SCI engine. + */ class Video32 { public: Video32(SegManager *segMan, EventManager *eventMan) : - _VMDPlayer(segMan, eventMan) {} + _SEQPlayer(segMan), + _AVIPlayer(segMan, eventMan), + _VMDPlayer(segMan, eventMan), + _robotPlayer(segMan) {} + SEQPlayer &getSEQPlayer() { return _SEQPlayer; } + AVIPlayer &getAVIPlayer() { return _AVIPlayer; } VMDPlayer &getVMDPlayer() { return _VMDPlayer; } + RobotDecoder &getRobotPlayer() { return _robotPlayer; } private: + SEQPlayer _SEQPlayer; + AVIPlayer _AVIPlayer; VMDPlayer _VMDPlayer; + RobotDecoder _robotPlayer; }; } // End of namespace Sci diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 1939e66179..0c09fcbb30 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -351,18 +351,6 @@ void GfxView::initData(GuiResourceId resourceId) { celData += celSize; } } -#ifdef ENABLE_SCI32 - // adjust width/height returned to scripts - if (_sci2ScaleRes != SCI_VIEW_NATIVERES_NONE) { - for (loopNo = 0; loopNo < _loopCount; loopNo++) - for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++) - _screen->adjustBackUpscaledCoordinates(_loop[loopNo].cel[celNo].scriptWidth, _loop[loopNo].cel[celNo].scriptHeight, _sci2ScaleRes); - } else if ((getSciVersion() >= SCI_VERSION_2_1_EARLY) && (getSciVersion() <= SCI_VERSION_2_1_LATE)) { - for (loopNo = 0; loopNo < _loopCount; loopNo++) - for (celNo = 0; celNo < _loop[loopNo].celCount; celNo++) - _coordAdjuster->fromDisplayToScript(_loop[loopNo].cel[celNo].scriptHeight, _loop[loopNo].cel[celNo].scriptWidth); - } -#endif break; default: diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index 96b48c0477..5e422468b5 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -92,7 +92,7 @@ private: void unditherBitmap(byte *bitmap, int16 width, int16 height, byte clearKey); ResourceManager *_resMan; - GfxCoordAdjuster *_coordAdjuster; + GfxCoordAdjuster16 *_coordAdjuster; GfxScreen *_screen; GfxPalette *_palette; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 1511356747..eb2c6a148b 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -91,7 +91,9 @@ MODULE_OBJS += \ graphics/remap32.o \ graphics/screen_item32.o \ graphics/text32.o \ + graphics/transitions32.o \ graphics/video32.o \ + graphics/cursor32.o \ sound/audio32.o \ sound/decoders/sol.o \ video/robot_decoder.o diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 48278e35a7..2e69932e49 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -573,6 +573,9 @@ Resource *ResourceManager::testResource(ResourceId id) { } int ResourceManager::addAppropriateSources() { +#ifdef ENABLE_SCI32 + _multiDiscAudio = false; +#endif if (Common::File::exists("resource.map")) { // SCI0-SCI2 file naming scheme ResourceSource *map = addExternalMap("resource.map"); @@ -615,6 +618,10 @@ int ResourceManager::addAppropriateSources() { if (mapFiles.empty() || files.empty() || mapFiles.size() != files.size()) return 0; + if (Common::File::exists("resaud.001")) { + _multiDiscAudio = true; + } + for (Common::ArchiveMemberList::const_iterator mapIterator = mapFiles.begin(); mapIterator != mapFiles.end(); ++mapIterator) { Common::String mapName = (*mapIterator)->getName(); int mapNumber = atoi(strrchr(mapName.c_str(), '.') + 1); @@ -659,6 +666,7 @@ int ResourceManager::addAppropriateSourcesForDetection(const Common::FSList &fsl #ifdef ENABLE_SCI32 ResourceSource *sci21PatchMap = 0; const Common::FSNode *sci21PatchRes = 0; + _multiDiscAudio = false; #endif // First, find resource.map @@ -859,6 +867,13 @@ void ResourceManager::addResourcesFromChunk(uint16 id) { scanNewSources(); } +void ResourceManager::findDisc(const int16 discNo) { + // Since all resources are expected to be copied from the original discs + // into a single game directory, this call just records the number of the CD + // that the game has requested + _currentDiscNo = discNo; +} + #endif void ResourceManager::freeResourceSources() { @@ -878,7 +893,9 @@ void ResourceManager::init() { _LRU.clear(); _resMap.clear(); _audioMapSCI1 = NULL; - +#ifdef ENABLE_SCI32 + _currentDiscNo = 1; +#endif // FIXME: put this in an Init() function, so that we can error out if detection fails completely _mapVersion = detectMapVersion(); @@ -1477,6 +1494,12 @@ void ResourceManager::readResourcePatchesBase36() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { name = (*x)->getName(); + // The S/T prefixes often conflict with non-patch files and generate + // spurious warnings about invalid patches + if (name.hasSuffix(".DLL") || name.hasSuffix(".EXE") || name.hasSuffix(".TXT")) { + continue; + } + ResourceId resource36 = convertPatchNameBase36((ResourceType)i, name); /* @@ -1738,11 +1761,42 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { // if we use the first entries in the resource file, half of the // game will be English and umlauts will also be missing :P if (resource->_source->getSourceType() == kSourceVolume) { + // Maps are read during the scanning process (below), so + // need to be treated as unallocated in order for the new + // data from this volume to be picked up and used + if (resId.getType() == kResourceTypeMap) { + resource->_status = kResStatusNoMalloc; + } resource->_source = source; resource->_fileOffset = fileOffset; resource->size = 0; } } + +#ifdef ENABLE_SCI32 + // Different CDs may have different audio maps on each disc. The + // ResourceManager does not know how to deal with this; it expects + // each resource ID to be unique across an entire game. To work + // around this problem, all audio maps from this disc must be + // processed immediately, since they will be replaced by the audio + // map from the next disc on the next call to readResourceMapSCI1 + if (_multiDiscAudio && resId.getType() == kResourceTypeMap) { + IntMapResourceSource *audioMap = static_cast<IntMapResourceSource *>(addSource(new IntMapResourceSource("MAP", mapVolumeNr, resId.getNumber()))); + Common::String volumeName; + if (resId.getNumber() == 65535) { + volumeName = Common::String::format("RESSFX.%03d", mapVolumeNr); + } else { + volumeName = Common::String::format("RESAUD.%03d", mapVolumeNr); + } + + ResourceSource *audioVolume = addSource(new AudioVolumeResourceSource(this, volumeName, audioMap, mapVolumeNr)); + if (!audioMap->_scanned) { + audioVolume->_scanned = true; + audioMap->_scanned = true; + audioMap->scanSource(this); + } + } +#endif } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index f70bf48bd4..70db5909b7 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -296,6 +296,7 @@ protected: typedef Common::HashMap<ResourceId, Resource *, ResourceIdHash> ResourceMap; +class IntMapResourceSource; class ResourceManager { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. @@ -397,6 +398,30 @@ public: * resource manager. */ void addResourcesFromChunk(uint16 id); + + /** + * Updates the currently active disc number. + */ + void findDisc(const int16 discNo); + + /** + * Gets the currently active disc number. + */ + int16 getCurrentDiscNo() const { return _currentDiscNo; } + +private: + /** + * The currently active disc number. + */ + int16 _currentDiscNo; + + /** + * If true, the game has multiple audio volumes that contain different + * audio files for each disc. + */ + bool _multiDiscAudio; + +public: #endif bool detectHires(); @@ -520,7 +545,7 @@ protected: * @param map The map * @return 0 on success, an SCI_ERROR_* code otherwise */ - int readAudioMapSCI11(ResourceSource *map); + int readAudioMapSCI11(IntMapResourceSource *map); /** * Reads SCI1 audio map files. diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 5ab443a16d..cbc4a02739 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -277,7 +277,7 @@ void ResourceManager::removeAudioResource(ResourceId resId) { // w syncSize (iff seq has bit 7 set) // w syncAscSize (iff seq has bit 6 set) -int ResourceManager::readAudioMapSCI11(ResourceSource *map) { +int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) { #ifndef ENABLE_SCI32 // SCI32 support is not built in. Check if this is a SCI32 game // and if it is abort here. @@ -286,17 +286,19 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { #endif uint32 offset = 0; - Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false); + Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_mapNumber), false); if (!mapRes) { - warning("Failed to open %i.MAP", map->_volumeNumber); + warning("Failed to open %i.MAP", map->_mapNumber); return SCI_ERROR_RESMAP_NOT_FOUND; } - ResourceSource *src = findVolume(map, 0); + ResourceSource *src = findVolume(map, map->_volumeNumber); - if (!src) + if (!src) { + warning("Failed to find volume for %i.MAP", map->_mapNumber); return SCI_ERROR_NO_RESOURCE_FILES_FOUND; + } byte *ptr = mapRes->data; @@ -309,7 +311,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { break; } - if (map->_volumeNumber == 65535) { + if (map->_mapNumber == 65535) { while (ptr < mapRes->data + mapRes->size) { uint16 n = READ_LE_UINT16(ptr); ptr += 2; @@ -327,7 +329,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { addResource(ResourceId(kResourceTypeAudio, n), src, offset); } - } else if (map->_volumeNumber == 0 && entrySize == 10 && ptr[3] == 0) { + } else if (map->_mapNumber == 0 && entrySize == 10 && ptr[3] == 0) { // QFG3 demo format // ptr[3] would be 'seq' in the normal format and cannot possibly be 0 while (ptr < mapRes->data + mapRes->size) { @@ -344,7 +346,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); } - } else if (map->_volumeNumber == 0 && entrySize == 8 && READ_LE_UINT16(ptr + 2) == 0xffff) { + } else if (map->_mapNumber == 0 && entrySize == 8 && READ_LE_UINT16(ptr + 2) == 0xffff) { // LB2 Floppy/Mother Goose SCI1.1 format Common::SeekableReadStream *stream = getVolumeFile(src); @@ -400,7 +402,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { // FIXME: The sync36 resource seems to be two bytes too big in KQ6CD // (bytes taken from the RAVE resource right after it) if (syncSize > 0) - addResource(ResourceId(kResourceTypeSync36, map->_volumeNumber, n & 0xffffff3f), src, offset, syncSize); + addResource(ResourceId(kResourceTypeSync36, map->_mapNumber, n & 0xffffff3f), src, offset, syncSize); } if (n & 0x40) { @@ -410,12 +412,12 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { ptr += 2; if (kq6HiresSyncSize > 0) { - addResource(ResourceId(kResourceTypeRave, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize, kq6HiresSyncSize); + addResource(ResourceId(kResourceTypeRave, map->_mapNumber, n & 0xffffff3f), src, offset + syncSize, kq6HiresSyncSize); syncSize += kq6HiresSyncSize; } } - addResource(ResourceId(kResourceTypeAudio36, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize); + addResource(ResourceId(kResourceTypeAudio36, map->_mapNumber, n & 0xffffff3f), src, offset + syncSize); } } @@ -937,13 +939,21 @@ void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource * } bool ResourceManager::addAudioSources() { +#ifdef ENABLE_SCI32 + // Multi-disc audio is added during addAppropriateSources for those titles + // that require it + if (_multiDiscAudio) { + return true; + } +#endif + Common::List<ResourceId> resources = listResources(kResourceTypeMap); Common::List<ResourceId>::iterator itr; for (itr = resources.begin(); itr != resources.end(); ++itr) { - ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->getNumber())); + ResourceSource *src = addSource(new IntMapResourceSource("MAP", 0, itr->getNumber())); - if ((itr->getNumber() == 65535) && Common::File::exists("RESOURCE.SFX")) + if (itr->getNumber() == 65535 && Common::File::exists("RESOURCE.SFX")) addSource(new AudioVolumeResourceSource(this, "RESOURCE.SFX", src, 0)); else if (Common::File::exists("RESOURCE.AUD")) addSource(new AudioVolumeResourceSource(this, "RESOURCE.AUD", src, 0)); @@ -991,7 +1001,7 @@ void ResourceManager::changeAudioDirectory(Common::String path) { if ((it->getNumber() == 65535)) continue; - ResourceSource *src = addSource(new IntMapResourceSource(mapName, it->getNumber())); + ResourceSource *src = addSource(new IntMapResourceSource(mapName, 0, it->getNumber())); addSource(new AudioVolumeResourceSource(this, audioResourceName, src, 0)); } diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 461d684005..fe4b0a97f4 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -134,8 +134,9 @@ public: class IntMapResourceSource : public ResourceSource { public: - IntMapResourceSource(const Common::String &name, int volNum) - : ResourceSource(kSourceIntMap, name, volNum) { + uint16 _mapNumber; + IntMapResourceSource(const Common::String &name, int volNum, int mapNum) + : ResourceSource(kSourceIntMap, name, volNum), _mapNumber(mapNum) { } virtual void scanSource(ResourceManager *resMan); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 3ea2756f56..86c0cffe15 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -65,23 +65,20 @@ #ifdef ENABLE_SCI32 #include "sci/graphics/controls32.h" +#include "sci/graphics/cursor32.h" #include "sci/graphics/frameout.h" #include "sci/graphics/palette32.h" #include "sci/graphics/remap32.h" #include "sci/graphics/text32.h" +#include "sci/graphics/transitions32.h" #include "sci/graphics/video32.h" #include "sci/sound/audio32.h" -// TODO: Move this to video32 -#include "sci/video/robot_decoder.h" #endif namespace Sci { SciEngine *g_sci = 0; - -class GfxDriver; - SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId) : Engine(syst), _gameDescription(desc), _gameId(gameId), _rng("sci") { @@ -95,6 +92,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam #ifdef ENABLE_SCI32 _audio32 = nullptr; _video32 = nullptr; + _gfxCursor32 = nullptr; #endif _features = 0; _resMan = 0; @@ -129,6 +127,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded"); DebugMan.addDebugChannel(kDebugLevelScriptPatcher, "ScriptPatcher", "Notifies when scripts are patched"); DebugMan.addDebugChannel(kDebugLevelWorkarounds, "Workarounds", "Notifies when workarounds are triggered"); + DebugMan.addDebugChannel(kDebugLevelVideo, "Video", "Video (SEQ, VMD, RBT) debugging"); DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging"); DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); @@ -170,12 +169,13 @@ SciEngine::~SciEngine() { delete _gfxControls32; delete _gfxPaint32; delete _gfxText32; - delete _robotDecoder; // GfxFrameout and GfxPalette32 must be deleted after Video32 since // destruction of screen items in the Video32 destructor relies on these // components delete _video32; + delete _gfxCursor32; delete _gfxPalette32; + delete _gfxTransitions32; delete _gfxFrameout; delete _gfxRemap32; delete _audio32; @@ -242,35 +242,31 @@ Common::Error SciEngine::run() { _scriptPatcher = new ScriptPatcher(); SegManager *segMan = new SegManager(_resMan, _scriptPatcher); - // Read user option for hires graphics + // Read user option for forcing hires graphics // Only show/selectable for: // - King's Quest 6 CD // - King's Quest 6 CD demo // - Gabriel Knight 1 CD // - Police Quest 4 CD // TODO: Check, if Gabriel Knight 1 floppy supports high resolution - // TODO: Check, if Gabriel Knight 1 on Mac supports high resolution - switch (getPlatform()) { - case Common::kPlatformDOS: - case Common::kPlatformWindows: - // Only DOS+Windows - switch (_gameId) { - case GID_KQ6: - case GID_GK1: - case GID_PQ4: - if (isCD()) - _forceHiresGraphics = ConfMan.getBool("enable_high_resolution_graphics"); - break; - default: - break; - } - default: - break; - }; + // + // Gabriel Knight 1 on Mac is hi-res only, so it should NOT get this option. + // Confirmed by [md5] and originally by clone2727. + if (Common::checkGameGUIOption(GAMEOPTION_HIGH_RESOLUTION_GRAPHICS, ConfMan.get("guioptions"))) { + // GAMEOPTION_HIGH_RESOLUTION_GRAPHICS is available for the currently detected game, + // so read the user option now. + // We need to do this, because the option's default is "true", but we don't want "true" + // for any game that does not have this option. + _forceHiresGraphics = ConfMan.getBool("enable_high_resolution_graphics"); + } - // Initialize the game screen - _gfxScreen = new GfxScreen(_resMan); - _gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering")); + if (getSciVersion() < SCI_VERSION_2) { + // Initialize the game screen + _gfxScreen = new GfxScreen(_resMan); + _gfxScreen->enableUndithering(ConfMan.getBool("disable_dithering")); + } else { + _gfxScreen = nullptr; + } _kernel = new Kernel(_resMan, segMan); _kernel->init(); @@ -707,11 +703,12 @@ void SciEngine::initGraphics() { #ifdef ENABLE_SCI32 _gfxControls32 = 0; _gfxText32 = 0; - _robotDecoder = 0; _gfxFrameout = 0; _gfxPaint32 = 0; _gfxPalette32 = 0; _gfxRemap32 = 0; + _gfxTransitions32 = 0; + _gfxCursor32 = 0; #endif if (hasMacIconBar()) @@ -731,23 +728,23 @@ void SciEngine::initGraphics() { #endif _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette16); - _gfxCursor = new GfxCursor(_resMan, _gfxPalette16, _gfxScreen); #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { // SCI32 graphic objects creation - _gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan); - _gfxCursor->init(_gfxCoordAdjuster, _eventMan); - _gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxCursor32 = new GfxCursor32(); + _gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, nullptr, _gfxCoordAdjuster); _gfxPaint32 = new GfxPaint32(_gamestate->_segMan); - _robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh); - _gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxScreen, _gfxPalette32); + _gfxTransitions32 = new GfxTransitions32(_gamestate->_segMan); + _gfxFrameout = new GfxFrameout(_gamestate->_segMan, _gfxPalette32, _gfxTransitions32, _gfxCursor32); + _gfxCursor32->init(_gfxFrameout->getCurrentBuffer()); _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache); _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32); _gfxFrameout->run(); } else { #endif // SCI0-SCI1.1 graphic objects creation + _gfxCursor = new GfxCursor(_resMan, _gfxPalette16, _gfxScreen); _gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen); _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); _gfxCursor->init(_gfxCoordAdjuster, _eventMan); @@ -926,14 +923,19 @@ Common::String SciEngine::getFilePrefix() const { } Common::String SciEngine::wrapFilename(const Common::String &name) const { - return getFilePrefix() + "-" + name; + Common::String prefix = getFilePrefix() + "-"; + if (name.hasPrefix(prefix.c_str())) + return name; + else + return prefix + name; } Common::String SciEngine::unwrapFilename(const Common::String &name) const { Common::String prefix = getFilePrefix() + "-"; if (name.hasPrefix(prefix.c_str())) return Common::String(name.c_str() + prefix.size()); - return name; + else + return name; } const char *SciEngine::getGameObjectName() { @@ -1038,17 +1040,19 @@ void SciEngine::syncIngameAudioOptions() { case GID_SQ6: // SCI2.1 case GID_TORIN: // SCI2.1 case GID_QFG4: // SCI2.1 + case GID_PQ4: // SCI2 + case GID_PHANTASMAGORIA: // SCI2.1 + case GID_MOTHERGOOSEHIRES: // SCI2.1 useGlobal90 = true; break; case GID_LSL6: // SCI2.1 // TODO: Uses gameFlags array break; + // Shivers does not use global 90 + // Police Quest: SWAT does not use global 90 + // // TODO: Unknown at the moment: - // Shivers - seems not to use global 90 - // Police Quest: SWAT - unable to check - // Police Quest 4 - unable to check - // Mixed Up Mother Goose - unable to check - // Phantasmagoria - seems to use global 90, unable to check for subtitles atm + // LSL7, Lighthouse, RAMA, Phantasmagoria 2 default: return; } @@ -1082,6 +1086,9 @@ void SciEngine::syncIngameAudioOptions() { case GID_SQ6: // SCI2.1, SQ6 seems to always use subtitles anyway case GID_TORIN: // SCI2.1 case GID_QFG4: // SCI2.1 + case GID_PQ4: // SCI2 + // Phantasmagoria does not support simultaneous speech + subtitles + // Mixed Up Mother Goose Deluxe does not support simultaneous speech + subtitles #endif // ENABLE_SCI32 _gamestate->variables[VAR_GLOBAL][90] = make_reg(0, 3); // speech + subtitles break; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 0020d25b91..b336eb8cce 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -45,6 +45,18 @@ struct ADGameDescription; */ namespace Sci { +// GUI-options, primarily used by detection_tables.h +#define GAMEOPTION_PREFER_DIGITAL_SFX GUIO_GAMEOPTIONS1 +#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS2 +#define GAMEOPTION_FB01_MIDI GUIO_GAMEOPTIONS3 +#define GAMEOPTION_JONES_CDAUDIO GUIO_GAMEOPTIONS4 +#define GAMEOPTION_KQ6_WINDOWS_CURSORS GUIO_GAMEOPTIONS5 +#define GAMEOPTION_SQ4_SILVER_CURSORS GUIO_GAMEOPTIONS6 +#define GAMEOPTION_EGA_UNDITHER GUIO_GAMEOPTIONS7 +// HIGH_RESOLUTION_GRAPHICS availability is checked for in SciEngine::run() +#define GAMEOPTION_HIGH_RESOLUTION_GRAPHICS GUIO_GAMEOPTIONS8 +#define GAMEOPTION_ENABLE_BLACK_LINED_VIDEO GUIO_GAMEOPTIONS9 + struct EngineState; class Vocabulary; class ResourceManager; @@ -63,7 +75,7 @@ class GfxCache; class GfxCompare; class GfxControls16; class GfxControls32; -class GfxCoordAdjuster; +class GfxCoordAdjuster16; class GfxCursor; class GfxMacIconBar; class GfxMenu; @@ -80,11 +92,11 @@ class GfxText32; class GfxTransitions; #ifdef ENABLE_SCI32 -// TODO: Move RobotDecoder to Video32 -class RobotDecoder; class GfxFrameout; class Audio32; class Video32; +class GfxTransitions32; +class GfxCursor32; #endif // our engine debug levels @@ -112,7 +124,8 @@ enum kDebugLevels { kDebugLevelOnStartup = 1 << 20, kDebugLevelDebugMode = 1 << 21, kDebugLevelScriptPatcher = 1 << 22, - kDebugLevelWorkarounds = 1 << 23 + kDebugLevelWorkarounds = 1 << 23, + kDebugLevelVideo = 1 << 24 }; enum SciGameId { @@ -356,7 +369,7 @@ public: GfxCompare *_gfxCompare; GfxControls16 *_gfxControls16; // Controls for 16-bit gfx GfxControls32 *_gfxControls32; // Controls for 32-bit gfx - GfxCoordAdjuster *_gfxCoordAdjuster; + GfxCoordAdjuster16 *_gfxCoordAdjuster; GfxCursor *_gfxCursor; GfxMenu *_gfxMenu; // Menu for 16-bit gfx GfxPalette *_gfxPalette16; @@ -375,8 +388,9 @@ public: #ifdef ENABLE_SCI32 Audio32 *_audio32; Video32 *_video32; - RobotDecoder *_robotDecoder; GfxFrameout *_gfxFrameout; // kFrameout and the like for 32-bit gfx + GfxTransitions32 *_gfxTransitions32; + GfxCursor32 *_gfxCursor32; #endif AudioPlayer *_audio; diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp index 0cf8e3cb13..4af474b918 100644 --- a/engines/sci/sound/audio32.cpp +++ b/engines/sci/sound/audio32.cpp @@ -164,7 +164,7 @@ Audio32::~Audio32() { #pragma mark - #pragma mark AudioStream implementation -int Audio32::writeAudioInternal(Audio::RewindableAudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume, const bool loop) { +int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume, const bool loop) { int samplesToRead = numSamples; // The parent rate converter will request N * 2 @@ -182,7 +182,8 @@ int Audio32::writeAudioInternal(Audio::RewindableAudioStream *const sourceStream do { if (loop && sourceStream->endOfStream()) { - sourceStream->rewind(); + Audio::RewindableAudioStream *rewindableStream = dynamic_cast<Audio::RewindableAudioStream *>(sourceStream); + rewindableStream->rewind(); } const int loopSamplesWritten = converter->flow(*sourceStream, targetBuffer, samplesToRead, leftVolume, rightVolume); @@ -305,12 +306,14 @@ int Audio32::readBuffer(Audio::st_sample_t *buffer, const int numSamples) { } if (channel.robot) { - // TODO: Robot audio into output buffer - continue; - } - - if (channel.vmd) { - // TODO: VMD audio into output buffer + if (channel.stream->endOfStream()) { + stop(channelIndex--); + } else { + const int channelSamplesWritten = writeAudioInternal(channel.stream, channel.converter, buffer, numSamples, kMaxVolume, kMaxVolume, channel.loop); + if (channelSamplesWritten > maxSamplesWritten) { + maxSamplesWritten = channelSamplesWritten; + } + } continue; } @@ -448,9 +451,9 @@ void Audio32::freeUnusedChannels() { Common::StackLock lock(_mutex); for (int channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) { const AudioChannel &channel = getChannel(channelIndex); - if (channel.stream->endOfStream()) { + if (!channel.robot && channel.stream->endOfStream()) { if (channel.loop) { - channel.stream->rewind(); + dynamic_cast<Audio::SeekableAudioStream *>(channel.stream)->rewind(); } else { stop(channelIndex--); } @@ -471,21 +474,29 @@ void Audio32::freeChannel(const int16 channelIndex) { Common::StackLock lock(_mutex); AudioChannel &channel = getChannel(channelIndex); - // We cannot unlock resources from the audio thread - // because ResourceManager is not thread-safe; instead, - // we just record that the resource needs unlocking and - // unlock it whenever we are on the main thread again - if (_inAudioThread) { - _resourcesToUnlock.push_back(channel.resource); + // Robots have no corresponding resource to free + if (channel.robot) { + delete channel.stream; + channel.stream = nullptr; + channel.robot = false; } else { - _resMan->unlockResource(channel.resource); + // We cannot unlock resources from the audio thread + // because ResourceManager is not thread-safe; instead, + // we just record that the resource needs unlocking and + // unlock it whenever we are on the main thread again + if (_inAudioThread) { + _resourcesToUnlock.push_back(channel.resource); + } else { + _resMan->unlockResource(channel.resource); + } + + channel.resource = nullptr; + delete channel.stream; + channel.stream = nullptr; + delete channel.resourceStream; + channel.resourceStream = nullptr; } - channel.resource = nullptr; - delete channel.stream; - channel.stream = nullptr; - delete channel.resourceStream; - channel.resourceStream = nullptr; delete channel.converter; channel.converter = nullptr; @@ -532,6 +543,111 @@ void Audio32::setNumOutputChannels(int16 numChannels) { } #pragma mark - +#pragma mark Robot + +int16 Audio32::findRobotChannel() const { + Common::StackLock lock(_mutex); + for (int16 i = 0; i < _numActiveChannels; ++i) { + if (_channels[i].robot) { + return i; + } + } + + return kNoExistingChannel; +} + +bool Audio32::playRobotAudio(const RobotAudioStream::RobotAudioPacket &packet) { + // Stop immediately + if (packet.dataSize == 0) { + warning("Stopping robot stream by zero-length packet"); + return stopRobotAudio(); + } + + // Flush and then stop + if (packet.dataSize == -1) { + warning("Stopping robot stream by negative-length packet"); + return finishRobotAudio(); + } + + Common::StackLock lock(_mutex); + int16 channelIndex = findRobotChannel(); + + bool isNewChannel = false; + if (channelIndex == kNoExistingChannel) { + if (_numActiveChannels == _channels.size()) { + return false; + } + + channelIndex = _numActiveChannels++; + isNewChannel = true; + } + + AudioChannel &channel = getChannel(channelIndex); + + if (isNewChannel) { + channel.id = ResourceId(); + channel.resource = nullptr; + channel.loop = false; + channel.robot = true; + channel.fadeStartTick = 0; + channel.pausedAtTick = 0; + channel.soundNode = NULL_REG; + channel.volume = kMaxVolume; + // TODO: SCI3 introduces stereo audio + channel.pan = -1; + channel.converter = Audio::makeRateConverter(RobotAudioStream::kRobotSampleRate, getRate(), false); + // The RobotAudioStream buffer size is + // ((bytesPerSample * channels * sampleRate * 2000ms) / 1000ms) & ~3 + // where bytesPerSample = 2, channels = 1, and sampleRate = 22050 + channel.stream = new RobotAudioStream(88200); + _robotAudioPaused = false; + + if (_numActiveChannels == 1) { + _startedAtTick = g_sci->getTickCount(); + } + } + + return static_cast<RobotAudioStream *>(channel.stream)->addPacket(packet); +} + +bool Audio32::queryRobotAudio(RobotAudioStream::StreamState &status) const { + Common::StackLock lock(_mutex); + + const int16 channelIndex = findRobotChannel(); + if (channelIndex == kNoExistingChannel) { + status.bytesPlaying = 0; + return false; + } + + status = static_cast<RobotAudioStream *>(getChannel(channelIndex).stream)->getStatus(); + return true; +} + +bool Audio32::finishRobotAudio() { + Common::StackLock lock(_mutex); + + const int16 channelIndex = findRobotChannel(); + if (channelIndex == kNoExistingChannel) { + return false; + } + + static_cast<RobotAudioStream *>(getChannel(channelIndex).stream)->finish(); + return true; +} + +bool Audio32::stopRobotAudio() { + Common::StackLock lock(_mutex); + + const int16 channelIndex = findRobotChannel(); + if (channelIndex == kNoExistingChannel) { + return false; + } + + stop(channelIndex); + return true; +} + +#pragma mark - #pragma mark Playback uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool autoPlay, const bool loop, const int16 volume, const reg_t soundNode, const bool monitor) { @@ -541,14 +657,15 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool if (channelIndex != kNoExistingChannel) { AudioChannel &channel = getChannel(channelIndex); + Audio::SeekableAudioStream *stream = dynamic_cast<Audio::SeekableAudioStream *>(channel.stream); if (channel.pausedAtTick) { resume(channelIndex); - return MIN(65534, 1 + channel.stream->getLength().msecs() * 60 / 1000); + return MIN(65534, 1 + stream->getLength().msecs() * 60 / 1000); } warning("Tried to resume channel %s that was not paused", channel.id.toString().c_str()); - return MIN(65534, 1 + channel.stream->getLength().msecs() * 60 / 1000); + return MIN(65534, 1 + stream->getLength().msecs() * 60 / 1000); } if (_numActiveChannels == _channels.size()) { @@ -605,7 +722,6 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool channel.resource = resource; channel.loop = loop; channel.robot = false; - channel.vmd = false; channel.fadeStartTick = 0; channel.soundNode = soundNode; channel.volume = volume < 0 || volume > kMaxVolume ? (int)kMaxVolume : volume; @@ -648,7 +764,7 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool // use audio streams, and allocate and fill the monitoring buffer // when reading audio data from the stream. - channel.duration = /* round up */ 1 + (channel.stream->getLength().msecs() * 60 / 1000); + channel.duration = /* round up */ 1 + (dynamic_cast<Audio::SeekableAudioStream *>(channel.stream)->getLength().msecs() * 60 / 1000); const uint32 now = g_sci->getTickCount(); channel.pausedAtTick = autoPlay ? 0 : now; @@ -693,8 +809,6 @@ bool Audio32::resume(const int16 channelIndex) { if (channel.robot) { channel.startedAtTick += now - channel.pausedAtTick; channel.pausedAtTick = 0; - // TODO: Robot - // StartRobot(); return true; } } diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h index b0c1ba1998..a9905ab6bf 100644 --- a/engines/sci/sound/audio32.h +++ b/engines/sci/sound/audio32.h @@ -30,8 +30,10 @@ #include "common/scummsys.h" // for int16, uint8, uint32, uint16 #include "engines/sci/resource.h" // for ResourceId #include "sci/engine/vm_types.h" // for reg_t, NULL_REG +#include "sci/video/robot_decoder.h" // for RobotAudioStream namespace Sci { +#pragma mark AudioChannel /** * An audio channel used by the software SCI mixer. @@ -53,14 +55,11 @@ struct AudioChannel { Common::SeekableReadStream *resourceStream; /** - * The audio stream loaded into this channel. - * `SeekableAudioStream` is used here instead of - * `RewindableAudioStream` because - * `RewindableAudioStream` does not include the - * `getLength` function, which is needed to tell the - * game engine the duration of audio streams. + * The audio stream loaded into this channel. Can cast + * to `SeekableAudioStream` for normal channels and + * `RobotAudioStream` for robot channels. */ - Audio::SeekableAudioStream *stream; + Audio::AudioStream *stream; /** * The converter used to transform and merge the input @@ -123,12 +122,6 @@ struct AudioChannel { bool robot; /** - * Whether or not this channel contains a VMD audio - * track. - */ - bool vmd; - - /** * For digital sound effects, the related VM * Sound::nodePtr object for the sound. */ @@ -194,7 +187,7 @@ private: * Mixes audio from the given source stream into the * target buffer using the given rate converter. */ - int writeAudioInternal(Audio::RewindableAudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume, const bool loop); + int writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume, const bool loop); #pragma mark - #pragma mark Channel management @@ -401,9 +394,18 @@ private: #pragma mark - #pragma mark Robot public: + bool playRobotAudio(const RobotAudioStream::RobotAudioPacket &packet); + bool queryRobotAudio(RobotAudioStream::StreamState &outStatus) const; + bool finishRobotAudio(); + bool stopRobotAudio(); private: /** + * Finds a channel that is configured for robot playback. + */ + int16 findRobotChannel() const; + + /** * When true, channels marked as robot audio will not be * played. */ diff --git a/engines/sci/sound/decoders/sol.cpp b/engines/sci/sound/decoders/sol.cpp index e445403120..ee1ba35406 100644 --- a/engines/sci/sound/decoders/sol.cpp +++ b/engines/sci/sound/decoders/sol.cpp @@ -21,6 +21,7 @@ */ #include "audio/audiostream.h" +#include "audio/rate.h" #include "audio/decoders/raw.h" #include "common/substream.h" #include "common/util.h" @@ -52,7 +53,7 @@ static const byte tableDPCM8[8] = { 0, 1, 2, 3, 6, 10, 15, 21 }; * Decompresses 16-bit DPCM compressed audio. Each byte read * outputs one sample into the decompression buffer. */ -static void deDPCM16(int16 *out, Common::ReadStream &audioStream, uint32 numBytes, int16 &sample) { +static void deDPCM16(int16 *out, Common::ReadStream &audioStream, const uint32 numBytes, int16 &sample) { for (uint32 i = 0; i < numBytes; ++i) { const uint8 delta = audioStream.readByte(); if (delta & 0x80) { @@ -65,6 +66,19 @@ static void deDPCM16(int16 *out, Common::ReadStream &audioStream, uint32 numByte } } +void deDPCM16(int16 *out, const byte *in, const uint32 numBytes, int16 &sample) { + for (uint32 i = 0; i < numBytes; ++i) { + const uint8 delta = *in++; + if (delta & 0x80) { + sample -= tableDPCM16[delta & 0x7f]; + } else { + sample += tableDPCM16[delta]; + } + sample = CLIP<int16>(sample, -32768, 32767); + *out++ = TO_LE_16(sample); + } +} + /** * Decompresses one half of an 8-bit DPCM compressed audio * byte. @@ -178,7 +192,7 @@ int SOLStream<STEREO, S16BIT>::getRate() const { template <bool STEREO, bool S16BIT> bool SOLStream<STEREO, S16BIT>::endOfData() const { - return _stream->eos() || _stream->pos() >= _dataOffset + _rawDataSize; + return _stream->eos() || _stream->pos() >= _rawDataSize; } template <bool STEREO, bool S16BIT> @@ -269,5 +283,4 @@ Audio::SeekableAudioStream *makeSOLStream(Common::SeekableReadStream *headerStre return Audio::makeRawStream(dataStream, sampleRate, rawFlags, disposeAfterUse); } - } diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index a2795d21f9..1757088ea4 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -20,391 +20,1597 @@ * */ -#include "common/archive.h" -#include "common/stream.h" -#include "common/substream.h" -#include "common/system.h" -#include "common/textconsole.h" -#include "common/util.h" - -#include "graphics/surface.h" -#include "audio/audiostream.h" -#include "audio/decoders/raw.h" - -#include "sci/resource.h" -#include "sci/util.h" -#include "sci/sound/audio.h" #include "sci/video/robot_decoder.h" +#include "common/archive.h" // for SearchMan +#include "common/debug.h" // for debugC +#include "common/endian.h" // for MKTAG +#include "common/memstream.h" // for MemoryReadStream +#include "common/platform.h" // for Platform::kPlatformMacintosh +#include "common/rational.h" // for operator*, Rational +#include "common/str.h" // for String +#include "common/stream.h" // for SeekableReadStream +#include "common/substream.h" // for SeekableSubReadStreamEndian +#include "common/textconsole.h" // for error, warning +#include "common/types.h" // for Flag::NO, Flag::YES +#include "sci/engine/seg_manager.h" // for SegManager +#include "sci/graphics/celobj32.h" // for Ratio, ::kLowResX, ::kLowResY +#include "sci/graphics/text32.h" // for BitmapResource +#include "sci/sound/audio32.h" // for Audio32 +#include "sci/sci.h" // for kDebugLevels::kDebugLevelVideo +#include "sci/util.h" // for READ_SCI11ENDIAN_UINT16, READ_SC... namespace Sci { -// TODO: -// - Positioning -// - Proper handling of frame scaling - scaled frames look squashed -// (probably because both dimensions should be scaled) -// - Transparency support -// - Timing - the arbitrary 100ms delay between each frame is not quite right -// - Proper handling of sound chunks in some cases, so that the frame size -// table can be ignored (it's only used to determine the correct sound chunk -// size at the moment, cause it can be wrong in some cases) -// - Fix audio "hiccups" - probably data that shouldn't be in the audio frames - - -// Some non technical information on robot files, from an interview with -// Greg Tomko-Pavia of Sierra On-Line -// Taken from http://anthonylarme.tripod.com/phantas/phintgtp.html -// -// (...) What we needed was a way of playing video, but have it blend into -// normal room art instead of occupying its own rectangular area. Room art -// consists of a background pic overlaid with various animating cels -// (traditional lingo: sprites). The cels each have a priority that determines -// who is on top and who is behind in the drawing order. Cels are read from -// *.v56 files (another proprietary format). A Robot is video frames with -// transparent background including priority and x,y information. Thus, it is -// like a cel, except it comes from an RBT - not a v56. Because it blends into -// our graphics engine, it looks just like a part of the room. A RBT can move -// around the screen and go behind other objects. (...) - -enum RobotPalTypes { - kRobotPalVariable = 0, - kRobotPalConstant = 1 -}; - -RobotDecoder::RobotDecoder(bool isBigEndian) { - _fileStream = 0; - _pos = Common::Point(0, 0); - _isBigEndian = isBigEndian; - _frameTotalSize = 0; +#pragma mark RobotAudioStream + +extern void deDPCM16(int16 *out, const byte *in, const uint32 numBytes, int16 &sample); + +RobotAudioStream::RobotAudioStream(const int32 bufferSize) : + _loopBuffer((byte *)malloc(bufferSize)), + _loopBufferSize(bufferSize), + _decompressionBuffer(nullptr), + _decompressionBufferSize(0), + _decompressionBufferPosition(-1), + _waiting(true), + _finished(false), + _firstPacketPosition(-1) {} + +RobotAudioStream::~RobotAudioStream() { + free(_loopBuffer); + free(_decompressionBuffer); } -RobotDecoder::~RobotDecoder() { - close(); +static void interpolateChannel(int16 *buffer, int32 numSamples, const int8 bufferIndex) { + if (numSamples <= 0) { + return; + } + + if (bufferIndex) { + int16 lastSample = *buffer; + int sample = lastSample; + int16 *target = buffer + 1; + const int16 *source = buffer + 2; + --numSamples; + + while (numSamples--) { + sample = *source + lastSample; + lastSample = *source; + sample /= 2; + *target = sample; + source += 2; + target += 2; + } + + *target = sample; + } else { + int16 *target = buffer; + const int16 *source = buffer + 1; + int16 lastSample = *source; + + while (numSamples--) { + int sample = *source + lastSample; + lastSample = *source; + sample /= 2; + *target = sample; + source += 2; + target += 2; + } + } } -bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) { - close(); +static void copyEveryOtherSample(int16 *out, const int16 *in, int numSamples) { + while (numSamples--) { + *out = *in++; + out += 2; + } +} + +bool RobotAudioStream::addPacket(const RobotAudioPacket &packet) { + Common::StackLock lock(_mutex); + + if (_finished) { + warning("Packet %d sent to finished robot audio stream", packet.position); + return false; + } + + // `packet.position` is the decompressed (doubled) position of the packet, + // so values of `position` will always be divisible either by 2 (even) or by + // 4 (odd). + const int8 bufferIndex = packet.position % 4 ? 1 : 0; + + // Packet 0 is the first primer, packet 2 is the second primer, + // packet 4+ are regular audio data + if (packet.position <= 2 && _firstPacketPosition == -1) { + _readHead = 0; + _readHeadAbs = 0; + _maxWriteAbs = _loopBufferSize; + _writeHeadAbs = 2; + _jointMin[0] = 0; + _jointMin[1] = 2; + _waiting = true; + _finished = false; + _firstPacketPosition = packet.position; + fillRobotBuffer(packet, bufferIndex); + return true; + } - _fileStream = new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), _isBigEndian, DisposeAfterUse::YES); + const int32 packetEndByte = packet.position + (packet.dataSize * sizeof(int16) * kEOSExpansion); - readHeaderChunk(); + // Already read all the way past this packet (or already wrote valid samples + // to this channel all the way past this packet), so discard it + if (packetEndByte <= MAX(_readHeadAbs, _jointMin[bufferIndex])) { + debugC(kDebugLevelVideo, "Rejecting packet %d, read past %d / %d", packet.position, _readHeadAbs, _jointMin[bufferIndex]); + return true; + } - // There are several versions of robot files, ranging from 3 to 6. - // v3: no known examples - // v4: PQ:SWAT demo - // v5: SCI2.1 and SCI3 games - // v6: SCI3 games - if (_header.version < 4 || _header.version > 6) - error("Unknown robot version: %d", _header.version); + // The loop buffer is full, so tell the caller to send the packet again + // later + if (_maxWriteAbs <= _jointMin[bufferIndex]) { + debugC(kDebugLevelVideo, "Rejecting packet %d, full buffer", packet.position); + return false; + } - RobotVideoTrack *videoTrack = new RobotVideoTrack(_header.frameCount); - addTrack(videoTrack); + fillRobotBuffer(packet, bufferIndex); - if (_header.hasSound) - addTrack(new RobotAudioTrack()); + // This packet is the second primer, so allow playback to begin + if (_firstPacketPosition != -1 && _firstPacketPosition != packet.position) { + debugC(kDebugLevelVideo, "Done waiting. Robot audio begins"); + _waiting = false; + _firstPacketPosition = -1; + } - videoTrack->readPaletteChunk(_fileStream, _header.paletteDataSize); - readFrameSizesChunk(); - videoTrack->calculateVideoDimensions(_fileStream, _frameTotalSize); + // Only part of the packet could be read into the loop buffer before it was + // full, so tell the caller to send the packet again later + if (packetEndByte > _maxWriteAbs) { + debugC(kDebugLevelVideo, "Partial read of packet %d (%d / %d)", packet.position, packetEndByte - _maxWriteAbs, packetEndByte - packet.position); + return false; + } + + // The entire packet was successfully read into the loop buffer return true; } -bool RobotDecoder::load(GuiResourceId id) { - // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) - - // its drawn at odd coordinates. SV can't play it either (along with some - // others), so it must be some new functionality added in RAMA's robot - // videos. Skip it for now. - if (g_sci->getGameId() == GID_RAMA && id == 1003) - return false; +void RobotAudioStream::fillRobotBuffer(const RobotAudioPacket &packet, const int8 bufferIndex) { + int32 sourceByte = 0; - // Robots for the options in the RAMA menu - if (g_sci->getGameId() == GID_RAMA && (id >= 1004 && id <= 1009)) - return false; + const int32 decompressedSize = packet.dataSize * sizeof(int16); + if (_decompressionBufferPosition != packet.position) { + if (decompressedSize != _decompressionBufferSize) { + _decompressionBuffer = (byte *)realloc(_decompressionBuffer, decompressedSize); + _decompressionBufferSize = decompressedSize; + } - // TODO: The robot video in the Lighthouse demo gets stuck - if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16) - return false; + int16 carry = 0; + deDPCM16((int16 *)_decompressionBuffer, packet.data, packet.dataSize, carry); + _decompressionBufferPosition = packet.position; + } + + int32 numBytes = decompressedSize; + int32 packetPosition = packet.position; + int32 endByte = packet.position + decompressedSize * kEOSExpansion; + int32 startByte = MAX(_readHeadAbs + bufferIndex * 2, _jointMin[bufferIndex]); + int32 maxWriteByte = _maxWriteAbs + bufferIndex * 2; + if (packetPosition < startByte) { + sourceByte = (startByte - packetPosition) / kEOSExpansion; + numBytes -= sourceByte; + packetPosition = startByte; + } + if (packetPosition > maxWriteByte) { + numBytes += (packetPosition - maxWriteByte) / kEOSExpansion; + packetPosition = maxWriteByte; + } + if (endByte > maxWriteByte) { + numBytes -= (endByte - maxWriteByte) / kEOSExpansion; + endByte = maxWriteByte; + } - Common::String fileName = Common::String::format("%d.rbt", id); + const int32 maxJointMin = MAX(_jointMin[0], _jointMin[1]); + if (endByte > maxJointMin) { + _writeHeadAbs += endByte - maxJointMin; + } + + if (packetPosition > _jointMin[bufferIndex]) { + int32 packetEndByte = packetPosition % _loopBufferSize; + int32 targetBytePosition; + int32 numBytesToEnd; + if ((packetPosition & ~3) > (_jointMin[1 - bufferIndex] & ~3)) { + targetBytePosition = _jointMin[1 - bufferIndex] % _loopBufferSize; + if (targetBytePosition >= packetEndByte) { + numBytesToEnd = _loopBufferSize - targetBytePosition; + memset(_loopBuffer + targetBytePosition, 0, numBytesToEnd); + targetBytePosition = (1 - bufferIndex) ? 2 : 0; + } + numBytesToEnd = packetEndByte - targetBytePosition; + if (numBytesToEnd > 0) { + memset(_loopBuffer + targetBytePosition, 0, numBytesToEnd); + } + } + targetBytePosition = _jointMin[bufferIndex] % _loopBufferSize; + if (targetBytePosition >= packetEndByte) { + numBytesToEnd = _loopBufferSize - targetBytePosition; + interpolateChannel((int16 *)(_loopBuffer + targetBytePosition), numBytesToEnd / sizeof(int16) / kEOSExpansion, 0); + targetBytePosition = bufferIndex ? 2 : 0; + } + numBytesToEnd = packetEndByte - targetBytePosition; + if (numBytesToEnd > 0) { + interpolateChannel((int16 *)(_loopBuffer + targetBytePosition), numBytesToEnd / sizeof(int16) / kEOSExpansion, 0); + } + } + + if (numBytes > 0) { + int32 targetBytePosition = packetPosition % _loopBufferSize; + int32 packetEndByte = endByte % _loopBufferSize; + int32 numBytesToEnd = 0; + if (targetBytePosition >= packetEndByte) { + numBytesToEnd = (_loopBufferSize - (targetBytePosition & ~3)) / kEOSExpansion; + copyEveryOtherSample((int16 *)(_loopBuffer + targetBytePosition), (int16 *)(_decompressionBuffer + sourceByte), numBytesToEnd / kEOSExpansion); + targetBytePosition = bufferIndex ? 2 : 0; + } + copyEveryOtherSample((int16 *)(_loopBuffer + targetBytePosition), (int16 *)(_decompressionBuffer + sourceByte + numBytesToEnd), (packetEndByte - targetBytePosition) / sizeof(int16) / kEOSExpansion); + } + _jointMin[bufferIndex] = endByte; +} + +void RobotAudioStream::interpolateMissingSamples(int32 numSamples) { + int32 numBytes = numSamples * sizeof(int16) * kEOSExpansion; + int32 targetPosition = _readHead; + + if (_readHeadAbs > _jointMin[1]) { + if (_readHeadAbs > _jointMin[0]) { + if (targetPosition + numBytes >= _loopBufferSize) { + const int32 numBytesToEdge = (_loopBufferSize - targetPosition); + memset(_loopBuffer + targetPosition, 0, numBytesToEdge); + numBytes -= numBytesToEdge; + targetPosition = 0; + } + memset(_loopBuffer + targetPosition, 0, numBytes); + _jointMin[0] += numBytes; + _jointMin[1] += numBytes; + } else { + if (targetPosition + numBytes >= _loopBufferSize) { + const int32 numSamplesToEdge = (_loopBufferSize - targetPosition) / sizeof(int16) / kEOSExpansion; + interpolateChannel((int16 *)(_loopBuffer + targetPosition), numSamplesToEdge, 1); + numSamples -= numSamplesToEdge; + targetPosition = 0; + } + interpolateChannel((int16 *)(_loopBuffer + targetPosition), numSamples, 1); + _jointMin[1] += numBytes; + } + } else if (_readHeadAbs > _jointMin[0]) { + if (targetPosition + numBytes >= _loopBufferSize) { + const int32 numSamplesToEdge = (_loopBufferSize - targetPosition) / sizeof(int16) / kEOSExpansion; + interpolateChannel((int16 *)(_loopBuffer + targetPosition), numSamplesToEdge, 0); + numSamples -= numSamplesToEdge; + targetPosition = 2; + } + interpolateChannel((int16 *)(_loopBuffer + targetPosition), numSamples, 0); + _jointMin[0] += numBytes; + } +} + +void RobotAudioStream::finish() { + Common::StackLock lock(_mutex); + _finished = true; +} + +RobotAudioStream::StreamState RobotAudioStream::getStatus() const { + Common::StackLock lock(_mutex); + StreamState status; + status.bytesPlaying = _readHeadAbs; + status.rate = getRate(); + status.bits = 8 * sizeof(int16); + return status; +} + +int RobotAudioStream::readBuffer(Audio::st_sample_t *outBuffer, int numSamples) { + Common::StackLock lock(_mutex); + + if (_waiting) { + return 0; + } + + assert(!((_writeHeadAbs - _readHeadAbs) & 1)); + const int maxNumSamples = (_writeHeadAbs - _readHeadAbs) / sizeof(Audio::st_sample_t); + numSamples = MIN(numSamples, maxNumSamples); + + if (!numSamples) { + return 0; + } + + interpolateMissingSamples(numSamples); + + Audio::st_sample_t *inBuffer = (Audio::st_sample_t *)(_loopBuffer + _readHead); + + assert(!((_loopBufferSize - _readHead) & 1)); + const int numSamplesToEnd = (_loopBufferSize - _readHead) / sizeof(Audio::st_sample_t); + + int numSamplesToRead = MIN(numSamples, numSamplesToEnd); + Common::copy(inBuffer, inBuffer + numSamplesToRead, outBuffer); + + if (numSamplesToRead < numSamples) { + inBuffer = (Audio::st_sample_t *)_loopBuffer; + outBuffer += numSamplesToRead; + numSamplesToRead = numSamples - numSamplesToRead; + Common::copy(inBuffer, inBuffer + numSamplesToRead, outBuffer); + } + + const int32 numBytes = numSamples * sizeof(Audio::st_sample_t); + + _readHead += numBytes; + if (_readHead > _loopBufferSize) { + _readHead -= _loopBufferSize; + } + _readHeadAbs += numBytes; + _maxWriteAbs += numBytes; + assert(!(_readHead & 1)); + assert(!(_readHeadAbs & 1)); + + return numSamples; +} + +#pragma mark - +#pragma mark RobotDecoder + +RobotDecoder::RobotDecoder(SegManager *segMan) : + _delayTime(this), + _segMan(segMan), + _status(kRobotStatusUninitialized), + _audioBuffer(nullptr), + _rawPalette((uint8 *)malloc(kRawPaletteSize)) {} + +RobotDecoder::~RobotDecoder() { + close(); + free(_rawPalette); + free(_audioBuffer); +} + +#pragma mark - +#pragma mark RobotDecoder - Initialization + +void RobotDecoder::initStream(const GuiResourceId robotId) { + const Common::String fileName = Common::String::format("%d.rbt", robotId); Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName); + _fileOffset = 0; - if (!stream) { - warning("Unable to open robot file %s", fileName.c_str()); - return false; + if (stream == nullptr) { + error("Unable to open robot file %s", fileName.c_str()); + } + + const uint16 id = stream->readUint16LE(); + if (id != 0x16) { + error("Invalid robot file %s", fileName.c_str()); + } + + // TODO: Mac version not tested, so this could be totally wrong + _stream = new Common::SeekableSubReadStreamEndian(stream, 0, stream->size(), g_sci->getPlatform() == Common::kPlatformMacintosh, DisposeAfterUse::YES); + _stream->seek(2, SEEK_SET); + if (_stream->readUint32BE() != MKTAG('S', 'O', 'L', 0)) { + error("Resource %s is not Robot type!", fileName.c_str()); + } +} + +void RobotDecoder::initPlayback() { + _startFrameNo = 0; + _startTime = -1; + _startingFrameNo = -1; + _cueForceShowFrame = -1; + _previousFrameNo = -1; + _currentFrameNo = 0; + _status = kRobotStatusPaused; +} + +void RobotDecoder::initAudio() { + _syncFrame = true; + + _audioRecordInterval = RobotAudioStream::kRobotSampleRate / _frameRate; + + // TODO: Might actually be for all games newer than Lighthouse; check to + // see which games have this condition. + if (g_sci->getGameId() != GID_LIGHTHOUSE && !(_audioRecordInterval & 1)) { + ++_audioRecordInterval; + } + + _expectedAudioBlockSize = _audioBlockSize - kAudioBlockHeaderSize; + _audioBuffer = (byte *)realloc(_audioBuffer, kRobotZeroCompressSize + _expectedAudioBlockSize); + + if (_primerReservedSize != 0) { + const int32 primerHeaderPosition = _stream->pos(); + _totalPrimerSize = _stream->readSint32(); + const int16 compressionType = _stream->readSint16(); + _evenPrimerSize = _stream->readSint32(); + _oddPrimerSize = _stream->readSint32(); + _primerPosition = _stream->pos(); + + if (compressionType) { + error("Unknown audio header compression type %d", compressionType); + } + + if (_evenPrimerSize + _oddPrimerSize != _primerReservedSize) { + _stream->seek(primerHeaderPosition + _primerReservedSize, SEEK_SET); + } + } else if (_primerZeroCompressFlag) { + _evenPrimerSize = 19922; + _oddPrimerSize = 21024; + } + + _firstAudioRecordPosition = _evenPrimerSize * 2; + + const int usedEachFrame = (RobotAudioStream::kRobotSampleRate / 2) / _frameRate; + _maxSkippablePackets = MAX(0, _audioBlockSize / usedEachFrame - 1); +} + +void RobotDecoder::initVideo(const int16 x, const int16 y, const int16 scale, const reg_t plane, const bool hasPalette, const uint16 paletteSize) { + _position = Common::Point(x, y); + + if (scale != 128) { + _scaleInfo.x = scale; + _scaleInfo.y = scale; + _scaleInfo.signal = kScaleSignalDoScaling32; + } + + _plane = g_sci->_gfxFrameout->getPlanes().findByObject(plane); + if (_plane == nullptr) { + error("Invalid plane %04x:%04x passed to RobotDecoder::open", PRINT_REG(plane)); + } + + _minFrameRate = _frameRate - kMaxFrameRateDrift; + _maxFrameRate = _frameRate + kMaxFrameRateDrift; + + if (_xResolution == 0 || _yResolution == 0) { + // TODO: Default values were taken from RESOURCE.CFG hires property + // if it exists, so need to check games' configuration files for those + _xResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + _yResolution = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; } - return loadStream(stream); + if (hasPalette) { + _stream->read(_rawPalette, paletteSize); + } else { + _stream->seek(paletteSize, SEEK_CUR); + } + + _screenItemList.reserve(kScreenItemListSize); + _maxCelArea.reserve(kFixedCelListSize); + + // Fixed cel buffers are for version 5 and newer + _fixedCels.reserve(MIN(_maxCelsPerFrame, (int16)kFixedCelListSize)); + _celDecompressionBuffer.reserve(_maxCelArea[0] + SciBitmap::getBitmapHeaderSize() + kRawPaletteSize); + _celDecompressionArea = _maxCelArea[0]; +} + +void RobotDecoder::initRecordAndCuePositions() { + PositionList recordSizes; + _videoSizes.reserve(_numFramesTotal); + _recordPositions.reserve(_numFramesTotal); + recordSizes.reserve(_numFramesTotal); + + switch(_version) { + case 5: // 16-bit sizes and positions + for (int i = 0; i < _numFramesTotal; ++i) { + _videoSizes.push_back(_stream->readUint16()); + } + for (int i = 0; i < _numFramesTotal; ++i) { + recordSizes.push_back(_stream->readUint16()); + } + break; + case 6: // 32-bit sizes and positions + for (int i = 0; i < _numFramesTotal; ++i) { + _videoSizes.push_back(_stream->readSint32()); + } + for (int i = 0; i < _numFramesTotal; ++i) { + recordSizes.push_back(_stream->readSint32()); + } + break; + default: + error("Unknown Robot version %d", _version); + } + + for (int i = 0; i < kCueListSize; ++i) { + _cueTimes[i] = _stream->readSint32(); + } + + for (int i = 0; i < kCueListSize; ++i) { + _cueValues[i] = _stream->readUint16(); + } + + Common::copy(_cueTimes, _cueTimes + kCueListSize, _masterCueTimes); + + int bytesRemaining = (_stream->pos() - _fileOffset) % kRobotFrameSize; + if (bytesRemaining != 0) { + _stream->seek(kRobotFrameSize - bytesRemaining, SEEK_CUR); + } + + int position = _stream->pos(); + _recordPositions.push_back(position); + for (int i = 0; i < _numFramesTotal - 1; ++i) { + position += recordSizes[i]; + _recordPositions.push_back(position); + } +} + +#pragma mark - +#pragma mark RobotDecoder - Playback + +void RobotDecoder::open(const GuiResourceId robotId, const reg_t plane, const int16 priority, const int16 x, const int16 y, const int16 scale) { + if (_status != kRobotStatusUninitialized) { + close(); + } + + initStream(robotId); + + _version = _stream->readUint16(); + + // TODO: Version 4 for PQ:SWAT demo? + if (_version < 5 || _version > 6) { + error("Unsupported version %d of Robot resource", _version); + } + + debugC(kDebugLevelVideo, "Opening version %d robot %d", _version, robotId); + + initPlayback(); + + _audioBlockSize = _stream->readUint16(); + _primerZeroCompressFlag = _stream->readSint16(); + _stream->seek(2, SEEK_CUR); // unused + _numFramesTotal = _stream->readUint16(); + const uint16 paletteSize = _stream->readUint16(); + _primerReservedSize = _stream->readUint16(); + _xResolution = _stream->readSint16(); + _yResolution = _stream->readSint16(); + const bool hasPalette = (bool)_stream->readByte(); + _hasAudio = (bool)_stream->readByte(); + _stream->seek(2, SEEK_CUR); // unused + _frameRate = _normalFrameRate = _stream->readSint16(); + _isHiRes = (bool)_stream->readSint16(); + _maxSkippablePackets = _stream->readSint16(); + _maxCelsPerFrame = _stream->readSint16(); + + // used for memory preallocation of fixed cels + _maxCelArea.push_back(_stream->readSint32()); + _maxCelArea.push_back(_stream->readSint32()); + _maxCelArea.push_back(_stream->readSint32()); + _maxCelArea.push_back(_stream->readSint32()); + _stream->seek(8, SEEK_CUR); // reserved + + if (_hasAudio) { + initAudio(); + } else { + _stream->seek(_primerReservedSize, SEEK_CUR); + } + + _priority = priority; + initVideo(x, y, scale, plane, hasPalette, paletteSize); + initRecordAndCuePositions(); } void RobotDecoder::close() { - VideoDecoder::close(); + if (_status == kRobotStatusUninitialized) { + return; + } + + debugC(kDebugLevelVideo, "Closing robot"); - delete _fileStream; - _fileStream = 0; + _status = kRobotStatusUninitialized; + _videoSizes.clear(); + _recordPositions.clear(); + _celDecompressionBuffer.clear(); + _doVersion5Scratch.clear(); + delete _stream; + _stream = nullptr; + + for (CelHandleList::size_type i = 0; i < _celHandles.size(); ++i) { + if (_celHandles[i].status == CelHandleInfo::kFrameLifetime) { + _segMan->freeBitmap(_celHandles[i].bitmapId); + } + } + _celHandles.clear(); + + for (FixedCelsList::size_type i = 0; i < _fixedCels.size(); ++i) { + _segMan->freeBitmap(_fixedCels[i]); + } + _fixedCels.clear(); + + if (g_sci->_gfxFrameout->getPlanes().findByObject(_plane->_object) != nullptr) { + for (RobotScreenItemList::size_type i = 0; i < _screenItemList.size(); ++i) { + if (_screenItemList[i] != nullptr) { + g_sci->_gfxFrameout->deleteScreenItem(*_screenItemList[i]); + } + } + } + _screenItemList.clear(); - delete[] _frameTotalSize; - _frameTotalSize = 0; + if (_hasAudio) { + _audioList.reset(); + } } -void RobotDecoder::readNextPacket() { - // Get our track - RobotVideoTrack *videoTrack = (RobotVideoTrack *)getTrack(0); - videoTrack->increaseCurFrame(); - Graphics::Surface *surface = videoTrack->getSurface(); +void RobotDecoder::pause() { + if (_status != kRobotStatusPlaying) { + return; + } + + if (_hasAudio) { + _audioList.stopAudioNow(); + } + + _status = kRobotStatusPaused; + _frameRate = _normalFrameRate; +} - if (videoTrack->endOfTrack()) +void RobotDecoder::resume() { + if (_status != kRobotStatusPaused) { return; + } + + _startingFrameNo = _currentFrameNo; + _status = kRobotStatusPlaying; + if (_hasAudio) { + primeAudio(_currentFrameNo * 60 / _frameRate); + _syncFrame = true; + } + + setRobotTime(_currentFrameNo); + for (int i = 0; i < kCueListSize; ++i) { + if (_masterCueTimes[i] != -1 && _masterCueTimes[i] < _currentFrameNo) { + _cueTimes[i] = -1; + } else { + _cueTimes[i] = _masterCueTimes[i]; + } + } +} - // Read frame image header (24 bytes) - _fileStream->skip(3); - byte frameScale = _fileStream->readByte(); - uint16 frameWidth = _fileStream->readUint16(); - uint16 frameHeight = _fileStream->readUint16(); - _fileStream->skip(4); // unknown, almost always 0 - uint16 frameX = _fileStream->readUint16(); - uint16 frameY = _fileStream->readUint16(); - - // TODO: In v4 robot files, frameX and frameY have a different meaning. - // Set them both to 0 for v4 for now, so that robots in PQ:SWAT show up - // correctly. - if (_header.version == 4) - frameX = frameY = 0; - - uint16 compressedSize = _fileStream->readUint16(); - uint16 frameFragments = _fileStream->readUint16(); - _fileStream->skip(4); // unknown - uint32 decompressedSize = frameWidth * frameHeight * frameScale / 100; - - // FIXME: A frame's height + position can go off limits... why? With the - // following, we cut the contents to fit the frame - uint16 scaledHeight = CLIP<uint16>(decompressedSize / frameWidth, 0, surface->h - frameY); - - // FIXME: Same goes for the frame's width + position. In this case, we - // modify the position to fit the contents on screen. - if (frameWidth + frameX > surface->w) - frameX = surface->w - frameWidth; - - assert(frameWidth + frameX <= surface->w && scaledHeight + frameY <= surface->h); - - DecompressorLZS lzs; - byte *decompressedFrame = new byte[decompressedSize]; - byte *outPtr = decompressedFrame; - - if (_header.version == 4) { - // v4 has just the one fragment, it seems, and ignores the fragment count - Common::SeekableSubReadStream fragmentStream(_fileStream, _fileStream->pos(), _fileStream->pos() + compressedSize); - lzs.unpack(&fragmentStream, outPtr, compressedSize, decompressedSize); +void RobotDecoder::showFrame(const uint16 frameNo, const uint16 newX, const uint16 newY, const uint16 newPriority) { + debugC(kDebugLevelVideo, "Show frame %d (%d %d %d)", frameNo, newX, newY, newPriority); + + if (newX != kUnspecified) { + _position.x = newX; + } + + if (newY != kUnspecified) { + _position.y = newY; + } + + if (newPriority != kUnspecified) { + _priority = newPriority; + } + + _currentFrameNo = frameNo; + pause(); + + if (frameNo != _previousFrameNo) { + seekToFrame(frameNo); + doVersion5(false); } else { - for (uint16 i = 0; i < frameFragments; ++i) { - uint32 compressedFragmentSize = _fileStream->readUint32(); - uint32 decompressedFragmentSize = _fileStream->readUint32(); - uint16 compressionType = _fileStream->readUint16(); - - if (compressionType == 0) { - Common::SeekableSubReadStream fragmentStream(_fileStream, _fileStream->pos(), _fileStream->pos() + compressedFragmentSize); - lzs.unpack(&fragmentStream, outPtr, compressedFragmentSize, decompressedFragmentSize); - } else if (compressionType == 2) { // untested - _fileStream->read(outPtr, compressedFragmentSize); + for (RobotScreenItemList::size_type i = 0; i < _screenItemList.size(); ++i) { + if (_isHiRes) { + SciBitmap &bitmap = *_segMan->lookupBitmap(_celHandles[i].bitmapId); + + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + + if (scriptWidth == kLowResX && scriptHeight == kLowResY) { + const Ratio lowResToScreenX(screenWidth, kLowResX); + const Ratio lowResToScreenY(screenHeight, kLowResY); + const Ratio screenToLowResX(kLowResX, screenWidth); + const Ratio screenToLowResY(kLowResY, screenHeight); + + const int16 scaledX = _originalScreenItemX[i] + (_position.x * lowResToScreenX).toInt(); + const int16 scaledY1 = _originalScreenItemY[i] + (_position.y * lowResToScreenY).toInt(); + const int16 scaledY2 = scaledY1 + bitmap.getHeight() - 1; + + const int16 lowResX = (scaledX * screenToLowResX).toInt(); + const int16 lowResY = (scaledY2 * screenToLowResY).toInt(); + + bitmap.setDisplace(Common::Point( + (scaledX - (lowResX * lowResToScreenX).toInt()) * -1, + (lowResY * lowResToScreenY).toInt() - scaledY1 + )); + + _screenItemX[i] = lowResX; + _screenItemY[i] = lowResY; + } else { + const int16 scaledX = _originalScreenItemX[i] + _position.x; + const int16 scaledY = _originalScreenItemY[i] + _position.y + bitmap.getHeight() - 1; + bitmap.setDisplace(Common::Point(0, bitmap.getHeight() - 1)); + _screenItemX[i] = scaledX; + _screenItemY[i] = scaledY; + } + } else { + _screenItemX[i] = _originalScreenItemX[i] + _position.x; + _screenItemY[i] = _originalScreenItemY[i] + _position.y; + } + + if (_screenItemList[i] == nullptr) { + CelInfo32 celInfo; + celInfo.type = kCelTypeMem; + celInfo.bitmap = _celHandles[i].bitmapId; + ScreenItem *screenItem = new ScreenItem(_plane->_object, celInfo); + _screenItemList[i] = screenItem; + screenItem->_position = Common::Point(_screenItemX[i], _screenItemY[i]); + if (_priority == -1) { + screenItem->_fixedPriority = false; + } else { + screenItem->_priority = _priority; + screenItem->_fixedPriority = true; + } + g_sci->_gfxFrameout->addScreenItem(*screenItem); } else { - error("Unknown frame compression found: %d", compressionType); + ScreenItem *screenItem = _screenItemList[i]; + screenItem->_celInfo.bitmap = _celHandles[i].bitmapId; + screenItem->_position = Common::Point(_screenItemX[i], _screenItemY[i]); + if (_priority == -1) { + screenItem->_fixedPriority = false; + } else { + screenItem->_priority = _priority; + screenItem->_fixedPriority = true; + } + g_sci->_gfxFrameout->updateScreenItem(*screenItem); + } + } + } + + _previousFrameNo = frameNo; +} + +int16 RobotDecoder::getCue() const { + if (_status == kRobotStatusUninitialized || + _status == kRobotStatusPaused || + _syncFrame) { + return 0; + } + + if (_status == kRobotStatusEnd) { + return -1; + } + + const uint16 estimatedNextFrameNo = MIN(calculateNextFrameNo(_delayTime.predictedTicks()), _numFramesTotal); + + for (int i = 0; i < kCueListSize; ++i) { + if (_cueTimes[i] != -1 && _cueTimes[i] <= estimatedNextFrameNo) { + if (_cueTimes[i] >= _previousFrameNo) { + _cueForceShowFrame = _cueTimes[i] + 1; } - outPtr += decompressedFragmentSize; + _cueTimes[i] = -1; + return _cueValues[i]; } } - // Copy over the decompressed frame - byte *inFrame = decompressedFrame; - byte *outFrame = (byte *)surface->getPixels(); + return 0; +} - // Black out the surface - memset(outFrame, 0, surface->w * surface->h); +int16 RobotDecoder::getFrameNo() const { + if (_status == kRobotStatusUninitialized) { + return 0; + } - // Move to the correct y coordinate - outFrame += surface->w * frameY; + return _currentFrameNo; +} + +RobotDecoder::RobotStatus RobotDecoder::getStatus() const { + return _status; +} - for (uint16 y = 0; y < scaledHeight; y++) { - memcpy(outFrame + frameX, inFrame, frameWidth); - inFrame += frameWidth; - outFrame += surface->w; +bool RobotDecoder::seekToFrame(const int frameNo) { + return _stream->seek(_recordPositions[frameNo], SEEK_SET); +} + +void RobotDecoder::setRobotTime(const int frameNo) { + _startTime = getTickCount(); + _startFrameNo = frameNo; +} + +#pragma mark - +#pragma mark RobotDecoder - Timing + +RobotDecoder::DelayTime::DelayTime(RobotDecoder *decoder) : + _decoder(decoder) { + for (int i = 0; i < kDelayListSize; ++i) { + _timestamps[i] = i; + _delays[i] = 0; } - delete[] decompressedFrame; + _oldestTimestamp = 0; + _newestTimestamp = kDelayListSize - 1; + _startTime = 0; +} - uint32 audioChunkSize = _frameTotalSize[videoTrack->getCurFrame()] - (24 + compressedSize); +void RobotDecoder::DelayTime::startTiming() { + _startTime = _decoder->getTickCount(); +} -// TODO: The audio chunk size below is usually correct, but there are some -// exceptions (e.g. robot 4902 in Phantasmagoria, towards its end) -#if 0 - // Read frame audio header (14 bytes) - _fileStream->skip(2); // buffer position - _fileStream->skip(2); // unknown (usually 1) - _fileStream->skip(2); /*uint16 audioChunkSize = _fileStream->readUint16() + 8;*/ - _fileStream->skip(2); -#endif +void RobotDecoder::DelayTime::endTiming() { + const int timeDelta = _decoder->getTickCount() - _startTime; + for (uint i = 0; i < kDelayListSize; ++i) { + if (_timestamps[i] == _oldestTimestamp) { + _timestamps[i] = ++_newestTimestamp; + _delays[i] = timeDelta; + break; + } + } + ++_newestTimestamp; + _startTime = 0; + sortList(); +} - // Queue the next audio frame - // FIXME: For some reason, there are audio hiccups/gaps - if (_header.hasSound) { - RobotAudioTrack *audioTrack = (RobotAudioTrack *)getTrack(1); - _fileStream->skip(8); // header - audioChunkSize -= 8; - audioTrack->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize), audioChunkSize * 2); +bool RobotDecoder::DelayTime::timingInProgress() const { + return _startTime != 0; +} + +int RobotDecoder::DelayTime::predictedTicks() const { + return _delays[kDelayListSize / 2]; +} + +void RobotDecoder::DelayTime::sortList() { + for (uint i = 0; i < kDelayListSize - 1; ++i) { + int smallestDelay = _delays[i]; + uint smallestIndex = i; + + for (uint j = i + 1; j < kDelayListSize - 1; ++j) { + if (_delays[j] < smallestDelay) { + smallestDelay = _delays[j]; + smallestIndex = j; + } + } + + if (smallestIndex != i) { + SWAP(_delays[i], _delays[smallestIndex]); + SWAP(_timestamps[i], _timestamps[smallestIndex]); + } + } +} + +uint16 RobotDecoder::calculateNextFrameNo(const uint32 extraTicks) const { + return ticksToFrames(getTickCount() + extraTicks - _startTime) + _startFrameNo; +} + +uint32 RobotDecoder::ticksToFrames(const uint32 ticks) const { + return (ticks * _frameRate) / 60; +} + +uint32 RobotDecoder::getTickCount() const { + return g_sci->getTickCount(); +} + +#pragma mark - +#pragma mark RobotDecoder - Audio + +RobotDecoder::AudioList::AudioList() : + _blocks(), + _blocksSize(0), + _oldestBlockIndex(0), + _newestBlockIndex(0), + _startOffset(0), + _status(kRobotAudioReady) {} + +void RobotDecoder::AudioList::startAudioNow() { + submitDriverMax(); + g_sci->_audio32->resume(kRobotChannel); + _status = kRobotAudioPlaying; +} + +void RobotDecoder::AudioList::stopAudio() { + g_sci->_audio32->finishRobotAudio(); + freeAudioBlocks(); + _status = kRobotAudioStopping; +} + +void RobotDecoder::AudioList::stopAudioNow() { + if (_status == kRobotAudioPlaying || _status == kRobotAudioStopping || _status == kRobotAudioPaused) { + g_sci->_audio32->stopRobotAudio(); + _status = kRobotAudioStopped; + } + + freeAudioBlocks(); +} + +void RobotDecoder::AudioList::submitDriverMax() { + while (_blocksSize != 0) { + if (!_blocks[_oldestBlockIndex]->submit(_startOffset)) { + return; + } + + delete _blocks[_oldestBlockIndex]; + _blocks[_oldestBlockIndex] = nullptr; + ++_oldestBlockIndex; + if (_oldestBlockIndex == kAudioListSize) { + _oldestBlockIndex = 0; + } + + --_blocksSize; + } +} + +void RobotDecoder::AudioList::addBlock(const int position, const int size, const byte *data) { + assert(data != nullptr); + assert(size >= 0); + assert(position >= -1); + + if (_blocksSize == kAudioListSize) { + delete _blocks[_oldestBlockIndex]; + _blocks[_oldestBlockIndex] = nullptr; + ++_oldestBlockIndex; + if (_oldestBlockIndex == kAudioListSize) { + _oldestBlockIndex = 0; + } + --_blocksSize; + } + + if (_blocksSize == 0) { + _oldestBlockIndex = _newestBlockIndex = 0; } else { - _fileStream->skip(audioChunkSize); - } -} - -void RobotDecoder::readHeaderChunk() { - // Header (60 bytes) - _fileStream->skip(6); - _header.version = _fileStream->readUint16(); - _header.audioChunkSize = _fileStream->readUint16(); - _header.audioSilenceSize = _fileStream->readUint16(); - _fileStream->skip(2); - _header.frameCount = _fileStream->readUint16(); - _header.paletteDataSize = _fileStream->readUint16(); - _header.unkChunkDataSize = _fileStream->readUint16(); - _fileStream->skip(5); - _header.hasSound = _fileStream->readByte(); - _fileStream->skip(34); - - // Some videos (e.g. robot 1305 in Phantasmagoria and - // robot 184 in Lighthouse) have an unknown chunk before - // the palette chunk (probably used for sound preloading). - // Skip it here. - if (_header.unkChunkDataSize) - _fileStream->skip(_header.unkChunkDataSize); -} - -void RobotDecoder::readFrameSizesChunk() { - // The robot video file contains 2 tables, with one entry for each frame: - // - A table containing the size of the image in each video frame - // - A table containing the total size of each video frame. - // In v5 robots, the tables contain 16-bit integers, whereas in v6 robots, - // they contain 32-bit integers. - - _frameTotalSize = new uint32[_header.frameCount]; - - // TODO: The table reading code can probably be removed once the - // audio chunk size is figured out (check the TODO inside processNextFrame()) -#if 0 - // We don't need any of the two tables to play the video, so we ignore - // both of them. - uint16 wordSize = _header.version == 6 ? 4 : 2; - _fileStream->skip(_header.frameCount * wordSize * 2); -#else - switch (_header.version) { - case 4: - case 5: // sizes are 16-bit integers - // Skip table with frame image sizes, as we don't need it - _fileStream->skip(_header.frameCount * 2); - for (int i = 0; i < _header.frameCount; ++i) - _frameTotalSize[i] = _fileStream->readUint16(); - break; - case 6: // sizes are 32-bit integers - // Skip table with frame image sizes, as we don't need it - _fileStream->skip(_header.frameCount * 4); - for (int i = 0; i < _header.frameCount; ++i) - _frameTotalSize[i] = _fileStream->readUint32(); - break; - default: - error("Can't yet handle index table for robot version %d", _header.version); + ++_newestBlockIndex; + if (_newestBlockIndex == kAudioListSize) { + _newestBlockIndex = 0; + } } -#endif - // 2 more unknown tables - _fileStream->skip(1024 + 512); + _blocks[_newestBlockIndex] = new AudioBlock(position, size, data); + ++_blocksSize; +} - // Pad to nearest 2 kilobytes - uint32 curPos = _fileStream->pos(); - if (curPos & 0x7ff) - _fileStream->seek((curPos & ~0x7ff) + 2048); +void RobotDecoder::AudioList::reset() { + stopAudioNow(); + _startOffset = 0; + _status = kRobotAudioReady; } -RobotDecoder::RobotVideoTrack::RobotVideoTrack(int frameCount) : _frameCount(frameCount) { - _surface = new Graphics::Surface(); - _curFrame = -1; - _dirtyPalette = false; +void RobotDecoder::AudioList::prepareForPrimer() { + g_sci->_audio32->pause(kRobotChannel); + _status = kRobotAudioPaused; } -RobotDecoder::RobotVideoTrack::~RobotVideoTrack() { - _surface->free(); - delete _surface; +void RobotDecoder::AudioList::setAudioOffset(const int offset) { + _startOffset = offset; } -uint16 RobotDecoder::RobotVideoTrack::getWidth() const { - return _surface->w; +RobotDecoder::AudioList::AudioBlock::AudioBlock(const int position, const int size, const byte* const data) : + _position(position), + _size(size) { + _data = (byte *)malloc(size); + memcpy(_data, data, size); } -uint16 RobotDecoder::RobotVideoTrack::getHeight() const { - return _surface->h; +RobotDecoder::AudioList::AudioBlock::~AudioBlock() { + free(_data); } -Graphics::PixelFormat RobotDecoder::RobotVideoTrack::getPixelFormat() const { - return _surface->format; +bool RobotDecoder::AudioList::AudioBlock::submit(const int startOffset) { + assert(_data != nullptr); + RobotAudioStream::RobotAudioPacket packet(_data, _size, (_position - startOffset) * 2); + return g_sci->_audio32->playRobotAudio(packet); } -void RobotDecoder::RobotVideoTrack::readPaletteChunk(Common::SeekableSubReadStreamEndian *stream, uint16 chunkSize) { - byte *paletteData = new byte[chunkSize]; - stream->read(paletteData, chunkSize); +void RobotDecoder::AudioList::freeAudioBlocks() { + while (_blocksSize != 0) { + delete _blocks[_oldestBlockIndex]; + _blocks[_oldestBlockIndex] = nullptr; + ++_oldestBlockIndex; + if (_oldestBlockIndex == kAudioListSize) { + _oldestBlockIndex = 0; + } + + --_blocksSize; + } +} - // SCI1.1 palette - byte palFormat = paletteData[32]; - uint16 palColorStart = paletteData[25]; - uint16 palColorCount = READ_SCI11ENDIAN_UINT16(paletteData + 29); +bool RobotDecoder::primeAudio(const uint32 startTick) { + bool success = true; + _audioList.reset(); + + if (startTick == 0) { + _audioList.prepareForPrimer(); + byte *evenPrimerBuff = new byte[_evenPrimerSize]; + byte *oddPrimerBuff = new byte[_oddPrimerSize]; + + success = readPrimerData(evenPrimerBuff, oddPrimerBuff); + if (success) { + if (_evenPrimerSize != 0) { + _audioList.addBlock(0, _evenPrimerSize, evenPrimerBuff); + } + if (_oddPrimerSize != 0) { + _audioList.addBlock(1, _oddPrimerSize, oddPrimerBuff); + } + } + + delete[] evenPrimerBuff; + delete[] oddPrimerBuff; + } else { + assert(_evenPrimerSize * 2 >= _audioRecordInterval || _oddPrimerSize * 2 >= _audioRecordInterval); + + int audioStartFrame = 0; + int videoStartFrame = startTick * _frameRate / 60; + assert(videoStartFrame < _numFramesTotal); + + int audioStartPosition = (startTick * RobotAudioStream::kRobotSampleRate) / 60; + if (audioStartPosition & 1) { + audioStartPosition--; + } + _audioList.setAudioOffset(audioStartPosition); + _audioList.prepareForPrimer(); + + if (audioStartPosition < _evenPrimerSize * 2 || + audioStartPosition + 1 < _oddPrimerSize * 2) { + + byte *evenPrimerBuffer = new byte[_evenPrimerSize]; + byte *oddPrimerBuffer = new byte[_oddPrimerSize]; + success = readPrimerData(evenPrimerBuffer, oddPrimerBuffer); + if (success) { + int halfAudioStartPosition = audioStartPosition / 2; + if (audioStartPosition < _evenPrimerSize * 2) { + _audioList.addBlock(audioStartPosition, _evenPrimerSize - halfAudioStartPosition, &evenPrimerBuffer[halfAudioStartPosition]); + } + + if (audioStartPosition + 1 < _oddPrimerSize * 2) { + _audioList.addBlock(audioStartPosition + 1, _oddPrimerSize - halfAudioStartPosition, &oddPrimerBuffer[halfAudioStartPosition]); + } + } + + delete[] evenPrimerBuffer; + delete[] oddPrimerBuffer; + } - int palOffset = 37; - memset(_palette, 0, 256 * 3); + if (audioStartPosition >= _firstAudioRecordPosition) { + int audioRecordSize = _expectedAudioBlockSize; + assert(audioRecordSize > 0); + assert(_audioRecordInterval > 0); + assert(_firstAudioRecordPosition >= 0); - for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { - if (palFormat == kRobotPalVariable) - palOffset++; - _palette[colorNo * 3 + 0] = paletteData[palOffset++]; - _palette[colorNo * 3 + 1] = paletteData[palOffset++]; - _palette[colorNo * 3 + 2] = paletteData[palOffset++]; + audioStartFrame = (audioStartPosition - _firstAudioRecordPosition) / _audioRecordInterval; + assert(audioStartFrame < videoStartFrame); + + if (audioStartFrame > 0) { + int lastAudioFrame = audioStartFrame - 1; + int oddRemainder = lastAudioFrame & 1; + int audioRecordStart = (lastAudioFrame * _audioRecordInterval) + oddRemainder + _firstAudioRecordPosition; + int audioRecordEnd = (audioRecordStart + ((audioRecordSize - 1) * 2)) + oddRemainder + _firstAudioRecordPosition; + + if (audioStartPosition >= audioRecordStart && audioStartPosition <= audioRecordEnd) { + --audioStartFrame; + } + } + + assert(!(audioStartPosition & 1)); + if (audioStartFrame & 1) { + ++audioStartPosition; + } + + if (!readPartialAudioRecordAndSubmit(audioStartFrame, audioStartPosition)) { + return false; + } + + ++audioStartFrame; + assert(audioStartFrame < videoStartFrame); + + int oddRemainder = audioStartFrame & 1; + int audioRecordStart = (audioStartFrame * _audioRecordInterval) + oddRemainder + _firstAudioRecordPosition; + int audioRecordEnd = (audioRecordStart + ((audioRecordSize - 1) * 2)) + oddRemainder + _firstAudioRecordPosition; + + if (audioStartPosition >= audioRecordStart && audioStartPosition <= audioRecordEnd) { + if (!readPartialAudioRecordAndSubmit(audioStartFrame, audioStartPosition + 1)) { + return false; + } + + ++audioStartFrame; + } + } + + int audioPosition, audioSize; + for (int i = audioStartFrame; i < videoStartFrame; i++) { + if (!readAudioDataFromRecord(i, _audioBuffer, audioPosition, audioSize)) { + break; + } + + _audioList.addBlock(audioPosition, audioSize, _audioBuffer); + } } - _dirtyPalette = true; - delete[] paletteData; + return success; } -void RobotDecoder::RobotVideoTrack::calculateVideoDimensions(Common::SeekableSubReadStreamEndian *stream, uint32 *frameSizes) { - // This is an O(n) operation, as each frame has a different size. - // We need to know the actual frame size to have a constant video size. - uint32 pos = stream->pos(); +bool RobotDecoder::readPrimerData(byte *outEvenBuffer, byte *outOddBuffer) { + if (_primerReservedSize != 0) { + if (_totalPrimerSize != 0) { + _stream->seek(_primerPosition, SEEK_SET); + if (_evenPrimerSize > 0) { + _stream->read(outEvenBuffer, _evenPrimerSize); + } + + if (_oddPrimerSize > 0) { + _stream->read(outOddBuffer, _oddPrimerSize); + } + } + } else if (_primerZeroCompressFlag) { + memset(outEvenBuffer, 0, _evenPrimerSize); + memset(outOddBuffer, 0, _oddPrimerSize); + } else { + error("ReadPrimerData - Flags corrupt"); + } + + return !_stream->err(); +} + +bool RobotDecoder::readAudioDataFromRecord(const int frameNo, byte *outBuffer, int &outAudioPosition, int &outAudioSize) { + _stream->seek(_recordPositions[frameNo] + _videoSizes[frameNo], SEEK_SET); + _audioList.submitDriverMax(); + + // Compressed absolute position of the audio block in the audio stream + const int position = _stream->readSint32(); - uint16 width = 0, height = 0; + // Size of the block of audio, excluding the audio block header + int size = _stream->readSint32(); - for (int curFrame = 0; curFrame < _frameCount; curFrame++) { - stream->skip(4); - uint16 frameWidth = stream->readUint16(); - uint16 frameHeight = stream->readUint16(); - if (frameWidth > width) - width = frameWidth; - if (frameHeight > height) - height = frameHeight; - stream->skip(frameSizes[curFrame] - 8); + assert(size <= _expectedAudioBlockSize); + + if (position == 0) { + return false; } - stream->seek(pos); + if (size != _expectedAudioBlockSize) { + memset(outBuffer, 0, kRobotZeroCompressSize); + _stream->read(outBuffer + kRobotZeroCompressSize, size); + size += kRobotZeroCompressSize; + } else { + _stream->read(outBuffer, size); + } - _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + outAudioPosition = position; + outAudioSize = size; + return !_stream->err(); } -RobotDecoder::RobotAudioTrack::RobotAudioTrack() { - _audioStream = Audio::makeQueuingAudioStream(11025, false); +bool RobotDecoder::readPartialAudioRecordAndSubmit(const int startFrame, const int startPosition) { + int audioPosition, audioSize; + bool success = readAudioDataFromRecord(startFrame, _audioBuffer, audioPosition, audioSize); + if (success) { + const int relativeStartOffset = (startPosition - audioPosition) / 2; + _audioList.addBlock(startPosition, audioSize - relativeStartOffset, _audioBuffer + relativeStartOffset); + } + + return success; } -RobotDecoder::RobotAudioTrack::~RobotAudioTrack() { - delete _audioStream; +#pragma mark - +#pragma mark RobotDecoder - Rendering + +uint16 RobotDecoder::getFrameSize(Common::Rect &outRect) const { + outRect.clip(0, 0); + for (RobotScreenItemList::size_type i = 0; i < _screenItemList.size(); ++i) { + ScreenItem &screenItem = *_screenItemList[i]; + outRect.extend(screenItem.getNowSeenRect(*_plane)); + } + + return _numFramesTotal; } -void RobotDecoder::RobotAudioTrack::queueBuffer(byte *buffer, int size) { - _audioStream->queueBuffer(buffer, size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN); +void RobotDecoder::doRobot() { + if (_status != kRobotStatusPlaying) { + return; + } + + if (!_syncFrame) { + if (_cueForceShowFrame != -1) { + _currentFrameNo = _cueForceShowFrame; + _cueForceShowFrame = -1; + } else { + const int nextFrameNo = calculateNextFrameNo(_delayTime.predictedTicks()); + if (nextFrameNo < _currentFrameNo) { + return; + } + _currentFrameNo = nextFrameNo; + } + } + + if (_currentFrameNo >= _numFramesTotal) { + const int finalFrameNo = _numFramesTotal - 1; + if (_previousFrameNo == finalFrameNo) { + _status = kRobotStatusEnd; + if (_hasAudio) { + _audioList.stopAudio(); + _frameRate = _normalFrameRate; + _hasAudio = false; + } + return; + } else { + _currentFrameNo = finalFrameNo; + } + } + + if (_currentFrameNo == _previousFrameNo) { + _audioList.submitDriverMax(); + return; + } + + if (_hasAudio) { + for (int candidateFrameNo = _previousFrameNo + _maxSkippablePackets + 1; candidateFrameNo < _currentFrameNo; candidateFrameNo += _maxSkippablePackets + 1) { + + _audioList.submitDriverMax(); + + int audioPosition, audioSize; + if (readAudioDataFromRecord(candidateFrameNo, _audioBuffer, audioPosition, audioSize)) { + _audioList.addBlock(audioPosition, audioSize, _audioBuffer); + } + } + _audioList.submitDriverMax(); + } + + _delayTime.startTiming(); + seekToFrame(_currentFrameNo); + doVersion5(); + if (_hasAudio) { + _audioList.submitDriverMax(); + } +} + +void RobotDecoder::frameAlmostVisible() { + if (_status == kRobotStatusPlaying && !_syncFrame) { + if (_previousFrameNo != _currentFrameNo) { + while (calculateNextFrameNo() < _currentFrameNo) { + _audioList.submitDriverMax(); + } + } + } +} + +void RobotDecoder::frameNowVisible() { + if (_status != kRobotStatusPlaying) { + return; + } + + if (_syncFrame) { + _syncFrame = false; + if (_hasAudio) { + _audioList.startAudioNow(); + _checkAudioSyncTime = _startTime + kAudioSyncCheckInterval; + } + + setRobotTime(_currentFrameNo); + } + + if (_delayTime.timingInProgress()) { + _delayTime.endTiming(); + } + + if (_hasAudio) { + _audioList.submitDriverMax(); + } + + if (_previousFrameNo != _currentFrameNo) { + _previousFrameNo = _currentFrameNo; + } + + if (!_syncFrame && _hasAudio && getTickCount() >= _checkAudioSyncTime) { + RobotAudioStream::StreamState status; + const bool success = g_sci->_audio32->queryRobotAudio(status); + if (!success) { + return; + } + + const int bytesPerFrame = status.rate / _normalFrameRate * (status.bits == 16 ? 2 : 1); + // check again in 1/3rd second + _checkAudioSyncTime = getTickCount() + 60 / 3; + + const int currentVideoFrameNo = calculateNextFrameNo() - _startingFrameNo; + const int currentAudioFrameNo = status.bytesPlaying / bytesPerFrame; + debugC(kDebugLevelVideo, "Video frame %d %s audio frame %d", currentVideoFrameNo, currentVideoFrameNo == currentAudioFrameNo ? "=" : currentVideoFrameNo < currentAudioFrameNo ? "<" : ">", currentAudioFrameNo); + if (currentVideoFrameNo < _numFramesTotal && + currentAudioFrameNo < _numFramesTotal) { + + bool shouldResetRobotTime = false; + + if (currentAudioFrameNo < currentVideoFrameNo - 1 && _frameRate != _minFrameRate) { + debugC(kDebugLevelVideo, "[v] Reducing frame rate"); + _frameRate = _minFrameRate; + shouldResetRobotTime = true; + } else if (currentAudioFrameNo > currentVideoFrameNo + 1 && _frameRate != _maxFrameRate) { + debugC(kDebugLevelVideo, "[^] Increasing frame rate"); + _frameRate = _maxFrameRate; + shouldResetRobotTime = true; + } else if (_frameRate != _normalFrameRate) { + debugC(kDebugLevelVideo, "[=] Setting to normal frame rate"); + _frameRate = _normalFrameRate; + shouldResetRobotTime = true; + } + + if (shouldResetRobotTime) { + if (currentAudioFrameNo < _currentFrameNo) { + setRobotTime(_currentFrameNo); + } else { + setRobotTime(currentAudioFrameNo); + } + } + } + } +} + +void RobotDecoder::expandCel(byte* target, const byte* source, const int16 celWidth, const int16 celHeight) const { + assert(source != nullptr && target != nullptr); + + const int sourceHeight = (celHeight * _verticalScaleFactor) / 100; + assert(sourceHeight > 0); + + const int16 numerator = celHeight; + const int16 denominator = sourceHeight; + int remainder = 0; + for (int16 y = sourceHeight - 1; y >= 0; --y) { + remainder += numerator; + int16 linesToDraw = remainder / denominator; + remainder %= denominator; + + while (linesToDraw--) { + memcpy(target, source, celWidth); + target += celWidth; + } + + source += celWidth; + } +} + +void RobotDecoder::setPriority(const int16 newPriority) { + _priority = newPriority; +} + +void RobotDecoder::doVersion5(const bool shouldSubmitAudio) { + const RobotScreenItemList::size_type oldScreenItemCount = _screenItemList.size(); + const int videoSize = _videoSizes[_currentFrameNo]; + _doVersion5Scratch.resize(videoSize); + + byte *videoFrameData = _doVersion5Scratch.begin(); + + if (!_stream->read(videoFrameData, videoSize)) { + error("RobotDecoder::doVersion5: Read error"); + } + + const RobotScreenItemList::size_type screenItemCount = READ_SCI11ENDIAN_UINT16(videoFrameData); + + if (screenItemCount > kScreenItemListSize) { + return; + } + + if (_hasAudio && + (getSciVersion() < SCI_VERSION_3 || shouldSubmitAudio)) { + int audioPosition, audioSize; + if (readAudioDataFromRecord(_currentFrameNo, _audioBuffer, audioPosition, audioSize)) { + _audioList.addBlock(audioPosition, audioSize, _audioBuffer); + } + } + + if (screenItemCount > oldScreenItemCount) { + _screenItemList.resize(screenItemCount); + _screenItemX.resize(screenItemCount); + _screenItemY.resize(screenItemCount); + _originalScreenItemX.resize(screenItemCount); + _originalScreenItemY.resize(screenItemCount); + } + + createCels5(videoFrameData + 2, screenItemCount, true); + for (RobotScreenItemList::size_type i = 0; i < screenItemCount; ++i) { + Common::Point position(_screenItemX[i], _screenItemY[i]); + +// TODO: Version 6 robot? +// int scaleXRemainder; + if (_scaleInfo.signal == kScaleSignalDoScaling32) { + position.x = (position.x * _scaleInfo.x) / 128; +// TODO: Version 6 robot? +// scaleXRemainder = (position.x * _scaleInfo.x) % 128; + position.y = (position.y * _scaleInfo.y) / 128; + } + + if (_screenItemList[i] == nullptr) { + CelInfo32 celInfo; + celInfo.bitmap = _celHandles[i].bitmapId; + ScreenItem *screenItem = new ScreenItem(_plane->_object, celInfo, position, _scaleInfo); + _screenItemList[i] = screenItem; + // TODO: Version 6 robot? + // screenItem->_field_30 = scaleXRemainder; + + if (_priority == -1) { + screenItem->_fixedPriority = false; + } else { + screenItem->_fixedPriority = true; + screenItem->_priority = _priority; + } + g_sci->_gfxFrameout->addScreenItem(*screenItem); + } else { + ScreenItem *screenItem = _screenItemList[i]; + screenItem->_celInfo.bitmap = _celHandles[i].bitmapId; + screenItem->_position = position; + // TODO: Version 6 robot? + // screenItem->_field_30 = scaleXRemainder; + + if (_priority == -1) { + screenItem->_fixedPriority = false; + } else { + screenItem->_fixedPriority = true; + screenItem->_priority = _priority; + } + g_sci->_gfxFrameout->updateScreenItem(*screenItem); + } + } + + for (RobotScreenItemList::size_type i = screenItemCount; i < oldScreenItemCount; ++i) { + if (_screenItemList[i] != nullptr) { + g_sci->_gfxFrameout->deleteScreenItem(*_screenItemList[i]); + _screenItemList[i] = nullptr; + } + } +} + +void RobotDecoder::createCels5(const byte *rawVideoData, const int16 numCels, const bool usePalette) { + preallocateCelMemory(rawVideoData, numCels); + for (int16 i = 0; i < numCels; ++i) { + rawVideoData += createCel5(rawVideoData, i, usePalette); + } +} + +uint32 RobotDecoder::createCel5(const byte *rawVideoData, const int16 screenItemIndex, const bool usePalette) { + _verticalScaleFactor = rawVideoData[1]; + const int16 celWidth = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 2); + const int16 celHeight = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 4); + const Common::Point celPosition((int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 10), + (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 12)); + const uint16 dataSize = READ_SCI11ENDIAN_UINT16(rawVideoData + 14); + const int16 numDataChunks = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 16); + + rawVideoData += kCelHeaderSize; + + const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; + const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; + const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth; + const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight; + + Common::Point displace; + if (scriptWidth == kLowResX && scriptHeight == kLowResY) { + const Ratio lowResToScreenX(screenWidth, kLowResX); + const Ratio lowResToScreenY(screenHeight, kLowResY); + const Ratio screenToLowResX(kLowResX, screenWidth); + const Ratio screenToLowResY(kLowResY, screenHeight); + + const int16 scaledX = celPosition.x + (_position.x * lowResToScreenX).toInt(); + const int16 scaledY1 = celPosition.y + (_position.y * lowResToScreenY).toInt(); + const int16 scaledY2 = scaledY1 + celHeight - 1; + + const int16 lowResX = (scaledX * screenToLowResX).toInt(); + const int16 lowResY = (scaledY2 * screenToLowResY).toInt(); + + displace.x = (scaledX - (lowResX * lowResToScreenX).toInt()) * -1; + displace.y = (lowResY * lowResToScreenY).toInt() - scaledY1; + _screenItemX[screenItemIndex] = lowResX; + _screenItemY[screenItemIndex] = lowResY; + + debugC(kDebugLevelVideo, "Low resolution position c: %d %d l: %d/%d %d/%d d: %d %d s: %d/%d %d/%d x: %d y: %d", celPosition.x, celPosition.y, lowResX, scriptWidth, lowResY, scriptHeight, displace.x, displace.y, scaledX, screenWidth, scaledY2, screenHeight, scaledX - displace.x, scaledY2 - displace.y); + } else { + const int16 highResX = celPosition.x + _position.x; + const int16 highResY = celPosition.y + _position.y + celHeight - 1; + + displace.x = 0; + displace.y = celHeight - 1; + _screenItemX[screenItemIndex] = highResX; + _screenItemY[screenItemIndex] = highResY; + + debugC(kDebugLevelVideo, "High resolution position c: %d %d s: %d %d d: %d %d", celPosition.x, celPosition.y, highResX, highResY, displace.x, displace.y); + } + + _originalScreenItemX[screenItemIndex] = celPosition.x; + _originalScreenItemY[screenItemIndex] = celPosition.y; + + assert(_celHandles[screenItemIndex].area >= celWidth * celHeight); + + SciBitmap &bitmap = *_segMan->lookupBitmap(_celHandles[screenItemIndex].bitmapId); + assert(bitmap.getWidth() == celWidth && bitmap.getHeight() == celHeight); + assert(bitmap.getScaledWidth() == _xResolution && bitmap.getScaledHeight() == _yResolution); + assert(bitmap.getHunkPaletteOffset() == (uint32)bitmap.getWidth() * bitmap.getHeight() + SciBitmap::getBitmapHeaderSize()); + bitmap.setDisplace(displace); + + byte *targetBuffer = nullptr; + if (_verticalScaleFactor == 100) { + // direct copy to bitmap + targetBuffer = bitmap.getPixels(); + } else { + // go through squashed cel decompressor + _celDecompressionBuffer.resize(_celDecompressionArea >= celWidth * (celHeight * _verticalScaleFactor / 100)); + targetBuffer = _celDecompressionBuffer.begin(); + } + + for (int i = 0; i < numDataChunks; ++i) { + uint compressedSize = READ_SCI11ENDIAN_UINT32(rawVideoData); + uint decompressedSize = READ_SCI11ENDIAN_UINT32(rawVideoData + 4); + uint16 compressionType = READ_SCI11ENDIAN_UINT16(rawVideoData + 8); + rawVideoData += 10; + + switch (compressionType) { + case kCompressionLZS: { + Common::MemoryReadStream videoDataStream(rawVideoData, compressedSize, DisposeAfterUse::NO); + _decompressor.unpack(&videoDataStream, targetBuffer, compressedSize, decompressedSize); + break; + } + case kCompressionNone: + Common::copy(rawVideoData, rawVideoData + decompressedSize, targetBuffer); + break; + default: + error("Unknown compression type %d!", compressionType); + } + + rawVideoData += compressedSize; + targetBuffer += decompressedSize; + } + + if (_verticalScaleFactor != 100) { + expandCel(bitmap.getPixels(), _celDecompressionBuffer.begin(), celWidth, celHeight); + } + + if (usePalette) { + Common::copy(_rawPalette, _rawPalette + kRawPaletteSize, bitmap.getHunkPalette()); + } + + return kCelHeaderSize + dataSize; } -Audio::AudioStream *RobotDecoder::RobotAudioTrack::getAudioStream() const { - return _audioStream; +void RobotDecoder::preallocateCelMemory(const byte *rawVideoData, const int16 numCels) { + for (CelHandleList::size_type i = 0; i < _celHandles.size(); ++i) { + CelHandleInfo &celHandle = _celHandles[i]; + + if (celHandle.status == CelHandleInfo::kFrameLifetime) { + _segMan->freeBitmap(celHandle.bitmapId); + celHandle.bitmapId = NULL_REG; + celHandle.status = CelHandleInfo::kNoCel; + celHandle.area = 0; + } + } + _celHandles.resize(numCels); + + const int numFixedCels = MIN(numCels, (int16)kFixedCelListSize); + for (int i = 0; i < numFixedCels; ++i) { + CelHandleInfo &celHandle = _celHandles[i]; + + // NOTE: There was a check to see if the cel handle was not allocated + // here, for some reason, which would mean that nothing was ever + // allocated from fixed cels, because the _celHandles array just got + // deleted and recreated... + if (celHandle.bitmapId == NULL_REG) { + break; + } + + celHandle.bitmapId = _fixedCels[i]; + celHandle.status = CelHandleInfo::kRobotLifetime; + celHandle.area = _maxCelArea[i]; + } + + uint maxFrameArea = 0; + for (int i = 0; i < numCels; ++i) { + const int16 celWidth = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 2); + const int16 celHeight = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 4); + const uint16 dataSize = READ_SCI11ENDIAN_UINT16(rawVideoData + 14); + const uint area = celWidth * celHeight; + + if (area > maxFrameArea) { + maxFrameArea = area; + } + + CelHandleInfo &celHandle = _celHandles[i]; + if (celHandle.status == CelHandleInfo::kRobotLifetime) { + if (_maxCelArea[i] < area) { + _segMan->freeBitmap(celHandle.bitmapId); + _segMan->allocateBitmap(&celHandle.bitmapId, celWidth, celHeight, 255, 0, 0, _xResolution, _yResolution, kRawPaletteSize, false, false); + celHandle.area = area; + celHandle.status = CelHandleInfo::kFrameLifetime; + } + } else if (celHandle.status == CelHandleInfo::kNoCel) { + _segMan->allocateBitmap(&celHandle.bitmapId, celWidth, celHeight, 255, 0, 0, _xResolution, _yResolution, kRawPaletteSize, false, false); + celHandle.area = area; + celHandle.status = CelHandleInfo::kFrameLifetime; + } else { + error("Cel Handle has bad status"); + } + + rawVideoData += kCelHeaderSize + dataSize; + } + + if (maxFrameArea > _celDecompressionBuffer.size()) { + _celDecompressionBuffer.resize(maxFrameArea); + } } } // End of namespace Sci diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h index 4faea5008a..9d8c720968 100644 --- a/engines/sci/video/robot_decoder.h +++ b/engines/sci/video/robot_decoder.h @@ -20,109 +20,1412 @@ * */ -#ifndef SCI_VIDEO_ROBOT_DECODER_H -#define SCI_VIDEO_ROBOT_DECODER_H +#ifndef SCI_SOUND_DECODERS_ROBOT_H +#define SCI_SOUND_DECODERS_ROBOT_H -#include "common/rational.h" -#include "common/rect.h" -#include "video/video_decoder.h" +#include "audio/audiostream.h" // for AudioStream +#include "audio/rate.h" // for st_sample_t +#include "common/array.h" // for Array +#include "common/mutex.h" // for StackLock, Mutex +#include "common/rect.h" // for Point, Rect (ptr only) +#include "common/scummsys.h" // for int16, int32, byte, uint16 +#include "sci/engine/vm_types.h" // for NULL_REG, reg_t +#include "sci/graphics/helpers.h" // for GuiResourceId +#include "sci/graphics/screen_item32.h" // for ScaleInfo, ScreenItem (ptr o... -namespace Audio { -class QueuingAudioStream; -} +namespace Common { class SeekableSubReadStreamEndian; } +namespace Sci { +class Plane; +class SegManager; -namespace Common { -class SeekableSubReadStreamEndian; -} +// There were 3 different Robot video versions, used in the following games: +// - v4: PQ:SWAT demo +// - v5: KQ7 DOS, Phantasmagoria, PQ:SWAT, Lighthouse +// - v6: RAMA +// +// Notes on Robot v5/v6 format: +// +// Robot is a packetized streaming AV format that encodes multiple bitmaps + +// positioning data, plus synchronised audio, for rendering in the SCI graphics +// system. +// +// Unlike traditional AV formats, Robot videos almost always require playback +// within the game engine because certain information (like the resolution of +// the Robot coordinates and the background for the video) is dependent on data +// that does not exist within the Robot file itself. +// +// The Robot container consists of a file header, an optional primer audio +// section, an optional colour palette, a frame seek index, a set of cuepoints, +// and variable-sized packets of compressed video+audio data. +// +// Integers in Robot files are coded using native endianness (LSB for x86 +// versions, MSB for 68k/PPC versions). +// +// Robot video coding is a relatively simple variable-length compression with no +// interframe compression. Each cel in a frame is constructed from multiple +// contiguous data blocks, each of which can be independently compressed with +// LZS or left uncompressed. An entire cel can also be line decimated, where +// lines are deleted from the source bitmap at compression time and are +// reconstructed by decompression using line doubling. Each cel also includes +// coordinates where it should be placed within the video frame, relative to the +// top-left corner of the frame. +// +// Audio coding is fixed-length, and all audio blocks except for the primer +// audio are the same size. Audio is encoded with Sierra SOL DPCM16 compression, +// and is split into two channels ('even' and 'odd'), each at a 11025Hz sample +// rate. The original signal is restored by interleaving samples from the two +// channels together. Channel packets are 'even' if they have an ''absolute +// position of audio'' that is evenly divisible by 2; otherwise, they are 'odd'. +// Because the channels use DPCM compression, there is an 8-byte runway at the +// start of every audio block that is never written to the output stream, which +// is used to move the signal to the correct location by the 9th sample. +// +// File header (v5/v6): +// +// byte | description +// 0 | signature 0x16 +// 1 | unused +// 2-5 | signature 'SOL\0' +// 6-7 | version (4, 5, and 6 are the only known versions) +// 8-9 | size of audio blocks +// 10-11 | primer is compressed flag +// 12-13 | unused +// 14-15 | total number of video frames +// 16-17 | embedded palette size, in bytes +// 18-19 | primer reserved size +// 20-21 | coordinate X-resolution (if 0, uses game coordinates) +// 22-23 | coordinate Y-resolution (if 0, uses game coordinates) +// 24 | if non-zero, Robot includes a palette +// 25 | if non-zero, Robot includes audio +// 26-27 | unused +// 28-29 | the frame rate, in frames per second +// 30-31 | coordinate conversion flag; if true, screen item coordinates +// | from the robot should be used as-is with NO conversion when +// | explicitly displaying a specific frame +// 32-33 | the maximum number of packets that can be skipped without causing +// | audio drop-out +// 34-35 | the maximum possible number of cels that will be displayed in any +// | frame of the robot +// 36-39 | the maximum possible size, in bytes, of the first fixed cel +// 40-43 | the maximum possible size, in bytes, of the second fixed cel +// 44-47 | the maximum possible size, in bytes, of the third fixed cel +// 48-51 | the maximum possible size, in bytes, of the fourth fixed cel +// 52-59 | unused +// +// If the ''file includes audio'' flag is false, seek ''primer reserved size'' +// bytes from the end of the file header to get past a padding zone. +// +// If the ''file includes audio'' flag is true, and the ''primer reserved size'' +// is not zero, the data immediately after the file header consists of an audio +// primer header plus compressed audio data: +// +// Audio primer header: +// +// byte | description +// 0-3 | the size, in bytes, of the entire primer audio section +// 4-5 | the compression format of the primer audio (must be zero) +// 6-9 | the size, in bytes, of the "even" primer +// 10-13 | the size, in bytes, of the "odd" primer +// +// If the combined sizes of the even and odd primers do not match the ''primer +// reserved size'', the next header block can be found ''primer reserved size'' +// bytes from the *start* of the audio primer header. +// +// Otherwise, if the Robot has audio, and the ''primer reserved size'' is zero, +// and the ''primer is compressed flag'' is set, the "even" primer size is +// 19922, the "odd" primer size is 21024, and the "even" and "odd" buffers +// should be zero-filled. +// +// Any other combination of these flags is an error. +// +// If the Robot has a palette, the next ''palette size'' bytes should be read +// as a SCI HunkPalette. Otherwise, seek ''palette size'' bytes from the current +// position to get to the frame index. +// +// The next section of the Robot is the video frame size index. In version 5 +// robots, read ''total number of frames'' 16-bit integers to get the size of +// the compressed video for each frame. For version 6 robots, use 32-bit +// integers. +// +// The next section of the Robot is the packet size index (combined compressed +// size of video + audio for each frame). In version 5 Robots, read ''total +// number of frames'' 16-bit integers. In version 6 robots, use 32-bit integers. +// +// The next section of the Robot is the cue times index. Read 256 32-bit +// integers, which represent the number of ticks from the start of playback that +// the given cue point falls on. +// +// The next section of the Robot is the cue values index. Read 256 16-bit +// integers, which represent the actual cue values that will be passed back to +// the game engine when a cue is requested. +// +// Finally, to get to the first frame packet, seek from the current position to +// the start of the next 2048-byte-aligned sector. +// +// Frame packet: +// +// byte | description +// 0..n | video data (size is in the ''video frame size index'') +// n+1.. | optional audio data (size is ''size of audio blocks'') +// +// Video data: +// +// byte | description +// 0-2 | number of cels in the frame (max 10) +// 3..n | cels +// +// Cel: +// +// 0-17 | cel header +// 18..n | data chunks +// +// Cel header: +// +// byte | description +// 0 | unused +// 1 | vertical scale factor, in percent decimation (100 = no decimation, +// | 50 = 50% of lines were removed) +// 2-3 | cel width +// 4-5 | cel height +// 6-9 | unused +// 10-11 | cel x-position, in Robot coordinates +// 12-13 | cel y-position, in Robot coordinates +// 14-15 | cel total data chunk size, in bytes +// 16-17 | number of data chunks +// +// Cel data chunk: +// +// 0-9 | cel data chunk header +// 10..n | cel data +// +// Cel data chunk header: +// +// byte | description +// 0-3 | compressed size +// 4-7 | decompressed size +// 8-9 | compression type (0 = LZS, 2 = uncompressed) +// +// Random frame seeking can be done by calculating the address of the frame +// packet by adding up the ''packet size index'' entries up to the current +// frame. This will normally disable audio playback, as audio data in a packet +// does not correspond to the video in the same packet. +// +// Audio data is placed immediately after the end of the video data in a packet, +// and consists of an audio header plus compressed audio data: +// +// Audio data: +// +// byte | description +// 0-7 | audio data header +// 8-15 | DPCM runway +// 16..n | compressed audio data +// +// Audio data header: +// +// byte | description +// 0-3 | absolute position of audio in the audio stream +// 4-7 | the size of the audio block, excluding the header +// +// When a block of audio is processed, first check to ensure that the +// decompressed audio block's `position * 2 + length * 4` runs past the end of +// the last packet of the same evenness/oddness. Discard the audio block +// entirely if data has already been written past the end of this block for this +// channel, or if the read head has already read past the end of this audio +// block. +// +// If the block is not discarded, apply DPCM decompression to the entire block, +// starting from beginning of the DPCM runway, using an initial sample value of +// 0. Then, copy every sample from the decompressed source outside of the DPCM +// runway into every *other* sample of the final audio buffer (1 -> 2, 2 -> 4, +// 3 -> 6, etc.). +// +// Finally, for any skipped samples where the opposing (even/odd) channel did +// not yet write, interpolate the skipped areas by adding together the +// neighbouring samples from this audio block and dividing by two. (This allows +// the audio quality to degrade to 11kHz in case it takes too long to decode all +// the frames in the stream). Interpolated samples must not be written on top of +// true data from the opposing channel. Audio from later packets must also not +// be written on top of data in the same channel that was already written by an +// earlier packet, in particular because the first 8 bytes of the next packet +// are garbage data used to move the waveform to the correct position (due to +// the use of DPCM compression). -namespace Sci { +#pragma mark - +#pragma mark RobotAudioStream + +/** + * A Robot audio stream is a simple loop buffer + * that accepts audio blocks from the Robot engine. + */ +class RobotAudioStream : public Audio::AudioStream { +public: + enum { + /** + * The sample rate used for all robot audio. + */ + kRobotSampleRate = 22050, + + /** + * Multiplier for the size of a packet that + * is being expanded by writing to every other + * byte of the target buffer. + */ + kEOSExpansion = 2 + }; + + /** + * Playback state information. Used for framerate + * calculation. + */ + struct StreamState { + /** + * The current position of the read head of + * the audio stream. + */ + int bytesPlaying; + + /** + * The sample rate of the audio stream. + * Always 22050. + */ + uint16 rate; + + /** + * The bit depth of the audio stream. + * Always 16. + */ + uint8 bits; + }; + + /** + * A single packet of compressed audio from a + * Robot data stream. + */ + struct RobotAudioPacket { + /** + * Raw DPCM-compressed audio data. + */ + byte *data; + + /** + * The size of the compressed audio data, + * in bytes. + */ + int dataSize; + + /** + * The uncompressed, file-relative position + * of this audio packet. + */ + int position; + + RobotAudioPacket(byte *data_, const int dataSize_, const int position_) : + data(data_), dataSize(dataSize_), position(position_) {} + }; + + RobotAudioStream(const int32 bufferSize); + virtual ~RobotAudioStream(); + + /** + * Adds a new audio packet to the stream. + * @returns `true` if the audio packet was fully + * consumed, otherwise `false`. + */ + bool addPacket(const RobotAudioPacket &packet); + + /** + * Prevents any additional audio packets from + * being added to the audio stream. + */ + void finish(); + + /** + * Returns the current status of the audio + * stream. + */ + StreamState getStatus() const; + +private: + Common::Mutex _mutex; + + /** + * Loop buffer for playback. Contains decompressed + * 16-bit PCM samples. + */ + byte *_loopBuffer; + + /** + * The size of the loop buffer, in bytes. + */ + int32 _loopBufferSize; + + /** + * The position of the read head within the loop + * buffer, in bytes. + */ + int32 _readHead; + + /** + * The lowest file position that can be buffered, + * in uncompressed bytes. + */ + int32 _readHeadAbs; + + /** + * The highest file position that can be buffered, + * in uncompressed bytes. + */ + int32 _maxWriteAbs; + + /** + * The highest file position, in uncompressed bytes, + * that has been written to the stream. + * Different from `_maxWriteAbs`, which is the highest + * uncompressed position which *can* be written right + * now. + */ + int32 _writeHeadAbs; + + /** + * The highest file position, in uncompressed bytes, + * that has been written to the even & odd sides of + * the stream. + * + * Index 0 corresponds to the 'even' side; index + * 1 correspond to the 'odd' side. + */ + int32 _jointMin[2]; + + /** + * When `true`, the stream is waiting for all primer + * blocks to be received before allowing playback to + * begin. + */ + bool _waiting; + + /** + * When `true`, the stream will accept no more audio + * blocks. + */ + bool _finished; + + /** + * The uncompressed position of the first packet of + * robot data. Used to decide whether all primer + * blocks have been received and the stream should + * be started. + */ + int32 _firstPacketPosition; + + /** + * Decompression buffer, used to temporarily store + * an uncompressed block of audio data. + */ + byte *_decompressionBuffer; + + /** + * The size of the decompression buffer, in bytes. + */ + int32 _decompressionBufferSize; + + /** + * The position of the packet currently in the + * decompression buffer. Used to avoid + * re-decompressing audio data that has already + * been decompressed during a partial packet read. + */ + int32 _decompressionBufferPosition; + + /** + * Calculates the absolute ranges for new fills + * into the loop buffer. + */ + void fillRobotBuffer(const RobotAudioPacket &packet, const int8 bufferIndex); + + /** + * Interpolates `numSamples` samples from the read + * head, if no true samples were written for one + * (or both) of the joint channels. + */ + void interpolateMissingSamples(const int32 numSamples); + +#pragma mark - +#pragma mark RobotAudioStream - AudioStream implementation +public: + int readBuffer(Audio::st_sample_t *outBuffer, int numSamples) override; + virtual bool isStereo() const override { return false; }; + virtual int getRate() const override { return 22050; }; + virtual bool endOfData() const override { + Common::StackLock lock(_mutex); + return _readHeadAbs >= _writeHeadAbs; + }; + virtual bool endOfStream() const override { + Common::StackLock lock(_mutex); + return _finished && endOfData(); + } +}; + +#pragma mark - +#pragma mark RobotDecoder + +/** + * RobotDecoder implements the logic required + * for Robot animations. + * + * @note A paused or finished RobotDecoder was + * classified as serializable in SCI3, but the + * save/load code would attempt to use uninitialised + * values, so it seems that robots were not ever + * actually able to be saved. + */ +class RobotDecoder { +public: + RobotDecoder(SegManager *segMan); + ~RobotDecoder(); + +private: + SegManager *_segMan; + +#pragma mark Constants +public: + /** + * The playback status of the robot. + */ + enum RobotStatus { + kRobotStatusUninitialized = 0, + kRobotStatusPlaying = 1, + kRobotStatusEnd = 2, + kRobotStatusPaused = 3 + }; + + enum { + // Special high value used to represent + // parameters that should be left unchanged + // when calling `showFrame` + kUnspecified = 50000 + }; + +private: + enum { + /** + * Maximum number of on-screen screen items. + */ + kScreenItemListSize = 10, + + /** + * Maximum number of queued audio blocks. + */ + kAudioListSize = 10, + + /** + * Maximum number of samples used for frame timing. + */ + kDelayListSize = 10, + + /** + * Maximum number of cues. + */ + kCueListSize = 256, + + /** + * Maximum number of 'fixed' cels that never + * change for the duration of a robot. + */ + kFixedCelListSize = 4, + + /** + * The size of a hunk palette in the Robot stream. + */ + kRawPaletteSize = 1200, + + /** + * The size of a frame of Robot data. This + * value was used to align the first block of + * data after the main Robot header to the next + * CD sector. + */ + kRobotFrameSize = 2048, + + /** + * The size of a block of zero-compressed + * audio. Used to fill audio when the size of + * an audio packet does not match the expected + * packet size. + */ + kRobotZeroCompressSize = 2048, -class RobotDecoder : public Video::VideoDecoder { + /** + * The size of the audio block header, in bytes. + * The audio block header consists of the + * compressed size of the audio in the record, + * plus the position of the audio in the + * compressed data stream. + */ + kAudioBlockHeaderSize = 8, + + /** + * The size of a Robot cel header, in bytes. + */ + kCelHeaderSize = 22, + + /** + * The maximum amount that the frame rate is + * allowed to drift from the nominal frame rate + * in order to correct for AV drift or slow + * playback. + */ + kMaxFrameRateDrift = 1 + }; + + /** + * The version number for the currently loaded + * robot. + * + * There are several known versions of robot: + * + * v2: before Nov 1994; no known examples + * v3: before Nov 1994; no known examples + * v4: Jan 1995; PQ:SWAT demo + * v5: Mar 1995; SCI2.1 and SCI3 games + * v6: SCI3 games + */ + uint16 _version; + +#pragma mark - +#pragma mark Initialisation +private: + /** + * Sets up the read stream for the robot. + */ + void initStream(const GuiResourceId robotId); + + /** + * Sets up the initial values for playback control. + */ + void initPlayback(); + + /** + * Sets up the initial values for audio decoding. + */ + void initAudio(); + + /** + * Sets up the initial values for video rendering. + */ + void initVideo(const int16 x, const int16 y, const int16 scale, const reg_t plane, const bool hasPalette, const uint16 paletteSize); + + /** + * Sets up the robot's data record and cue positions. + */ + void initRecordAndCuePositions(); + +#pragma mark - +#pragma mark Playback public: - RobotDecoder(bool isBigEndian); - virtual ~RobotDecoder(); + /** + * Opens a robot file for playback. + * Newly opened robots are paused by default. + */ + void open(const GuiResourceId robotId, const reg_t plane, const int16 priority, const int16 x, const int16 y, const int16 scale); - bool loadStream(Common::SeekableReadStream *stream); - bool load(GuiResourceId id); + /** + * Closes the currently open robot file. + */ void close(); - void setPos(uint16 x, uint16 y) { _pos = Common::Point(x, y); } - Common::Point getPos() const { return _pos; } + /** + * Pauses the robot. Once paused, the audio for a robot + * is disabled until the end of playback. + */ + void pause(); + + /** + * Resumes a paused robot. + */ + void resume(); + + /** + * Moves robot to the specified frame and pauses playback. + * + * @note Called DisplayFrame in SSCI. + */ + void showFrame(const uint16 frameNo, const uint16 newX, const uint16 newY, const uint16 newPriority); + + /** + * Retrieves the value associated with the + * current cue point. + */ + int16 getCue() const; + + /** + * Gets the currently displayed frame. + */ + int16 getFrameNo() const; + + /** + * Gets the playback status of the player. + */ + RobotStatus getStatus() const; + +private: + /** + * The read stream containing raw robot data. + */ + Common::SeekableSubReadStreamEndian *_stream; + + /** + * The current status of the player. + */ + RobotStatus _status; + + typedef Common::Array<int> PositionList; + + /** + * A map of frame numbers to byte offsets within `_stream`. + */ + PositionList _recordPositions; + + /** + * The offset of the Robot file within a + * resource bundle. + */ + int32 _fileOffset; + + /** + * A list of cue times that is updated to + * prevent earlier cue values from being + * given to the game more than once. + */ + mutable int32 _cueTimes[kCueListSize]; + + /** + * The original list of cue times from the + * raw Robot data. + */ + int32 _masterCueTimes[kCueListSize]; + + /** + * The list of values to provide to a game + * when a cue value is requested. + */ + int32 _cueValues[kCueListSize]; + + /** + * The current playback frame rate. + */ + int16 _frameRate; + + /** + * The nominal playback frame rate. + */ + int16 _normalFrameRate; + + /** + * The minimal playback frame rate. Used to + * correct for AV sync drift when the video + * is more than one frame ahead of the audio. + */ + int16 _minFrameRate; + + /** + * The maximum playback frame rate. Used to + * correct for AV sync drift when the video + * is more than one frame behind the audio. + */ + int16 _maxFrameRate; + + /** + * The maximum number of record blocks that + * can be skipped without causing audio to + * drop out. + */ + int16 _maxSkippablePackets; + + /** + * The currently displayed frame number. + */ + int _currentFrameNo; + + /** + * The last displayed frame number. + */ + int _previousFrameNo; + + /** + * The time, in ticks, when the robot was + * last started or resumed. + */ + int32 _startTime; + + /** + * The first frame displayed when the + * robot was resumed. + */ + int32 _startFrameNo; + + /** + * The last frame displayed when the robot + * was resumed. + */ + int32 _startingFrameNo; + + /** + * Seeks the raw data stream to the record for + * the given frame number. + */ + bool seekToFrame(const int frameNo); -protected: - void readNextPacket(); + /** + * Sets the start time and frame of the robot + * when the robot is started or resumed. + */ + void setRobotTime(const int frameNo); +#pragma mark - +#pragma mark Timing private: - class RobotVideoTrack : public FixedRateVideoTrack { + /** + * This class tracks the amount of time it takes for + * a frame of robot animation to be rendered. This + * information is used by the player to speculatively + * skip rendering of future frames to keep the + * animation in sync with the robot audio. + */ + class DelayTime { public: - RobotVideoTrack(int frameCount); - ~RobotVideoTrack(); - - uint16 getWidth() const; - uint16 getHeight() const; - Graphics::PixelFormat getPixelFormat() const; - int getCurFrame() const { return _curFrame; } - int getFrameCount() const { return _frameCount; } - const Graphics::Surface *decodeNextFrame() { return _surface; } - const byte *getPalette() const { _dirtyPalette = false; return _palette; } - bool hasDirtyPalette() const { return _dirtyPalette; } - - void readPaletteChunk(Common::SeekableSubReadStreamEndian *stream, uint16 chunkSize); - void calculateVideoDimensions(Common::SeekableSubReadStreamEndian *stream, uint32 *frameSizes); - Graphics::Surface *getSurface() { return _surface; } - void increaseCurFrame() { _curFrame++; } - - protected: - Common::Rational getFrameRate() const { return Common::Rational(60, 10); } + DelayTime(RobotDecoder *decoder); + + /** + * Starts performance timing. + */ + void startTiming(); + + /** + * Ends performance timing. + */ + void endTiming(); + + /** + * Returns whether or not timing is currently in + * progress. + */ + bool timingInProgress() const; + + /** + * Returns the median time, in ticks, of the + * currently stored timing samples. + */ + int predictedTicks() const; private: - int _frameCount; - int _curFrame; - byte _palette[256 * 3]; - mutable bool _dirtyPalette; - Graphics::Surface *_surface; + RobotDecoder *_decoder; + + /** + * The start time, in ticks, of the current timing + * loop. If no loop is in progress, the value is 0. + * + * @note This is slightly different than SSCI where + * the not-timing value was -1. + */ + uint32 _startTime; + + /** + * A sorted list containing the timing data for + * the last `kDelayListSize` frames, in ticks. + */ + int _delays[kDelayListSize]; + + /** + * A list of monotonically increasing identifiers + * used to identify and replace the oldest sample + * in the `_delays` array when finishing the + * next timing operation. + */ + uint _timestamps[kDelayListSize]; + + /** + * The identifier of the oldest timing. + */ + uint _oldestTimestamp; + + /** + * The identifier of the newest timing. + */ + uint _newestTimestamp; + + /** + * Sorts the list of timings. + */ + void sortList(); }; - class RobotAudioTrack : public AudioTrack { + /** + * Calculates the next frame number that needs + * to be rendered, using the timing data + * collected by DelayTime. + */ + uint16 calculateNextFrameNo(const uint32 extraTicks = 0) const; + + /** + * Calculates and returns the number of frames + * that should be rendered in `ticks` time, + * according to the current target frame rate + * of the robot. + */ + uint32 ticksToFrames(const uint32 ticks) const; + + /** + * Gets the current game time, in ticks. + */ + uint32 getTickCount() const; + + /** + * The performance timer for the robot. + */ + DelayTime _delayTime; + +#pragma mark - +#pragma mark Audio +private: + enum { + /** + * The number of ticks that should elapse + * between each AV sync check. + */ + kAudioSyncCheckInterval = 5 * 60 /* 5 seconds */ + }; + + /** + * The status of the audio track of a Robot + * animation. + */ + enum RobotAudioStatus { + kRobotAudioReady = 1, + kRobotAudioStopped = 2, + kRobotAudioPlaying = 3, + kRobotAudioPaused = 4, + kRobotAudioStopping = 5 + }; + +#pragma mark - +#pragma mark Audio - AudioList +private: + /** + * This class manages packetized audio playback + * for robots. + */ + class AudioList { public: - RobotAudioTrack(); - ~RobotAudioTrack(); + AudioList(); + + /** + * Starts playback of robot audio. + */ + void startAudioNow(); + + /** + * Stops playback of robot audio, allowing + * any queued audio to finish playing back. + */ + void stopAudio(); + + /** + * Stops playback of robot audio immediately. + */ + void stopAudioNow(); + + /** + * Submits as many blocks of audio as possible + * to the audio engine. + */ + void submitDriverMax(); + + /** + * Adds a new AudioBlock to the queue. + * + * @param position The absolute position of the + * audio for the block, in compressed bytes. + * @param size The size of the buffer. + * @param buffer A pointer to compressed audio + * data that will be copied into the new + * AudioBlock. + */ + void addBlock(const int position, const int size, const byte *buffer); - Audio::Mixer::SoundType getSoundType() const { return Audio::Mixer::kMusicSoundType; } + /** + * Immediately stops any active playback and + * purges all audio data in the audio list. + */ + void reset(); - void queueBuffer(byte *buffer, int size); + /** + * Pauses the robot audio channel in + * preparation for the first block of audio + * data to be read. + */ + void prepareForPrimer(); - protected: - Audio::AudioStream *getAudioStream() const; + /** + * Sets the audio offset which is used to + * offset the position of audio packets + * sent to the audio stream. + */ + void setAudioOffset(const int offset); + +#pragma mark - +#pragma mark Audio - AudioList - AudioBlock private: - Audio::QueuingAudioStream *_audioStream; + /** + * AudioBlock represents a block of audio + * from the Robot's audio track. + */ + class AudioBlock { + public: + AudioBlock(const int position, const int size, const byte *const data); + ~AudioBlock(); + + /** + * Submits the block of audio to the + * audio manager. + * @returns true if the block was fully + * read, or false if the block was not + * read or only partially read. + */ + bool submit(const int startOffset); + + private: + /** + * The absolute position, in compressed + * bytes, of this audio block's audio + * data in the audio stream. + */ + int _position; + + /** + * The compressed size, in bytes, of + * this audio block's audio data. + */ + int _size; + + /** + * A buffer containing raw + * SOL-compressed audio data. + */ + byte *_data; + }; + + /** + * The list of compressed audio blocks + * submitted for playback. + */ + AudioBlock *_blocks[kAudioListSize]; + + /** + * The number of blocks in `_blocks` that are + * ready to be submitted. + */ + uint8 _blocksSize; + + /** + * The index of the oldest submitted audio block. + */ + uint8 _oldestBlockIndex; + + /** + * The index of the newest submitted audio block. + */ + uint8 _newestBlockIndex; + + /** + * The offset used when sending packets to the + * audio stream. + */ + int _startOffset; + + /** + * The status of robot audio playback. + */ + RobotAudioStatus _status; + + /** + * Frees all audio blocks in the `_blocks` list. + */ + void freeAudioBlocks(); }; - struct RobotHeader { - // 6 bytes, identifier bytes - uint16 version; - uint16 audioChunkSize; - uint16 audioSilenceSize; - // 2 bytes, unknown - uint16 frameCount; - uint16 paletteDataSize; - uint16 unkChunkDataSize; - // 5 bytes, unknown - byte hasSound; - // 34 bytes, unknown - } _header; - - void readHeaderChunk(); - void readFrameSizesChunk(); - - Common::Point _pos; - bool _isBigEndian; - uint32 *_frameTotalSize; - - Common::SeekableSubReadStreamEndian *_fileStream; -}; + /** + * Whether or not this robot animation has + * an audio track. + */ + bool _hasAudio; + + /** + * The audio list for the current robot. + */ + AudioList _audioList; + + /** + * The size, in bytes, of a block of audio data, + * excluding the audio block header. + */ + uint16 _audioBlockSize; + + /** + * The expected size of a block of audio data, + * in bytes, excluding the audio block header. + */ + int16 _expectedAudioBlockSize; + + /** + * The number of compressed audio bytes that are + * needed per frame to fill the audio buffer + * without causing audio to drop out. + */ + int16 _audioRecordInterval; + + /** + * If true, primer audio buffers should be filled + * with silence instead of trying to read buffers + * from the Robot data. + */ + uint16 _primerZeroCompressFlag; + + /** + * The size, in bytes, of the primer audio in the + * Robot, including any extra alignment padding. + */ + uint16 _primerReservedSize; + + /** + * The combined size, in bytes, of the even and odd + * primer channels. + */ + int32 _totalPrimerSize; + + /** + * The absolute offset of the primer audio data in + * the robot data stream. + */ + int32 _primerPosition; + + /** + * The size, in bytes, of the even primer. + */ + int32 _evenPrimerSize; + + /** + * The size, in bytes, of the odd primer. + */ + int32 _oddPrimerSize; + + /** + * The absolute position in the audio stream of + * the first audio packet. + */ + int32 _firstAudioRecordPosition; -} // End of namespace Sci + /** + * A temporary buffer used to hold one frame of + * raw (DPCM-compressed) audio when reading audio + * records from the robot stream. + */ + byte *_audioBuffer; + /** + * The next tick count when AV sync should be + * checked and framerate adjustments made, if + * necessary. + */ + uint32 _checkAudioSyncTime; + + /** + * Primes the audio buffer with the first frame + * of audio data. + * + * @note `primeAudio` was `InitAudio` in SSCI + */ + bool primeAudio(const uint32 startTick); + + /** + * Reads primer data from the robot data stream + * and puts it into the given buffers. + */ + bool readPrimerData(byte *outEvenBuffer, byte *outOddBuffer); + + /** + * Reads audio data for the given frame number + * into the given buffer. + * + * @param outAudioPosition The position of the + * audio, in compressed bytes, in the data stream. + * @param outAudioSize The size of the audio data, + * in compressed bytes. + */ + bool readAudioDataFromRecord(const int frameNo, byte *outBuffer, int &outAudioPosition, int &outAudioSize); + + /** + * Submits part of the audio packet of the given + * frame to the audio list, starting `startPosition` + * bytes into the audio. + */ + bool readPartialAudioRecordAndSubmit(const int startFrame, const int startPosition); + +#pragma mark - +#pragma mark Rendering +public: + /** + * Puts the current dimensions of the robot, in game script + * coordinates, into the given rect, and returns the total + * number of frames in the robot animation. + */ + uint16 getFrameSize(Common::Rect &outRect) const; + + /** + * Pumps the robot player for the next frame of video. + * This is the main rendering function. + */ + void doRobot(); + + /** + * Submits any outstanding audio blocks that should + * be added to the queue before the robot frame + * becomes visible. + */ + void frameAlmostVisible(); + + /** + * Evaluates frame drift and makes modifications to + * the player in order to ensure that future frames + * will arrive on time. + */ + void frameNowVisible(); + + /** + * Scales a vertically compressed cel to its original + * uncompressed dimensions. + */ + void expandCel(byte *target, const byte* source, const int16 celWidth, const int16 celHeight) const; + + /** + * Sets the visual priority of the robot. + * @see Plane::_priority + */ + void setPriority(const int16 newPriority); + +private: + enum CompressionType { + kCompressionLZS = 0, + kCompressionNone = 2 + }; + + /** + * Describes the state of a Robot video cel. + */ + struct CelHandleInfo { + /** + * The persistence level of Robot cels. + */ + enum CelHandleLifetime { + kNoCel = 0, + kFrameLifetime = 1, + kRobotLifetime = 2 + }; + + /** + * A reg_t pointer to an in-memory + * bitmap containing the cel. + */ + reg_t bitmapId; + + /** + * The lifetime of the cel, either just + * for this frame or for the entire + * duration of the robot playback. + */ + CelHandleLifetime status; + + /** + * The size, in pixels, of the decompressed + * cel. + */ + int area; + + CelHandleInfo() : bitmapId(NULL_REG), status(kNoCel), area(0) {} + }; + + typedef Common::Array<ScreenItem *> RobotScreenItemList; + typedef Common::Array<CelHandleInfo> CelHandleList; + typedef Common::Array<int> VideoSizeList; + typedef Common::Array<uint> MaxCelAreaList; + typedef Common::Array<reg_t> FixedCelsList; + typedef Common::Array<Common::Point> CelPositionsList; + typedef Common::Array<byte> ScratchMemory; + + /** + * Renders a version 5/6 robot frame. + */ + void doVersion5(const bool shouldSubmitAudio = true); + + /** + * Creates screen items for a version 5/6 robot. + */ + void createCels5(const byte *rawVideoData, const int16 numCels, const bool usePalette); + + /** + * Creates a single screen item for a cel in a + * version 5/6 robot. + * + * Returns the size, in bytes, of the raw cel data. + */ + uint32 createCel5(const byte *rawVideoData, const int16 screenItemIndex, const bool usePalette); + + /** + * Preallocates memory for the next `numCels` cels + * in the robot data stream. + */ + void preallocateCelMemory(const byte *rawVideoData, const int16 numCels); + + /** + * The decompressor for LZS-compressed cels. + */ + DecompressorLZS _decompressor; + + /** + * The origin of the robot animation, in screen + * coordinates. + */ + Common::Point _position; + + /** + * Global scaling applied to the robot. + */ + ScaleInfo _scaleInfo; + + /** + * The native resolution of the robot. + */ + int16 _xResolution, _yResolution; + + /** + * Whether or not the coordinates read from robot + * data are high resolution. + */ + bool _isHiRes; + + /** + * The maximum number of cels that will be rendered + * on any given frame in this robot. Used for + * preallocation of cel memory. + */ + int16 _maxCelsPerFrame; + + /** + * The maximum areas, in pixels, for each of + * the fixed cels in the robot. Used for + * preallocation of cel memory. + */ + MaxCelAreaList _maxCelArea; + + /** + * The hunk palette to use when rendering the + * current frame, if the `usePalette` flag was set + * in the robot header. + */ + uint8 *_rawPalette; + + /** + * A list of the raw video data sizes, in bytes, + * for each frame of the robot. + */ + VideoSizeList _videoSizes; + + /** + * A list of cels that will be present for the + * entire duration of the robot animation. + */ + FixedCelsList _fixedCels; + + /** + * A list of handles for each cel in the current + * frame. + */ + CelHandleList _celHandles; + + /** + * Scratch memory used to temporarily store + * decompressed cel data for vertically squashed + * cels. + */ + ScratchMemory _celDecompressionBuffer; + + /** + * The size, in bytes, of the squashed cel + * decompression buffer. + */ + int _celDecompressionArea; + + /** + * If true, the robot just started playing and + * is awaiting output for the first frame. + */ + bool _syncFrame; + + /** + * Scratch memory used to store the compressed robot + * video data for the current frame. + */ + ScratchMemory _doVersion5Scratch; + + /** + * When set to a non-negative value, forces the next + * call to doRobot to render the given frame number + * instead of whatever frame would have normally been + * rendered. + */ + mutable int _cueForceShowFrame; + + /** + * The plane where the robot animation will be drawn. + */ + Plane *_plane; + + /** + * A list of pointers to ScreenItems used by the robot. + */ + RobotScreenItemList _screenItemList; + + /** + * The positions of the various screen items in this + * robot, in screen coordinates. + */ + Common::Array<int16> _screenItemX, _screenItemY; + + /** + * The raw position values from the cel header for + * each screen item currently on-screen. + */ + Common::Array<int16> _originalScreenItemX, _originalScreenItemY; + + /** + * The duration of the current robot, in frames. + */ + uint16 _numFramesTotal; + + /** + * The screen priority of the video. + * @see ScreenItem::_priority + */ + int16 _priority; + + /** + * The amount of visual vertical compression applied + * to the current cel. A value of 100 means no + * compression; a value above 100 indicates how much + * the cel needs to be scaled along the y-axis to + * return to its original dimensions. + */ + uint8 _verticalScaleFactor; +}; +} // end of namespace Sci #endif diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 68e4887b00..81372d0586 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Sat Apr 30 14:24:41 2016 + This file was generated by the md5table tool on Mon Aug 8 18:46:17 2016 DO NOT EDIT MANUALLY! */ @@ -188,6 +188,7 @@ static const MD5Table md5table[] = { { "3b301b7892f883ce42ab4be6a274fea6", "samnmax", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformDOS }, { "3b832f4a90740bf22e9b8ed42ca0128c", "freddi4", "HE 99", "", -1, Common::EN_GRB, Common::kPlatformUnknown }, { "3c4c471342bd95505a42334367d8f127", "puttmoon", "HE 70", "", 12161, Common::RU_RUS, Common::kPlatformWindows }, + { "3c90d2a39cafa60b8ebce70a34a59a41", "airport", "", "Demo", 51152, Common::NL_NLD, Common::kPlatformWindows }, { "3cce1913a3bc586b51a75c3892ff18dd", "indy3", "VGA", "VGA", -1, Common::RU_RUS, Common::kPlatformDOS }, { "3cf4b6ff78f735b671d8ccc2bc110b15", "maniac", "V2", "V2", -1, Common::ES_ESP, Common::kPlatformAmiga }, { "3d219e7546039543307b55a91282bf18", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatformDOS }, diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index a829ab22e6..423be448fe 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -48,7 +48,7 @@ Screen::Screen(SherlockEngine *vm) : BaseSurface(), _vm(vm), Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0); Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0); Common::fill(&_tMap[0], &_tMap[PALETTE_SIZE], 0); - + // Set up the initial font setFont(IS_SERRATED_SCALPEL ? 1 : 4); @@ -172,8 +172,8 @@ void Screen::restoreBackground(const Common::Rect &r) { _backBuffer.SHblitFrom(_backBuffer2, Common::Point(r.left, r.top), r); } -void Screen::slamArea(int16 xp, int16 yp, int16 width, int16 height) { - slamRect(Common::Rect(xp, yp, xp + width, yp + height)); +void Screen::slamArea(int16 xp, int16 yp, int16 width_, int16 height_) { + slamRect(Common::Rect(xp, yp, xp + width_, yp + height_)); } void Screen::slamRect(const Common::Rect &r) { @@ -204,11 +204,11 @@ void Screen::slamRect(const Common::Rect &r) { } } -void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, - int16 *width, int16 *height) { +void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, + int16 *width_, int16 *height_) { Common::Point imgPos = pt + frame->_offset; Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->_frame.w, imgPos.y + frame->_frame.h); - Common::Rect oldBounds(*xp, *yp, *xp + *width, *yp + *height); + Common::Rect oldBounds(*xp, *yp, *xp + *width_, *yp + *height_); if (!_flushScreen) { // See if the areas of the old and new overlap, and if so combine the areas @@ -228,16 +228,16 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, i *xp = newBounds.left; *yp = newBounds.top; - *width = newBounds.width(); - *height = newBounds.height(); + *width_ = newBounds.width(); + *height_ = newBounds.height(); } void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, - int16 *width, int16 *height, int scaleVal) { + int16 *width_, int16 *height_, int scaleVal) { Common::Point imgPos(pt.x + frame->sDrawXOffset(scaleVal), pt.y + frame->sDrawYOffset(scaleVal)); - Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->sDrawXSize(scaleVal), + Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->sDrawXSize(scaleVal), imgPos.y + frame->sDrawYSize(scaleVal)); - Common::Rect oldBounds(*xp, *yp, *xp + *width, *yp + *height); + Common::Rect oldBounds(*xp, *yp, *xp + *width_, *yp + *height_); if (!_flushScreen) { // See if the areas of the old and new overlap, and if so combine the areas @@ -257,8 +257,8 @@ void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 * *xp = newBounds.left; *yp = newBounds.top; - *width = newBounds.width(); - *height = newBounds.height(); + *width_ = newBounds.width(); + *height_ = newBounds.height(); } void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, Common::Rect &newBounds, int scaleVal) { @@ -292,15 +292,15 @@ void Screen::print(const Common::Point &pt, uint color, const char *formatStr, . // Figure out area to draw text in Common::Point pos = pt; - int width = stringWidth(str); + int width_ = stringWidth(str); pos.y--; // Font is always drawing one line higher if (!pos.x) // Center text horizontally - pos.x = (this->width() - width) / 2; + pos.x = (this->width() - width_) / 2; - Common::Rect textBounds(pos.x, pos.y, pos.x + width, pos.y + _fontHeight); + Common::Rect textBounds(pos.x, pos.y, pos.x + width_, pos.y + _fontHeight); if (textBounds.right > this->width()) - textBounds.moveTo(this->width() - width, textBounds.top); + textBounds.moveTo(this->width() - width_, textBounds.top); if (textBounds.bottom > this->height()) textBounds.moveTo(textBounds.left, this->height() - _fontHeight); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index e068ac481a..c6b38f78d7 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -30,6 +30,11 @@ namespace Sherlock { SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Sherlock") { + DebugMan.addDebugChannel(kDebugLevelScript, "scripts", "Script debug level"); + DebugMan.addDebugChannel(kDebugLevelAdLibDriver, "AdLib", "AdLib driver debugging"); + DebugMan.addDebugChannel(kDebugLevelMT32Driver, "MT32", "MT32 driver debugging"); + DebugMan.addDebugChannel(kDebugLevelMusic, "Music", "Music debugging"); + _animation = nullptr; _debugger = nullptr; _events = nullptr; @@ -74,11 +79,6 @@ SherlockEngine::~SherlockEngine() { } void SherlockEngine::initialize() { - DebugMan.addDebugChannel(kDebugLevelScript, "scripts", "Script debug level"); - DebugMan.addDebugChannel(kDebugLevelAdLibDriver, "AdLib", "AdLib driver debugging"); - DebugMan.addDebugChannel(kDebugLevelMT32Driver, "MT32", "MT32 driver debugging"); - DebugMan.addDebugChannel(kDebugLevelMusic, "Music", "Music debugging"); - Fonts::setVm(this); ImageFile::setVm(this); ImageFile3DO::setVm(this); diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp index 93bc001149..cca012630c 100644 --- a/engines/sherlock/surface.cpp +++ b/engines/sherlock/surface.cpp @@ -29,9 +29,9 @@ BaseSurface::BaseSurface() : Graphics::Screen(0, 0), Fonts() { free(); // Free the 0x0 surface allocated by Graphics::Screen } -BaseSurface::BaseSurface(int width, int height) : Graphics::Screen(width, height), +BaseSurface::BaseSurface(int width_, int height_) : Graphics::Screen(width_, height_), Fonts() { - create(width, height); + create(width_, height_); } void BaseSurface::writeString(const Common::String &str, const Common::Point &pt, uint overrideColor) { @@ -61,7 +61,7 @@ void BaseSurface::SHtransBlitFrom(const Graphics::Surface &src, const Common::Po Common::Rect srcRect(0, 0, src.w, src.h); Common::Rect destRect(pt.x, pt.y, pt.x + src.w * SCALE_THRESHOLD / scaleVal, pt.y + src.h * SCALE_THRESHOLD / scaleVal); - + Graphics::Screen::transBlitFrom(src, srcRect, destRect, TRANSPARENCY, flipped, overrideColor); } diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h index 401d9b648d..d55606ed82 100644 --- a/engines/sherlock/surface.h +++ b/engines/sherlock/surface.h @@ -121,7 +121,7 @@ protected: virtual void addDirtyRect(const Common::Rect &r) {} public: Surface() : BaseSurface() {} - Surface(int width, int height) : BaseSurface(width, height) {} + Surface(int width_, int height_) : BaseSurface(width_, height_) {} }; } // End of namespace Sherlock diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 44e81494f7..8ad177abbb 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -821,6 +821,12 @@ const char *const TinselEngine::_textFiles[][3] = { TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _random("tinsel"), _console(0), _sound(0), _midiMusic(0), _pcmMusic(0), _bmv(0) { + // Register debug flags + DebugMan.addDebugChannel(kTinselDebugAnimations, "animations", "Animations debugging"); + DebugMan.addDebugChannel(kTinselDebugActions, "actions", "Actions debugging"); + DebugMan.addDebugChannel(kTinselDebugSound, "sound", "Sound debugging"); + DebugMan.addDebugChannel(kTinselDebugMusic, "music", "Music debugging"); + _vm = this; _gameId = 0; @@ -828,12 +834,6 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) _config = new Config(this); - // Register debug flags - DebugMan.addDebugChannel(kTinselDebugAnimations, "animations", "Animations debugging"); - DebugMan.addDebugChannel(kTinselDebugActions, "actions", "Actions debugging"); - DebugMan.addDebugChannel(kTinselDebugSound, "sound", "Sound debugging"); - DebugMan.addDebugChannel(kTinselDebugMusic, "music", "Music debugging"); - // Setup mixer syncSoundSettings(); diff --git a/engines/titanic/carry/arm.cpp b/engines/titanic/carry/arm.cpp new file mode 100644 index 0000000000..880c93d309 --- /dev/null +++ b/engines/titanic/carry/arm.cpp @@ -0,0 +1,213 @@ +/* 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/carry/arm.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CArm, CCarry) + ON_MESSAGE(PuzzleSolvedMsg) + ON_MESSAGE(TranslateObjectMsg) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MaitreDHappyMsg) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(MouseDragMoveMsg) +END_MESSAGE_MAP() + +CArm::CArm() : CCarry(), _string6("Key"), + _field138(0), _field158(0), _field16C(3), _field170(0), + _armRect(220, 208, 409, 350) { +} + +void CArm::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string6, indent); + file->writeNumberLine(_field138, indent); + file->writeNumberLine(_hookedRect.left, indent); + file->writeNumberLine(_hookedRect.top, indent); + file->writeNumberLine(_hookedRect.right, indent); + file->writeNumberLine(_hookedRect.bottom, indent); + + file->writeQuotedLine(_string7, indent); + file->writeNumberLine(_field158, indent); + file->writeNumberLine(_armRect.left, indent); + file->writeNumberLine(_armRect.top, indent); + file->writeNumberLine(_armRect.right, indent); + file->writeNumberLine(_armRect.bottom, indent); + file->writeNumberLine(_field16C, indent); + file->writeNumberLine(_field170, indent); + + CCarry::save(file, indent); +} + +void CArm::load(SimpleFile *file) { + file->readNumber(); + _string6 = file->readString(); + _field138 = file->readNumber(); + _hookedRect.left = file->readNumber(); + _hookedRect.top = file->readNumber(); + _hookedRect.right = file->readNumber(); + _hookedRect.bottom = file->readNumber(); + + _string7 = file->readString(); + _field158 = file->readNumber(); + _armRect.left = file->readNumber(); + _armRect.top = file->readNumber(); + _armRect.right = file->readNumber(); + _armRect.bottom = file->readNumber(); + _field16C = file->readNumber(); + _field170 = file->readNumber(); + + CCarry::load(file); +} + +bool CArm::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _field138 = 0; + _fieldE0 = 1; + + CString name = getName(); + if (name == "Arm1") { + CActMsg actMsg("LoseArm"); + actMsg.execute("MaitreD"); + CPuzzleSolvedMsg solvedMsg; + solvedMsg.execute("AuditoryCentre"); + } else if (name == "Arm2") { + CPuzzleSolvedMsg solvedMsg; + solvedMsg.execute("Key"); + } + + return true; +} + +bool CArm::TranslateObjectMsg(CTranslateObjectMsg *msg) { + Point newPos(_bounds.left - msg->_delta.x, _bounds.top - msg->_delta.y); + setPosition(newPos); + return true; +} + +bool CArm::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (_string6 != "None") { + CShowTextMsg textMsg("The arm is already holding something."); + textMsg.execute("PET"); + return false; + } else if (msg->_other->getName() == "GondolierLeftLever") { + CIsHookedOnMsg hookedMsg(_hookedRect, 0, getName()); + hookedMsg._rect.translate(_bounds.left, _bounds.top); + hookedMsg.execute("GondolierLeftLever"); + + if (hookedMsg._result) { + _string7 = "GondolierLeftLever"; + } else { + petAddToInventory(); + } + } else if (msg->_other->getName() == "GondolierRightLever") { + CIsHookedOnMsg hookedMsg(_hookedRect, 0, getName()); + hookedMsg._rect.translate(_bounds.left, _bounds.top); + hookedMsg.execute("GondolierRightLever"); + + if (hookedMsg._result) { + _string7 = "GondolierRightLever"; + } else { + petAddToInventory(); + } + } + + return true; +} + +bool CArm::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!_fieldE0) { + CShowTextMsg textMsg("You can't get this."); + textMsg.execute("PET"); + } else if (checkStartDragging(msg)) { + _tempPos = msg->_mousePos - _bounds; + setPosition(msg->_mousePos - _tempPos); + + if (!_string7.empty()) { + CActMsg actMsg("Unhook"); + actMsg.execute(_string7); + _string7.clear(); + } + + loadFrame(_visibleFrame); + return true; + } + + return false; +} + +bool CArm::MaitreDHappyMsg(CMaitreDHappyMsg *msg) { + CGameObject *petItem; + if (find(getName(), &petItem, FIND_PET)) { + if (!_field158) + playSound("z#47.wav", 100, 0, 0); + if (_string6 == "Key" || _string6 == "AuditoryCentre") { + CGameObject *child = static_cast<CGameObject *>(getFirstChild()); + if (child) { + child->setVisible(true); + petAddToInventory(); + } + + _visibleFrame = _field170; + loadFrame(_visibleFrame); + _string6 = "None"; + petInvChange(); + } + } + + _field158 = 1; + _fieldE0 = 1; + return true; +} + +bool CArm::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + if (_field158) { + if (_string6 == "Key" || _string6 == "AuditoryCentre") { + CCarry *child = static_cast<CCarry *>(getFirstChild()); + if (child) { + _visibleFrame = _field170; + loadFrame(_visibleFrame); + child->setVisible(true); + child->petAddToInventory(); + } + + _string6 = "None"; + } + } + + return true; +} + +bool CArm::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + setPosition(msg->_mousePos - _tempPos); + + if (_string6 != "None" && compareViewNameTo("FrozenArboretum.Node 5.S")) { + loadFrame(_armRect.contains(msg->_mousePos) ? + _field16C : _visibleFrame); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/arm.h b/engines/titanic/carry/arm.h new file mode 100644 index 0000000000..fc8bba1f08 --- /dev/null +++ b/engines/titanic/carry/arm.h @@ -0,0 +1,68 @@ +/* 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_ARM_H +#define TITANIC_ARM_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CArm : public CCarry { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); + bool TranslateObjectMsg(CTranslateObjectMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MaitreDHappyMsg(CMaitreDHappyMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); +private: + CString _string6; + int _field138; + Rect _hookedRect; + CString _string7; + int _field158; + Rect _armRect; + int _field16C; + int _field170; +public: + CLASSDEF; + CArm(); + + /** + * 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_ARM_H */ diff --git a/engines/titanic/carry/auditory_centre.cpp b/engines/titanic/carry/auditory_centre.cpp new file mode 100644 index 0000000000..0bda975a36 --- /dev/null +++ b/engines/titanic/carry/auditory_centre.cpp @@ -0,0 +1,47 @@ +/* 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/carry/auditory_centre.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAuditoryCentre, CBrain) + ON_MESSAGE(PuzzleSolvedMsg) +END_MESSAGE_MAP() + +void CAuditoryCentre::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBrain::save(file, indent); +} + +void CAuditoryCentre::load(SimpleFile *file) { + file->readNumber(); + CBrain::load(file); +} + +bool CAuditoryCentre::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _fieldE0 = 1; + setVisible(true); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/auditory_centre.h b/engines/titanic/carry/auditory_centre.h new file mode 100644 index 0000000000..6f24e86208 --- /dev/null +++ b/engines/titanic/carry/auditory_centre.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_AUDITORY_CENTRE_H +#define TITANIC_AUDITORY_CENTRE_H + +#include "titanic/carry/brain.h" + +namespace Titanic { + +class CAuditoryCentre : public CBrain { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *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_AUDITORY_CENTRE_H */ diff --git a/engines/titanic/carry/bowl_ear.cpp b/engines/titanic/carry/bowl_ear.cpp new file mode 100644 index 0000000000..852a77899a --- /dev/null +++ b/engines/titanic/carry/bowl_ear.cpp @@ -0,0 +1,68 @@ +/* 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/carry/bowl_ear.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBowlEar, CEar) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(ReplaceBowlAndNutsMsg) + ON_MESSAGE(NutPuzzleMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CBowlEar::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CEar::save(file, indent); +} + +void CBowlEar::load(SimpleFile *file) { + file->readNumber(); + CEar::load(file); +} + +bool CBowlEar::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + CBowlStateChangeMsg changeMsg(3); + changeMsg.execute("ParrotNutBowlActor"); + + return CEar::PETGainedObjectMsg(msg); +} + +bool CBowlEar::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + setVisible(false); + return true; +} + +bool CBowlEar::NutPuzzleMsg(CNutPuzzleMsg *msg) { + if (msg->_value == "BowlUnlocked") + _fieldE0 = 1; + + return true; +} + +bool CBowlEar::MouseDragStartMsg(CMouseDragStartMsg *msg) { + setVisible(true); + return CEar::MouseDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/bowl_ear.h b/engines/titanic/carry/bowl_ear.h new file mode 100644 index 0000000000..d78092f6d7 --- /dev/null +++ b/engines/titanic/carry/bowl_ear.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_BOWL_EAR_H +#define TITANIC_BOWL_EAR_H + +#include "titanic/carry/ear.h" + +namespace Titanic { + +class CBowlEar : public CEar { + DECLARE_MESSAGE_MAP; + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg); + bool NutPuzzleMsg(CNutPuzzleMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *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_BOWL_EAR_H */ diff --git a/engines/titanic/carry/brain.cpp b/engines/titanic/carry/brain.cpp new file mode 100644 index 0000000000..8df0de9961 --- /dev/null +++ b/engines/titanic/carry/brain.cpp @@ -0,0 +1,134 @@ +/* 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/carry/brain.h" +#include "titanic/game/brain_slot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBrain, CCarry) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(PassOnDragStartMsg) + ON_MESSAGE(PETGainedObjectMsg) +END_MESSAGE_MAP() + +CBrain::CBrain() : CCarry(), _field134(0), _field138(0) { +} + +void CBrain::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_pos1, indent); + file->writeNumberLine(_field134, indent); + file->writeNumberLine(_field138, indent); + + CCarry::save(file, indent); +} + +void CBrain::load(SimpleFile *file) { + file->readNumber(); + _pos1 = file->readPoint(); + _field134 = file->readNumber(); + _field138 = file->readNumber(); + + CCarry::load(file); +} + +bool CBrain::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CBrainSlot *slot = static_cast<CBrainSlot *>(msg->_other); + if (slot) { + if (slot->getName() == "CentralCore") { + setVisible(false); + petMoveToHiddenRoom(); + CAddHeadPieceMsg headpieceMsg(getName()); + headpieceMsg.execute("CentralCoreSlot"); + } + else if (!slot->_value1 && slot->getName() == "CentralCoreSlot") { + setVisible(false); + petMoveToHiddenRoom(); + CAddHeadPieceMsg headpieceMsg(getName()); + headpieceMsg.execute(msg->_other); + playSound("z#116.wav", 100, 0, 0); + setPosition(Point(0, 0)); + setVisible(false); + _field134 = 1; + } + + return true; + } + else { + return CCarry::UseWithOtherMsg(msg); + } +} + +bool CBrain::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +bool CBrain::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) + return false; + + if (_field134) { + CTakeHeadPieceMsg headpieceMsg(getName()); + headpieceMsg.execute("TitaniaControl"); + + _field134 = 0; + setVisible(true); + moveToView(); + + setPosition(Point(msg->_mousePos.x - _bounds.width() / 2, + msg->_mousePos.y - _bounds.height() / 2)); + } + + return CCarry::MouseDragStartMsg(msg); +} + +bool CBrain::PassOnDragStartMsg(CPassOnDragStartMsg *msg) { + if (_field134) { + CTakeHeadPieceMsg headpieceMsg(getName()); + headpieceMsg.execute("TitaniaControl"); + _field134 = 0; + + setVisible(true); + moveToView(); + setPosition(Point(msg->_mousePos.x - _bounds.width() / 2, + msg->_mousePos.y - _bounds.height() / 2)); + } + + return CCarry::PassOnDragStartMsg(msg); +} + +bool CBrain::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + if (!_field138) { + if (getName() == "Perch") { + stateInc38(); + _field138 = 1; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/brain.h b/engines/titanic/carry/brain.h new file mode 100644 index 0000000000..bcba161e27 --- /dev/null +++ b/engines/titanic/carry/brain.h @@ -0,0 +1,61 @@ +/* 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_BRAIN_H +#define TITANIC_BRAIN_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CBrain : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool PassOnDragStartMsg(CPassOnDragStartMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); +private: + Point _pos1; + int _field134; + int _field138; +public: + CLASSDEF; + CBrain(); + + /** + * 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_BRAIN_H */ diff --git a/engines/titanic/carry/bridge_piece.cpp b/engines/titanic/carry/bridge_piece.cpp new file mode 100644 index 0000000000..fc845feff0 --- /dev/null +++ b/engines/titanic/carry/bridge_piece.cpp @@ -0,0 +1,95 @@ +/* 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/carry/bridge_piece.h" +#include "titanic/game/ship_setting.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBridgePiece, CCarry) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(PassOnDragStartMsg) +END_MESSAGE_MAP() + +CBridgePiece::CBridgePiece() : CCarry(), _field140(0) { +} + +void CBridgePiece::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string6, indent); + file->writePoint(_pos3, indent); + file->writeNumberLine(_field140, indent); + + CCarry::save(file, indent); +} + +void CBridgePiece::load(SimpleFile *file) { + file->readNumber(); + _string6 = file->readString(); + _pos3 = file->readPoint(); + _field140 = file->readNumber(); + + CCarry::load(file); +} + +bool CBridgePiece::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CShipSetting *shipSetting = static_cast<CShipSetting *>(msg->_other); + if (!shipSetting) { + return CCarry::UseWithOtherMsg(msg); + } else if (shipSetting->_string4 == "NULL") { + petAddToInventory(); + return true; + } else { + setVisible(false); + playSound("z#54.wav", 100, 0, 0); + setPosition(shipSetting->_pos1); + shipSetting->_string4 = getName(); + petMoveToHiddenRoom(); + + CAddHeadPieceMsg headpieceMsg(shipSetting->getName() == _string6 ? + "Enable" : "Disable"); + CSetFrameMsg frameMsg; + + CString name = getName(); + if (name == "ChickenBridge") { + frameMsg._frameNumber = 1; + } else if (name == "FanBridge") { + frameMsg._frameNumber = 2; + } else if (name == "SeasonBridge") { + frameMsg._frameNumber = 3; + } else if (name == "BeamBridge") { + frameMsg._frameNumber = 0; + } + + frameMsg.execute(shipSetting); + headpieceMsg.execute(shipSetting); + return true; + } +} + +bool CBridgePiece::PassOnDragStartMsg(CPassOnDragStartMsg *msg) { + setVisible(true); + moveToView(); + return CCarry::PassOnDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/bridge_piece.h b/engines/titanic/carry/bridge_piece.h new file mode 100644 index 0000000000..80a1cc98a8 --- /dev/null +++ b/engines/titanic/carry/bridge_piece.h @@ -0,0 +1,55 @@ +/* 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_BRIDGE_PIECE_H +#define TITANIC_BRIDGE_PIECE_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CBridgePiece : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool PassOnDragStartMsg(CPassOnDragStartMsg *msg); +private: + CString _string6; + Point _pos3; + int _field140; +public: + CLASSDEF; + CBridgePiece(); + + /** + * 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_BRIDGE_PIECE_H */ diff --git a/engines/titanic/carry/carry.cpp b/engines/titanic/carry/carry.cpp new file mode 100644 index 0000000000..75b3b6f35b --- /dev/null +++ b/engines/titanic/carry/carry.cpp @@ -0,0 +1,241 @@ +/* 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/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/npcs/character.h" +#include "titanic/npcs/succubus.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCarry, CGameObject) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseDragMoveMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(RemoveFromGameMsg) + ON_MESSAGE(MoveToStartPosMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(PassOnDragStartMsg) +END_MESSAGE_MAP() + +CCarry::CCarry() : CGameObject(), _fieldDC(0), _fieldE0(1), + _field100(0), _field104(0), _field108(0), _field10C(0), + _itemFrame(0), _enterFrame(0), _enterFrameSet(false), _visibleFrame(0), + _string1("None"), + _fullViewName("NULL"), + _string3("That doesn't seem to do anything."), + _string4("It doesn't seem to want this.") { +} + +void CCarry::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string1, indent); + file->writePoint(_origPos, indent); + file->writeQuotedLine(_fullViewName, indent); + file->writeNumberLine(_fieldDC, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeQuotedLine(_string3, indent); + file->writeQuotedLine(_string4, indent); + file->writePoint(_tempPos, indent); + file->writeNumberLine(_field104, indent); + file->writeNumberLine(_field108, indent); + file->writeNumberLine(_field10C, indent); + file->writeNumberLine(_itemFrame, indent); + file->writeQuotedLine(_string5, indent); + file->writeNumberLine(_enterFrame, indent); + file->writeNumberLine(_enterFrameSet, indent); + file->writeNumberLine(_visibleFrame, indent); + + CGameObject::save(file, indent); +} + +void CCarry::load(SimpleFile *file) { + file->readNumber(); + _string1 = file->readString(); + _origPos = file->readPoint(); + _fullViewName = file->readString(); + _fieldDC = file->readNumber(); + _fieldE0 = file->readNumber(); + _string3 = file->readString(); + _string4 = file->readString(); + _tempPos = file->readPoint(); + _field104 = file->readNumber(); + _field108 = file->readNumber(); + _field10C = file->readNumber(); + _itemFrame = file->readNumber(); + _string5 = file->readString(); + _enterFrame = file->readNumber(); + _enterFrameSet = file->readNumber(); + _visibleFrame = file->readNumber(); + + CGameObject::load(file); +} + +bool CCarry::MouseDragStartMsg(CMouseDragStartMsg *msg) { + CString name = getName(); + + if (_fieldE0) { + if (_visible) { + CShowTextMsg textMsg("You can't get this."); + textMsg.execute("PET"); + } + } else { + if (checkStartDragging(msg)) { + CPassOnDragStartMsg startMsg(msg->_mousePos); + startMsg.execute(this); + return true; + } + } + + return false; +} + +bool CCarry::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + setPosition(msg->_mousePos - _tempPos); + return true; +} + +bool CCarry::MouseDragEndMsg(CMouseDragEndMsg *msg) { + if (msg->_dropTarget) { + if (msg->_dropTarget->isPet()) { + petAddToInventory(); + return true; + } + + CCharacter *npc = static_cast<CCharacter *>(msg->_dropTarget); + if (npc) { + CUseWithCharMsg charMsg(npc); + charMsg.execute(this, nullptr, 0); + return true; + } + + CDropObjectMsg dropMsg(this); + if (dropMsg.execute(msg->_dropTarget)) + return true; + + // Fall back on a use with other message + CUseWithOtherMsg otherMsg(msg->_dropTarget); + if (otherMsg.execute(this, nullptr, 0)) + return true; + } + + CString viewName = getViewFullName(); + if (viewName.empty() || msg->_mousePos.y >= 360) { + sleep(250); + petAddToInventory(); + } else { + setPosition(_origPos); + loadFrame(_itemFrame); + } + + return true; +} + +bool CCarry::UseWithCharMsg(CUseWithCharMsg *msg) { + CSuccUBus *succubus = static_cast<CSuccUBus *>(msg->_character); + if (succubus) { + CSubAcceptCCarryMsg carryMsg; + carryMsg._item = this; + carryMsg.execute(succubus); + } else { + CShowTextMsg textMsg(_string4); + textMsg.execute("PET"); + petAddToInventory(); + } + + return true; +} + +bool CCarry::LeaveViewMsg(CLeaveViewMsg *msg) { + return true; +} + +bool CCarry::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CShowTextMsg textMsg(_string3); + textMsg.execute("PET"); + + _fullViewName = getViewFullName(); + if (_fullViewName.empty() || _bounds.top >= 360) { + sleep(250); + petAddToInventory(); + } else { + setPosition(_origPos); + } + + return true; +} + +bool CCarry::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + if (msg->_visible && _visibleFrame != -1) + loadFrame(_visibleFrame); + + return true; +} + +bool CCarry::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CCarry::RemoveFromGameMsg(CRemoveFromGameMsg *msg) { + setPosition(Point(0, 0)); + setVisible(false); + + return true; +} + +bool CCarry::MoveToStartPosMsg(CMoveToStartPosMsg *msg) { + setPosition(_origPos); + return true; +} + +bool CCarry::EnterViewMsg(CEnterViewMsg *msg) { + if (!_enterFrameSet) { + loadFrame(_enterFrame); + _enterFrameSet = true; + } + + return true; +} + +bool CCarry::PassOnDragStartMsg(CPassOnDragStartMsg *msg) { + if (_visibleFrame != -1) + loadFrame(_visibleFrame); + + if (msg->_value3) { + _tempPos.x = _bounds.width() / 2; + _tempPos.y = _bounds.height() / 2; + } else { + _tempPos = msg->_mousePos - _bounds; + } + + setPosition(_tempPos - getMousePos()); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/carry.h b/engines/titanic/carry/carry.h new file mode 100644 index 0000000000..fb5519e290 --- /dev/null +++ b/engines/titanic/carry/carry.h @@ -0,0 +1,82 @@ +/* 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_CARRY_H +#define TITANIC_CARRY_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CCarry : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool RemoveFromGameMsg(CRemoveFromGameMsg *msg); + bool MoveToStartPosMsg(CMoveToStartPosMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool PassOnDragStartMsg(CPassOnDragStartMsg *msg); +protected: + CString _string1; + int _fieldDC; + CString _string3; + CString _string4; + Point _tempPos; + int _field100; + int _field104; + int _field108; + int _field10C; + int _itemFrame; + CString _string5; + int _enterFrame; + bool _enterFrameSet; + int _visibleFrame; +public: + int _fieldE0; + Point _origPos; + CString _fullViewName; +public: + CLASSDEF; + CCarry(); + + /** + * 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_CARRY_H */ diff --git a/engines/titanic/carry/carry_parrot.cpp b/engines/titanic/carry/carry_parrot.cpp new file mode 100644 index 0000000000..8a453e348c --- /dev/null +++ b/engines/titanic/carry/carry_parrot.cpp @@ -0,0 +1,237 @@ +/* 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/carry/carry_parrot.h" +#include "titanic/core/project_item.h" +#include "titanic/core/room_item.h" +#include "titanic/game/cage.h" +#include "titanic/npcs/parrot.h" +#include "titanic/npcs/succubus.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCarryParrot, CCarry) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(IsParrotPresentMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(PassOnDragStartMsg) + ON_MESSAGE(PreEnterViewMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +CCarryParrot::CCarryParrot() : CCarry(), _string6("PerchedParrot"), + _timerId(0), _field13C(0), _field140(false), _field144(10), + _field148(25), _field14C(0), _field150(8) { +} + +void CCarryParrot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string6, indent); + file->writeNumberLine(_timerId, indent); + file->writeNumberLine(_field13C, indent); + file->writeNumberLine(_field140, indent); + + CCarry::save(file, indent); +} + +void CCarryParrot::load(SimpleFile *file) { + file->readNumber(); + _string6 = file->readString(); + _timerId = file->readNumber(); + _field13C = file->readNumber(); + _field140 = file->readNumber(); + + CCarry::load(file); +} + +bool CCarryParrot::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + CParrot::_v4 = 4; + CActMsg actMsg("Shut"); + actMsg.execute("ParrotCage"); + + return true; +} + +bool CCarryParrot::TimerMsg(CTimerMsg *msg) { + if (CParrot::_v4 == 1 || CParrot::_v4 == 4) { + if (++_field13C >= 30) { + CActMsg actMsg("FreeParrot"); + actMsg.execute(this); + } + } + + return true; +} + +bool CCarryParrot::IsParrotPresentMsg(CIsParrotPresentMsg *msg) { + msg->_value = true; + return true; +} + +bool CCarryParrot::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_visible) { + setVisible(false); + _fieldE0 = 0; + CParrot::_v4 = 2; + } + + return true; +} + +bool CCarryParrot::MouseDragEndMsg(CMouseDragEndMsg *msg) { + stopMovie(); + + if (msg->_mousePos.y >= 360) { + petAddToInventory(); + return true; + } + + if (compareViewNameTo("ParrotLobby.Node 1.N")) { + if (msg->_mousePos.x >= 75 && msg->_mousePos.x <= 565 && + !CParrot::_v2 && !CCage::_open) { + setVisible(false); + _fieldE0 = 0; + CTreeItem *perchedParrot = findUnder(getRoot(), "PerchedParrot"); + detach(); + addUnder(perchedParrot); + sound8(true); + + CPutParrotBackMsg backMsg(msg->_mousePos.x); + backMsg.execute(perchedParrot); + } else { + setVisible(false); + _fieldE0 = 0; + CParrot::_v4 = 2; + playSound("z#475.wav", 100, 0, 0); + sound8(true); + moveUnder(findRoom()); + + CActMsg actMsg("Shut"); + actMsg.execute("ParrotCage"); + } + } else { + CCharacter *character = static_cast<CCharacter *>(msg->_dropTarget); + if (character) { + CUseWithCharMsg charMsg(character); + charMsg.execute(this, nullptr, 0); + } else { + setVisible(false); + _fieldE0 = 0; + playSound("z#475.wav", 100, 0, 0); + sound8(true); + moveUnder(findRoom()); + } + } + + return true; +} + +bool CCarryParrot::PassOnDragStartMsg(CPassOnDragStartMsg *msg) { + if (CParrot::_v4 != 3) { + moveToView(); + setPosition(Point(0, 0)); + setVisible(true); + playClip("Pick Up", 2); + playClip("Flapping", 1); + + stopTimer(_timerId); + _timerId = addTimer(1000, 1000); + + _field13C = 0; + CParrot::_v4 = 1; + msg->_value3 = 1; + + return CCarry::PassOnDragStartMsg(msg); + } + + CTrueTalkNPC *npc = static_cast<CTrueTalkNPC *>(getRoot()->findByName(_string6)); + if (npc) + startTalking(npc, 0x446BF); + + _fieldE0 = 0; + playSound("z#475.wav", 100, 0, 0); + moveUnder(findRoom()); + msg->_value4 = 1; + + return true; +} + +bool CCarryParrot::PreEnterViewMsg(CPreEnterViewMsg *msg) { + loadSurface(); + CCarryParrot *parrot = static_cast<CCarryParrot *>(getRoot()->findByName("CarryParrot")); + if (parrot) + parrot->_fieldE0 = 0; + + return true; +} + +bool CCarryParrot::UseWithCharMsg(CUseWithCharMsg *msg) { + CSuccUBus *succubus = static_cast<CSuccUBus *>(msg->_character); + if (succubus) + CParrot::_v4 = 3; + + return CCarry::UseWithCharMsg(msg); +} + +bool CCarryParrot::ActMsg(CActMsg *msg) { + if (msg->_action == "FreeParrot" && (CParrot::_v4 == 4 || CParrot::_v4 == 1)) { + CTrueTalkNPC *npc = static_cast<CTrueTalkNPC *>(getRoot()->findByName(_string6)); + if (npc) + startTalking(npc, 0x446BF); + + setVisible(false); + _fieldE0 = 0; + + if (CParrot::_v4 == 4) { + CActMsg actMsg("Shut"); + actMsg.execute("ParrotCage"); + } else { + playSound("z#475.wav", 100, 0, 0); + + if (!_field140) { + CCarry *feathers = static_cast<CCarry *>(getRoot()->findByName("Feathers")); + if (feathers) { + feathers->setVisible(true); + feathers->petAddToInventory(); + } + + _field140 = true; + } + + getPetControl()->removeFromInventory(this); + getPetControl()->setAreaChangeType(1); + moveUnder(getRoom()); + } + + CParrot::_v4 = 2; + stopTimer(_timerId); + _timerId = 0; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/carry_parrot.h b/engines/titanic/carry/carry_parrot.h new file mode 100644 index 0000000000..2980f26d8a --- /dev/null +++ b/engines/titanic/carry/carry_parrot.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_CARRY_PARROT_H +#define TITANIC_CARRY_PARROT_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CCarryParrot : public CCarry { + DECLARE_MESSAGE_MAP; + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool IsParrotPresentMsg(CIsParrotPresentMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool PassOnDragStartMsg(CPassOnDragStartMsg *msg); + bool PreEnterViewMsg(CPreEnterViewMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool ActMsg(CActMsg *msg); +private: + CString _string6; + int _timerId; + int _field13C; + bool _field140; + int _field144; + int _field148; + int _field14C; + int _field150; +public: + CLASSDEF; + CCarryParrot(); + + /** + * 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_CARRY_PARROT_H */ diff --git a/engines/titanic/carry/central_core.cpp b/engines/titanic/carry/central_core.cpp new file mode 100644 index 0000000000..e210b34cbe --- /dev/null +++ b/engines/titanic/carry/central_core.cpp @@ -0,0 +1,93 @@ +/* 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/carry/central_core.h" +#include "titanic/npcs/parrot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCentralCore, CBrain) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(DropZoneLostObjectMsg) + ON_MESSAGE(DropZoneGotObjectMsg) +END_MESSAGE_MAP() + +void CCentralCore::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBrain::save(file, indent); +} + +void CCentralCore::load(SimpleFile *file) { + file->readNumber(); + CBrain::load(file); +} + +bool CCentralCore::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CString name = msg->_other->getName(); + if (name == "HammerDispensorButton") { + CPuzzleSolvedMsg solvedMsg; + solvedMsg.execute("BigHammer"); + } else if (name == "SpeechCentre") { + CShowTextMsg textMsg("This does not reach."); + textMsg.execute("PET"); + } + + return CBrain::UseWithOtherMsg(msg); +} + +bool CCentralCore::DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg) { + CString name = msg->_object->getName(); + if (name == "PerchCoreHolder") { + CParrot::_v2 = 1; + if (isEquals("CentralCore")) + CParrot::_v5 = 0; + + CActMsg actMsg("LosePerch"); + actMsg.execute("ParrotLobbyController"); + } else if (name == "PerchHolder") { + CActMsg actMsg("LoseStick"); + actMsg.execute("ParrotLobbyController"); + } + + return true; +} + +bool CCentralCore::DropZoneGotObjectMsg(CDropZoneGotObjectMsg *msg) { + CString name = msg->_object->getName(); + if (name == "PerchCoreHolder") { + if (isEquals("CentralCore")) { + CParrot::_v5 = 1; + CActMsg actMsg("CoreReplaced"); + actMsg.execute("ParrotCage"); + } + + CActMsg actMsg("GainPerch"); + actMsg.execute("ParrotLobbyController"); + } else if (name == "PerchHolder") { + CActMsg actMsg("GainStick"); + actMsg.execute("ParrotLobbyController"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/central_core.h b/engines/titanic/carry/central_core.h new file mode 100644 index 0000000000..cc5d9c2f95 --- /dev/null +++ b/engines/titanic/carry/central_core.h @@ -0,0 +1,51 @@ +/* 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_CENTRAL_CORE_H +#define TITANIC_CENTRAL_CORE_H + +#include "titanic/carry/brain.h" + +namespace Titanic { + +class CCentralCore : public CBrain { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg); + bool DropZoneGotObjectMsg(CDropZoneGotObjectMsg *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_CENTRAL_CORE_H */ diff --git a/engines/titanic/carry/chicken.cpp b/engines/titanic/carry/chicken.cpp new file mode 100644 index 0000000000..65404dc65d --- /dev/null +++ b/engines/titanic/carry/chicken.cpp @@ -0,0 +1,225 @@ +/* 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/carry/chicken.h" +#include "titanic/game/sauce_dispensor.h" +#include "titanic/npcs/succubus.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChicken, CCarry) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(ParrotTriesChickenMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(PETObjectStateMsg) + ON_MESSAGE(PETLostObjectMsg) +END_MESSAGE_MAP() + +int CChicken::_v1; + +CChicken::CChicken() : CCarry(), _string6("None"), + _field12C(1), _field13C(0), _timerId(0) { +} + +void CChicken::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field12C, indent); + file->writeQuotedLine(_string6, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_field13C, indent); + file->writeNumberLine(_timerId, indent); + + CCarry::save(file, indent); +} + +void CChicken::load(SimpleFile *file) { + file->readNumber(); + _field12C = file->readNumber(); + _string6 = file->readString(); + _v1 = file->readNumber(); + _field13C = file->readNumber(); + _timerId = file->readNumber(); + + CCarry::load(file); +} + +bool CChicken::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (msg->_other->getName() == "Napkin") { + if (_field12C || _string6 == "None") { + CActMsg actMsg("Clean"); + actMsg.execute(this); + petAddToInventory(); + } else { + CShowTextMsg textMsg("The chicken is already clean."); + textMsg.execute("PET"); + } + + petAddToInventory(); + } else { + CSauceDispensor *dispensor = static_cast<CSauceDispensor *>(msg->_other); + if (!dispensor || _string6 == "None") { + return CCarry::UseWithOtherMsg(msg); + } else { + setVisible(false); + CUse use(this); + use.execute(msg->_other); + } + } + + return true; +} + +bool CChicken::UseWithCharMsg(CUseWithCharMsg *msg) { + CSuccUBus *succubus = static_cast<CSuccUBus *>(msg->_character); + if (succubus) { + setPosition(Point(330, 300)); + CSubAcceptCCarryMsg acceptMsg; + acceptMsg._item = this; + acceptMsg.execute(succubus); + } else { + petAddToInventory(); + } + + return true; +} + +bool CChicken::ActMsg(CActMsg *msg) { + if (msg->_action == "GoToPET") { + setVisible(true); + petAddToInventory(); + } else if (msg->_action == "Tomato") { + _string6 = "Tomato"; + loadFrame(4); + _visibleFrame = 4; + } else if (msg->_action == "Mustard") { + _string6 = "Mustard"; + loadFrame(5); + _visibleFrame = 5; + } else if (msg->_action == "Bird") { + _string6 = "Bird"; + loadFrame(2); + _visibleFrame = 2; + } else if (msg->_action == "None") { + setVisible(false); + } else if (msg->_action == "Clean") { + _string6 = "None"; + loadFrame(3); + _field12C = 0; + _visibleFrame = 3; + } + else if (msg->_action == "Dispense Chicken") { + _string6 = "None"; + _field13C = 0; + _field12C = 1; + loadFrame(1); + _visibleFrame = 1; + _v1 = 120; + } else if (msg->_action == "Hot") { + _v1 = 120; + } else if (msg->_action == "Eaten") { + setVisible(false); + petMoveToHiddenRoom(); + _field13C = 1; + } + + return true; +} + +bool CChicken::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + if (msg->_visible) + loadFrame(_visibleFrame); + + return true; +} + +bool CChicken::TimerMsg(CTimerMsg *msg) { + CGameObject *obj = getMailManFirstObject(); + while (obj && obj->getName() != "Chicken") + obj = getMailManNextObject(obj); + + bool flag = false; + if (obj) { + flag = _v1; + } else if (_v1 > 0) { + --_v1; + flag = _v1; + } + + if (flag) { + petInvChange(); + stopTimer(_timerId); + } + + return true; +} + +bool CChicken::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + stopTimer(_timerId); + _timerId = addTimer(1000, 1000); + return true; +} + +bool CChicken::ParrotTriesChickenMsg(CParrotTriesChickenMsg *msg) { + if (_v1 > 0) + msg->_value1 = 1; + + if (_string6 == "Tomato") { + msg->_value2 = 1; + } else if (_string6 == "Mustard") { + msg->_value2 = 2; + } else if (_string6 == "Bird") { + msg->_value2 = 3; + } + + return true; +} + +bool CChicken::MouseDragEndMsg(CMouseDragEndMsg *msg) { + if (_field13C) + return true; + else + return CCarry::MouseDragEndMsg(msg); +} + +bool CChicken::PETObjectStateMsg(CPETObjectStateMsg *msg) { + if (_v1 > 0) + msg->_value = 2; + + return true; +} + +bool CChicken::PETLostObjectMsg(CPETLostObjectMsg *msg) { + if (compareViewNameTo("ParrotLobby.Node 1.N")) { + CActMsg actMsg("StartChickenDrag"); + actMsg.execute("PerchedParrot"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/chicken.h b/engines/titanic/carry/chicken.h new file mode 100644 index 0000000000..e64ae458a4 --- /dev/null +++ b/engines/titanic/carry/chicken.h @@ -0,0 +1,68 @@ +/* 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_CHICKEN_H +#define TITANIC_CHICKEN_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CChicken : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool ActMsg(CActMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool ParrotTriesChickenMsg(CParrotTriesChickenMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool PETObjectStateMsg(CPETObjectStateMsg *msg); + bool PETLostObjectMsg(CPETLostObjectMsg *msg); +public: + static int _v1; +public: + int _field12C; + CString _string6; + int _field13C; + int _timerId; +public: + CLASSDEF; + CChicken(); + + /** + * 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_CHICKEN_H */ diff --git a/engines/titanic/carry/crushed_tv.cpp b/engines/titanic/carry/crushed_tv.cpp new file mode 100644 index 0000000000..486537d28e --- /dev/null +++ b/engines/titanic/carry/crushed_tv.cpp @@ -0,0 +1,79 @@ +/* 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/carry/crushed_tv.h" +#include "titanic/npcs/character.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCrushedTV, CCarry) + ON_MESSAGE(ActMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +CCrushedTV::CCrushedTV() : CCarry() { +} + +void CCrushedTV::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CCrushedTV::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CCrushedTV::ActMsg(CActMsg *msg) { + if (msg->_action == "SmashTV") { + setVisible(true); + _fieldE0 = 1; + } + + return true; +} + +bool CCrushedTV::UseWithCharMsg(CUseWithCharMsg *msg) { + if (msg->_character->getName() == "Barbot" && msg->_character->_visible) { + setVisible(false); + CActMsg actMsg("CrushedTV"); + actMsg.execute(msg->_character); + return true; + } else { + return CCarry::UseWithCharMsg(msg); + } +} + +bool CCrushedTV::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) { + return false; + } else if (compareViewNameTo("BottomOfWell.Node 7.N")) { + changeView("BottomOfWell.Node 12.N", ""); + CActMsg actMsg("TelevisionTaken"); + actMsg.execute("BOWTelevisionMonitor"); + } + + return CCarry::MouseDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/crushed_tv.h b/engines/titanic/carry/crushed_tv.h new file mode 100644 index 0000000000..340930f842 --- /dev/null +++ b/engines/titanic/carry/crushed_tv.h @@ -0,0 +1,54 @@ +/* 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_CRUSHED_TV_H +#define TITANIC_CRUSHED_TV_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CCrushedTV : public CCarry { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +public: + CLASSDEF; + CCrushedTV(); + + /** + * 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_CRUSHED_TV_H */ diff --git a/engines/titanic/carry/ear.cpp b/engines/titanic/carry/ear.cpp new file mode 100644 index 0000000000..a2234bc6dc --- /dev/null +++ b/engines/titanic/carry/ear.cpp @@ -0,0 +1,67 @@ +/* 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/carry/ear.h" +#include "titanic/game/head_slot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEar, CHeadPiece) + ON_MESSAGE(ActMsg) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CEar::CEar() : CHeadPiece() { +} + +void CEar::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CHeadPiece::save(file, indent); +} + +void CEar::load(SimpleFile *file) { + file->readNumber(); + CHeadPiece::load(file); +} + +bool CEar::ActMsg(CActMsg *msg) { + if (msg->_action == "MusicSolved") + _fieldE0 = true; + return true; +} + +bool CEar::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CHeadSlot *slot = dynamic_cast<CHeadSlot *>(msg->_other); + if (slot) { + setVisible(false); + petMoveToHiddenRoom(); + setPosition(Point(0, 0)); + + CAddHeadPieceMsg addMsg(getName()); + if (addMsg._value != "NULL") + addMsg.execute(addMsg._value == "Ear1" ? "Ear1Slot" : "Ear2Slot"); + } + + return CCarry::UseWithOtherMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/ear.h b/engines/titanic/carry/ear.h new file mode 100644 index 0000000000..a357f46bbf --- /dev/null +++ b/engines/titanic/carry/ear.h @@ -0,0 +1,51 @@ +/* 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_EAR_H +#define TITANIC_EAR_H + +#include "titanic/carry/head_piece.h" + +namespace Titanic { + +class CEar : public CHeadPiece { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +public: + CLASSDEF; + CEar(); + + /** + * 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_EAR_H */ diff --git a/engines/titanic/carry/eye.cpp b/engines/titanic/carry/eye.cpp new file mode 100644 index 0000000000..400df2fdc8 --- /dev/null +++ b/engines/titanic/carry/eye.cpp @@ -0,0 +1,139 @@ +/* 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/carry/eye.h" +#include "titanic/game/head_slot.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/game/transport/lift.h" +#include "titanic/game/television.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEye, CHeadPiece) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(PassOnDragStartMsg) +END_MESSAGE_MAP() + +CEye::CEye() : CHeadPiece(), _eyeFlag(false) { +} + +void CEye::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_eyeFlag, indent); + CHeadPiece::save(file, indent); +} + +void CEye::load(SimpleFile *file) { + file->readNumber(); + _eyeFlag = file->readNumber(); + CHeadPiece::load(file); +} + + +bool CEye::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CHeadSlot *slot = dynamic_cast<CHeadSlot *>(msg->_other); + if (slot) { + petMoveToHiddenRoom(); + _flag = true; + CAddHeadPieceMsg headMsg(getName()); + + if (headMsg._value != "NULL") + headMsg.execute(isEquals("Eye1") ? "Eye1Slot" : "Eye2Slot"); + } else if (msg->_other->isEquals("LiftbotWithoutHead")) { + CPetControl *pet = getPetControl(); + if (!CLift::_v1 && pet->getRoomsElevatorNum() == 4) { + _eyeFlag = true; + setPosition(_origPos); + setVisible(false); + CActMsg actMsg1(getName()); + actMsg1.execute("GetLiftEye"); + + CActMsg actMsg2("AddWrongHead"); + actMsg2.execute("FaultyLiftbot"); + } + } else { + return CCarry::UseWithOtherMsg(msg); + } + + return true; +} + +bool CEye::UseWithCharMsg(CUseWithCharMsg *msg) { + CLift *lift = dynamic_cast<CLift *>(msg->_character); + if (lift && lift->getName() == "Well") { + CPetControl *pet = getPetControl(); + if (!CLift::_v1 && pet->getRoomsElevatorNum() == 4) { + _eyeFlag = true; + setPosition(_origPos); + setVisible(false); + + CActMsg actMsg1(getName()); + actMsg1.execute("GetLiftEye"); + CActMsg actMsg2("AddWrongHead"); + actMsg2.execute(msg->_character); + } + + return true; + } else { + return CHeadPiece::UseWithCharMsg(msg); + } +} + +bool CEye::ActMsg(CActMsg *msg) { + if (msg->_action == "BellbotGetLight") { + setVisible(true); + petAddToInventory(); + playSound("z#47.wav"); + + CActMsg actMsg("Eye Removed"); + actMsg.execute("1stClassState"); + } else { + _eyeFlag = false; + + CActMsg actMsg("LoseHead"); + actMsg.execute("FaultyLiftbot"); + } + + return true; +} + +bool CEye::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + if (isEquals("Eye1")) + CTelevision::_v5 = 0; + + return CHeadPiece::PETGainedObjectMsg(msg); +} + +bool CEye::PassOnDragStartMsg(CPassOnDragStartMsg *msg) { + setVisible(true); + if (_eyeFlag) + CTelevision::_v6 = 0; + else if (isEquals("Eye1")) + CTelevision::_v5 = 0; + + return CHeadPiece::PassOnDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/eye.h b/engines/titanic/carry/eye.h new file mode 100644 index 0000000000..886bd39b84 --- /dev/null +++ b/engines/titanic/carry/eye.h @@ -0,0 +1,56 @@ +/* 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_EYE_H +#define TITANIC_EYE_H + +#include "titanic/carry/head_piece.h" + +namespace Titanic { + +class CEye : public CHeadPiece { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool ActMsg(CActMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool PassOnDragStartMsg(CPassOnDragStartMsg *msg); +private: + bool _eyeFlag; +public: + CLASSDEF; + CEye(); + + /** + * 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_EYE_H */ diff --git a/engines/titanic/carry/feathers.cpp b/engines/titanic/carry/feathers.cpp new file mode 100644 index 0000000000..a5d2babfb1 --- /dev/null +++ b/engines/titanic/carry/feathers.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/carry/feathers.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CFeathers, CCarry); + +CFeathers::CFeathers() : CCarry() { +} + +void CFeathers::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CFeathers::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/feathers.h b/engines/titanic/carry/feathers.h new file mode 100644 index 0000000000..7282bcb580 --- /dev/null +++ b/engines/titanic/carry/feathers.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_FEATHERS_H +#define TITANIC_FEATHERS_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CFeathers : public CCarry { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CFeathers(); + + /** + * 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_FEATHERS_H */ diff --git a/engines/titanic/carry/fruit.cpp b/engines/titanic/carry/fruit.cpp new file mode 100644 index 0000000000..68f3af7229 --- /dev/null +++ b/engines/titanic/carry/fruit.cpp @@ -0,0 +1,98 @@ +/* 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/carry/fruit.h" +#include "titanic/npcs/character.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFruit, CCarry) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(LemonFallsFromTreeMsg) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +CFruit::CFruit() : CCarry(), _field12C(0), + _field130(0), _field134(0), _field138(0) { +} + +void CFruit::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_field130, indent); + file->writeNumberLine(_field134, indent); + file->writeNumberLine(_field138, indent); + + CCarry::save(file, indent); +} + +void CFruit::load(SimpleFile *file) { + file->readNumber(); + _field12C = file->readNumber(); + _field130 = file->readNumber(); + _field134 = file->readNumber(); + _field138 = file->readNumber(); + + CCarry::load(file); +} + +bool CFruit::UseWithCharMsg(CUseWithCharMsg *msg) { + if (msg->_character->isEquals("Barbot") && msg->_character->_visible) { + CActMsg actMsg("Fruit"); + actMsg.execute(msg->_character); + _fieldE0 = 0; + setVisible(false); + return true; + } else { + return CCarry::UseWithCharMsg(msg); + } +} + +bool CFruit::LemonFallsFromTreeMsg(CLemonFallsFromTreeMsg *msg) { + setVisible(true); + dragMove(msg->_pt); + _field130 = 1; + return true; +} + +bool CFruit::UseWithOtherMsg(CUseWithOtherMsg *msg) { + petAddToInventory(); + return true; +} + +bool CFruit::FrameMsg(CFrameMsg *msg) { + if (_field130) { + if (_bounds.top > 240) { + _field130 = 0; + _field134 = 1; + } + + makeDirty(); + _bounds.top += 3; + makeDirty(); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/fruit.h b/engines/titanic/carry/fruit.h new file mode 100644 index 0000000000..bcbd314de8 --- /dev/null +++ b/engines/titanic/carry/fruit.h @@ -0,0 +1,58 @@ +/* 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_FRUIT_H +#define TITANIC_FRUIT_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CFruit : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool LemonFallsFromTreeMsg(CLemonFallsFromTreeMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool FrameMsg(CFrameMsg *msg); +private: + int _field12C; + int _field130; + int _field134; + int _field138; +public: + CLASSDEF; + CFruit(); + + /** + * 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_FRUIT_H */ diff --git a/engines/titanic/carry/glass.cpp b/engines/titanic/carry/glass.cpp new file mode 100644 index 0000000000..03050dc60d --- /dev/null +++ b/engines/titanic/carry/glass.cpp @@ -0,0 +1,158 @@ +/* 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/carry/glass.h" +#include "titanic/carry/chicken.h" +#include "titanic/game/sauce_dispensor.h" +#include "titanic/npcs/character.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGlass, CCarry) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +CGlass::CGlass() : CCarry(), _string6("None") { +} + +void CGlass::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string6, indent); + CCarry::save(file, indent); +} + +void CGlass::load(SimpleFile *file) { + file->readNumber(); + _string6 = file->readString(); + CCarry::load(file); +} + +bool CGlass::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CSauceDispensor *dispensor = dynamic_cast<CSauceDispensor *>(msg->_other); + CChicken *chicken = dynamic_cast<CChicken *>(msg->_other); + + if (dispensor && _string6 != "None") { + CUse useMsg(this); + useMsg.execute(dispensor); + } else if (msg->_other->isEquals("Chicken") && _string6 != "None") { + if (chicken->_string6 != "None") { + if (!chicken->_field12C) { + CActMsg actMsg(_string6); + actMsg.execute("Chicken"); + } + + _string6 = "None"; + loadFrame(0); + _visibleFrame = 0; + } + + petAddToInventory(); + } else if (msg->_other->isEquals("Napkin") && _string6 != "None") { + petAddToInventory(); + _string6 = "None"; + loadFrame(0); + _visibleFrame = 0; + } else { + petAddToInventory(); + } + + return true; +} + +bool CGlass::UseWithCharMsg(CUseWithCharMsg *msg) { + if (msg->_character->isEquals("Barbot") && msg->_character->_visible) { + CActMsg actMsg(_string6); + setVisible(false); + + if (_string6 != "Bird") + setPosition(_origPos); + + actMsg.execute(msg->_character); + } else { + petAddToInventory(); + } + + return true; +} + +bool CGlass::ActMsg(CActMsg *msg) { + if (msg->_action == "GoToPET") { + setVisible(true); + petAddToInventory(); + } else if (msg->_action == "Mustard") { + _string6 = "Mustard"; + loadFrame(1); + _visibleFrame = 1; + } else if (msg->_action == "Tomato") { + _string6 = "Tomato"; + loadFrame(2); + _visibleFrame = 2; + } else if (msg->_action == "Bird") { + _string6 = "Bird"; + loadFrame(3); + _visibleFrame = 3; + } else if (msg->_action == "InTitilator") { + _string6 = "None"; + loadFrame(0); + _visibleFrame = 0; + } + + return true; +} + +bool CGlass::MouseDragEndMsg(CMouseDragEndMsg *msg) { + showMouse(); + if (msg->_dropTarget) { + error("TODO: See what drop target is"); + CCharacter *npc = dynamic_cast<CCharacter *>(msg->_dropTarget); + if (npc) { + CUseWithCharMsg useMsg(npc); + useMsg.execute(this); + } else { + CUseWithOtherMsg otherMsg(npc); + otherMsg.execute(this); + } + } else if (compareViewNameTo(_fullViewName) && msg->_mousePos.y < 360) { + setPosition(_origPos); + } else { + petAddToInventory(); + } + + return true; +} + +bool CGlass::TurnOn(CTurnOn *msg) { + setVisible(true); + return true; +} + +bool CGlass::TurnOff(CTurnOff *msg) { + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/glass.h b/engines/titanic/carry/glass.h new file mode 100644 index 0000000000..85443840a1 --- /dev/null +++ b/engines/titanic/carry/glass.h @@ -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. + * + */ + +#ifndef TITANIC_GLASS_H +#define TITANIC_GLASS_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CGlass : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool ActMsg(CActMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); +private: + CString _string6; +public: + CLASSDEF; + CGlass(); + + /** + * 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_GLASS_H */ diff --git a/engines/titanic/carry/hammer.cpp b/engines/titanic/carry/hammer.cpp new file mode 100644 index 0000000000..88c766d564 --- /dev/null +++ b/engines/titanic/carry/hammer.cpp @@ -0,0 +1,63 @@ +/* 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/carry/hammer.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHammer, CCarry) + ON_MESSAGE(PuzzleSolvedMsg) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CHammer::CHammer() : CCarry() { +} + +void CHammer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CHammer::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CHammer::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _fieldE0 = 1; + return true; +} + +bool CHammer::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CString name = msg->_other->getName(); + if (name == "LongStickDispenser") { + CPuzzleSolvedMsg solvedMsg; + solvedMsg.execute("LongStickDispenser"); + } else if (name == "Bomb") { + CActMsg actMsg("Hit"); + actMsg.execute("Bomb"); + } + + return CCarry::UseWithOtherMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/hammer.h b/engines/titanic/carry/hammer.h new file mode 100644 index 0000000000..8cc86f3db1 --- /dev/null +++ b/engines/titanic/carry/hammer.h @@ -0,0 +1,51 @@ +/* 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_HAMMER_H +#define TITANIC_HAMMER_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CHammer : public CCarry { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +public: + CLASSDEF; + CHammer(); + + /** + * 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_HAMMER_H */ diff --git a/engines/titanic/carry/head_piece.cpp b/engines/titanic/carry/head_piece.cpp new file mode 100644 index 0000000000..34850488a7 --- /dev/null +++ b/engines/titanic/carry/head_piece.cpp @@ -0,0 +1,93 @@ +/* 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/carry/head_piece.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHeadPiece, CCarry) + ON_MESSAGE(SenseWorkingMsg) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +CHeadPiece::CHeadPiece() : CCarry(), _string6("Not Working"), + _flag(0), _field13C(false) { +} + +void CHeadPiece::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + file->writeQuotedLine(_string6, indent); + file->writeNumberLine(_field13C, indent); + + CCarry::save(file, indent); +} + +void CHeadPiece::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + _string6 = file->readString(); + _field13C = file->readNumber(); + + CCarry::load(file); +} + +bool CHeadPiece::SenseWorkingMsg(CSenseWorkingMsg *msg) { + _string6 = msg->_value; + return true; +} + +bool CHeadPiece::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + _visibleFrame = 1; + if (!_field13C) { + stateInc38(); + _field13C = true; + } + + return true; +} + +bool CHeadPiece::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkPoint(msg->_mousePos, false, true)) { + return false; + } else if (!_fieldE0) { + return true; + } + + if (_flag) { + setVisible(true); + moveToView(); + setPosition(Point(msg->_mousePos.x - _bounds.width() / 2, + msg->_mousePos.y - _bounds.height() / 2)); + + CTakeHeadPieceMsg takeMsg(getName()); + if (takeMsg._value != "NULL") + takeMsg.execute("TitaniaControl"); + + _flag = false; + } + + return CCarry::MouseDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/head_piece.h b/engines/titanic/carry/head_piece.h new file mode 100644 index 0000000000..367f781f0e --- /dev/null +++ b/engines/titanic/carry/head_piece.h @@ -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. + * + */ + +#ifndef TITANIC_HEAD_PIECE_H +#define TITANIC_HEAD_PIECE_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CHeadPiece : public CCarry { + DECLARE_MESSAGE_MAP; + bool SenseWorkingMsg(CSenseWorkingMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +protected: + bool _flag; + CString _string6; + bool _field13C; +public: + CLASSDEF; + CHeadPiece(); + + /** + * 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_HEAD_PIECE_H */ diff --git a/engines/titanic/carry/hose.cpp b/engines/titanic/carry/hose.cpp new file mode 100644 index 0000000000..e90119138a --- /dev/null +++ b/engines/titanic/carry/hose.cpp @@ -0,0 +1,120 @@ +/* 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/carry/hose.h" +#include "titanic/npcs/succubus.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHose, CCarry) + ON_MESSAGE(DropZoneGotObjectMsg) + ON_MESSAGE(PumpingMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(HoseConnectedMsg) + ON_MESSAGE(DropZoneLostObjectMsg) +END_MESSAGE_MAP() + +CHoseStatics *CHose::_statics; + +void CHose::init() { + _statics = new CHoseStatics(); +} + +void CHose::deinit() { + delete _statics; +} + +CHose::CHose() : CCarry(), + _string6("Succ-U-Bus auxiliary hose attachment incompatible with sliding glass cover.") { +} + +void CHose::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_statics->_actionVal, indent); + file->writeQuotedLine(_statics->_actionTarget, indent); + file->writeQuotedLine(_string6, indent); + CCarry::save(file, indent); +} + +void CHose::load(SimpleFile *file) { + file->readNumber(); + _statics->_actionVal = file->readNumber(); + _statics->_actionTarget = file->readString(); + _string6 = file->readString(); + CCarry::load(file); +} + +bool CHose::DropZoneGotObjectMsg(CDropZoneGotObjectMsg *msg) { + _statics->_actionTarget = msg->_object->getName(); + CPumpingMsg pumpingMsg; + pumpingMsg._value = _statics->_actionVal; + pumpingMsg.execute(_statics->_actionTarget); + CHoseConnectedMsg connectedMsg; + connectedMsg._value = 1; + connectedMsg.execute(this); + + return true; +} + +bool CHose::PumpingMsg(CPumpingMsg *msg) { + _statics->_actionVal = msg->_value; + if (!_statics->_actionTarget.empty()) { + CPumpingMsg pumpingMsg; + pumpingMsg._value = _statics->_actionVal; + pumpingMsg.execute(_statics->_actionTarget); + } + + return true; +} + +bool CHose::UseWithCharMsg(CUseWithCharMsg *msg) { + CSuccUBus *succubus = dynamic_cast<CSuccUBus *>(msg->_character); + if (!_statics->_actionVal && succubus) { + CHoseConnectedMsg connectedMsg(1, this); + if (connectedMsg.execute(succubus)) + return true; + } + + return CCarry::UseWithCharMsg(msg); +} + +bool CHose::HoseConnectedMsg(CHoseConnectedMsg *msg) { + if (msg->_value) { + CHose *hose = dynamic_cast<CHose *>(findChildInstanceOf(CHose::_type)); + if (hose) { + setVisible(true); + petAddToInventory(); + } + } + + return true; +} + +bool CHose::DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg) { + CPumpingMsg pumpingMsg; + pumpingMsg._value = 0; + pumpingMsg.execute(msg->_object); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/hose.h b/engines/titanic/carry/hose.h new file mode 100644 index 0000000000..3c8c1549c1 --- /dev/null +++ b/engines/titanic/carry/hose.h @@ -0,0 +1,66 @@ +/* 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_HOSE_H +#define TITANIC_HOSE_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +struct CHoseStatics { + int _actionVal; + CString _actionTarget; + CHoseStatics() : _actionVal(0) {} +}; + +class CHose : public CCarry { + DECLARE_MESSAGE_MAP; + bool DropZoneGotObjectMsg(CDropZoneGotObjectMsg *msg); + bool PumpingMsg(CPumpingMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool HoseConnectedMsg(CHoseConnectedMsg *msg); + bool DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg); +protected: + CString _string6; +public: + static CHoseStatics *_statics; +public: + CLASSDEF; + CHose(); + static void init(); + static void deinit(); + + /** + * 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_HOSE_H */ diff --git a/engines/titanic/carry/hose_end.cpp b/engines/titanic/carry/hose_end.cpp new file mode 100644 index 0000000000..c9996437bb --- /dev/null +++ b/engines/titanic/carry/hose_end.cpp @@ -0,0 +1,45 @@ +/* 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/carry/hose_end.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CHoseEnd, CHose); + +CHoseEnd::CHoseEnd() : CHose() { + _string6 = "Connection refused by remote hose."; +} + +void CHoseEnd::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string6, indent); + CHose::save(file, indent); +} + +void CHoseEnd::load(SimpleFile *file) { + file->readNumber(); + _string6 = file->readString(); + CHose::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/hose_end.h b/engines/titanic/carry/hose_end.h new file mode 100644 index 0000000000..836c94456a --- /dev/null +++ b/engines/titanic/carry/hose_end.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_HOSE_END_H +#define TITANIC_HOSE_END_H + +#include "titanic/carry/hose.h" + +namespace Titanic { + +class CHoseEnd : public CHose { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CHoseEnd(); + + /** + * 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_HOSE_END_H */ diff --git a/engines/titanic/carry/key.cpp b/engines/titanic/carry/key.cpp new file mode 100644 index 0000000000..187ff1b6c3 --- /dev/null +++ b/engines/titanic/carry/key.cpp @@ -0,0 +1,60 @@ +/* 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/carry/key.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CKey, CCarry) + ON_MESSAGE(PuzzleSolvedMsg) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CKey::CKey() : CCarry() { +} + +void CKey::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CKey::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CKey::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _fieldE0 = 1; + setVisible(true); + return true; +} + +bool CKey::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (msg->_other->getName() == "1stClassPhono") { + CActMsg actMsg("Unlock"); + actMsg.execute(msg->_other); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/key.h b/engines/titanic/carry/key.h new file mode 100644 index 0000000000..9d3957937c --- /dev/null +++ b/engines/titanic/carry/key.h @@ -0,0 +1,51 @@ +/* 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_KEY_H +#define TITANIC_KEY_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CKey : public CCarry { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +public: + CLASSDEF; + CKey(); + + /** + * 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_KEY_H */ diff --git a/engines/titanic/carry/liftbot_head.cpp b/engines/titanic/carry/liftbot_head.cpp new file mode 100644 index 0000000000..5f516fcf8c --- /dev/null +++ b/engines/titanic/carry/liftbot_head.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 "titanic/carry/liftbot_head.h" +#include "titanic/game/transport/lift.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLiftbotHead, CCarry) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +CLiftbotHead::CLiftbotHead() : CCarry(), _flag(false) { +} + +void CLiftbotHead::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CCarry::save(file, indent); +} + +void CLiftbotHead::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CCarry::load(file); +} + +bool CLiftbotHead::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (msg->_other->getName() == "LiftbotWithoutHead") { + CPetControl *pet = getPetControl(); + if (CLift::_v1 == 1 && pet->getRoomsElevatorNum() == 4) { + _flag = true; + CActMsg actMsg("AddRightHead"); + actMsg.execute("FaultyLiftbot"); + setVisible(false); + } + + return true; + } else { + return CCarry::UseWithOtherMsg(msg); + } +} + +bool CLiftbotHead::UseWithCharMsg(CUseWithCharMsg *msg) { + CLift *lift = dynamic_cast<CLift *>(msg->_character); + if (lift) { + CPetControl *pet = getPetControl(); + if (lift->isEquals("Well") && !CLift::_v1 && pet->getRoomsElevatorNum() == 4) { + _flag = true; + CActMsg actMsg("AddRightHead"); + actMsg.execute(lift); + setVisible(false); + + return true; + } + } + + return CCarry::UseWithCharMsg(msg); +} + +bool CLiftbotHead::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) { + return false; + } else if (compareViewNameTo("BottomOfWell.Node 8.N")) { + changeView("BottomOfWell.Node 13.N"); + moveToView(); + + CActMsg actMsg("LiftbotHeadTaken"); + actMsg.execute("BOWLiftbotHeadMonitor"); + + return CCarry::MouseDragStartMsg(msg); + } else if (_flag) { + _flag = false; + CActMsg actMsg("LoseHead"); + actMsg.execute("FaultyLiftbot"); + } + + return CCarry::MouseDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/liftbot_head.h b/engines/titanic/carry/liftbot_head.h new file mode 100644 index 0000000000..44cc51c993 --- /dev/null +++ b/engines/titanic/carry/liftbot_head.h @@ -0,0 +1,54 @@ +/* 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_LIFTBOT_HEAD_H +#define TITANIC_LIFTBOT_HEAD_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CLiftbotHead : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CLiftbotHead(); + + /** + * 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_LIFTBOT_HEAD_H */ diff --git a/engines/titanic/carry/long_stick.cpp b/engines/titanic/carry/long_stick.cpp new file mode 100644 index 0000000000..557b75ab87 --- /dev/null +++ b/engines/titanic/carry/long_stick.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/carry/long_stick.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLongStick, CCarry) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(PuzzleSolvedMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +CLongStick::CLongStick() : CCarry() { +} + +void CLongStick::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CLongStick::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CLongStick::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (msg->_other->isEquals("SpeechCentre")) { + CPuzzleSolvedMsg puzzleMsg; + puzzleMsg.execute(msg->_other); + } else if (msg->_other->isEquals("LongStickDispensor")) { + petDisplayMessage(1, "You already have one."); + } else if (msg->_other->isEquals("Bomb")) { + CActMsg actMsg("Hit"); + actMsg.execute("Bomb"); + } else { + return CCarry::UseWithOtherMsg(msg); + } + + return true; +} + +bool CLongStick::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _fieldE0 = 1; + return true; +} + +bool CLongStick::LeaveViewMsg(CLeaveViewMsg *msg) { + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/long_stick.h b/engines/titanic/carry/long_stick.h new file mode 100644 index 0000000000..329ca838f9 --- /dev/null +++ b/engines/titanic/carry/long_stick.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_LONG_STICK_H +#define TITANIC_LONG_STICK_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CLongStick : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +public: + CLASSDEF; + CLongStick(); + + /** + * 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_LONG_STICK_H */ diff --git a/engines/titanic/carry/magazine.cpp b/engines/titanic/carry/magazine.cpp new file mode 100644 index 0000000000..cdf92fc707 --- /dev/null +++ b/engines/titanic/carry/magazine.cpp @@ -0,0 +1,93 @@ +/* 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/carry/magazine.h" +#include "titanic/npcs/deskbot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMagazine, CCarry) + ON_MESSAGE(UseWithCharMsg) + ON_MESSAGE(MouseDoubleClickMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CMagazine::CMagazine() : CCarry() { +} + +void CMagazine::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_field130, indent); + + CCarry::save(file, indent); +} + +void CMagazine::load(SimpleFile *file) { + file->readNumber(); + _field12C = file->readNumber(); + _field130 = file->readNumber(); + + CCarry::load(file); +} + +bool CMagazine::UseWithCharMsg(CUseWithCharMsg *msg) { + CDeskbot *deskbot = static_cast<CDeskbot *>(msg->_character); + if (deskbot) { + if (deskbot->_deskbotActive) { + setVisible(false); + setPosition(Point(1000, 1000)); + CActMsg actMsg("2ndClassUpgrade"); + actMsg.execute("Deskbot"); + } + + return true; + } else { + return CCarry::UseWithCharMsg(msg); + } +} + +bool CMagazine::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + return true; +} + +bool CMagazine::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +bool CMagazine::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (msg->_other->getName() == "SwitchOnDeskbot") { + // TODO: other _field108 if + if (false) { + setVisible(false); + setPosition(Point(1000, 1000)); + CActMsg actMsg("2ndClassUpgrade"); + actMsg.execute("Deskbot"); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/magazine.h b/engines/titanic/carry/magazine.h new file mode 100644 index 0000000000..d1db4689ba --- /dev/null +++ b/engines/titanic/carry/magazine.h @@ -0,0 +1,58 @@ +/* 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_MAGAZINE_H +#define TITANIC_MAGAZINE_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CMagazine : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithCharMsg(CUseWithCharMsg *msg); + bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +private: + int _field12C; + int _field130; +public: + CLASSDEF; + CMagazine(); + + /** + * 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_MAGAZINE_H */ diff --git a/engines/titanic/carry/maitred_left_arm.cpp b/engines/titanic/carry/maitred_left_arm.cpp new file mode 100644 index 0000000000..0962f232bd --- /dev/null +++ b/engines/titanic/carry/maitred_left_arm.cpp @@ -0,0 +1,68 @@ +/* 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/carry/maitred_left_arm.h" +#include "titanic/npcs/true_talk_npc.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreDLeftArm, CArm) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CMaitreDLeftArm::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CArm::save(file, indent); +} + +void CMaitreDLeftArm::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CArm::load(file); +} + +bool CMaitreDLeftArm::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_flag) { + CTrueTalkNPC *maitreD = dynamic_cast<CTrueTalkNPC *>(findRoomObject("MaitreD")); + startTalking(maitreD, 126); + startTalking(maitreD, 127); + } + + return true; +} + +bool CMaitreDLeftArm::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkPoint(msg->_mousePos) && !_flag) { + CVisibleMsg visibleMsg; + visibleMsg.execute("MD left arm background image"); + _flag = true; + + CArmPickedUpFromTableMsg takenMsg; + takenMsg.execute("Restaurant Table Pan Handler", nullptr, MSGFLAG_SCAN); + } + + return CArm::MouseDragStartMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/maitred_left_arm.h b/engines/titanic/carry/maitred_left_arm.h new file mode 100644 index 0000000000..0e1732df46 --- /dev/null +++ b/engines/titanic/carry/maitred_left_arm.h @@ -0,0 +1,53 @@ +/* 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_LEFT_ARM_H +#define TITANIC_LEFT_ARM_H + +#include "titanic/carry/arm.h" + +namespace Titanic { + +class CMaitreDLeftArm : public CArm { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CMaitreDLeftArm() : CArm(), _flag(false) {} + + /** + * 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_LEFT_ARM_H */ diff --git a/engines/titanic/carry/maitred_right_arm.cpp b/engines/titanic/carry/maitred_right_arm.cpp new file mode 100644 index 0000000000..5cec6be9bd --- /dev/null +++ b/engines/titanic/carry/maitred_right_arm.cpp @@ -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. + * + */ + +#include "titanic/carry/maitred_right_arm.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreDRightArm, CArm) + ON_MESSAGE(DropZoneLostObjectMsg) +END_MESSAGE_MAP() + +void CMaitreDRightArm::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CArm::save(file, indent); +} + +void CMaitreDRightArm::load(SimpleFile *file) { + file->readNumber(); + CArm::load(file); +} + +bool CMaitreDRightArm::DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg) { + CActMsg actMsg("LoseArm"); + actMsg.execute("MaitreDBody"); + actMsg.execute("MaitreD Arm Holder"); + _fieldE0 = 1; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/maitred_right_arm.h b/engines/titanic/carry/maitred_right_arm.h new file mode 100644 index 0000000000..4a53d45f69 --- /dev/null +++ b/engines/titanic/carry/maitred_right_arm.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_MAITRED_RIGHT_ARM_H +#define TITANIC_MAITRED_RIGHT_ARM_H + +#include "titanic/carry/arm.h" + +namespace Titanic { + +class CMaitreDRightArm : public CArm { + DECLARE_MESSAGE_MAP; + bool DropZoneLostObjectMsg(CDropZoneLostObjectMsg *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_MAITRED_RIGHT_ARM_H */ diff --git a/engines/titanic/carry/mouth.cpp b/engines/titanic/carry/mouth.cpp new file mode 100644 index 0000000000..e48929a391 --- /dev/null +++ b/engines/titanic/carry/mouth.cpp @@ -0,0 +1,80 @@ +/* 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/carry/mouth.h" +#include "titanic/game/head_slot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMouth, CHeadPiece) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(PETGainedObjectMsg) +END_MESSAGE_MAP() + +CMouth::CMouth() : CHeadPiece() { +} + +void CMouth::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CHeadPiece::save(file, indent); +} + +void CMouth::load(SimpleFile *file) { + file->readNumber(); + CHeadPiece::load(file); +} + +bool CMouth::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CHeadSlot *slot = dynamic_cast<CHeadSlot *>(msg->_other); + if (!slot) + return CHeadPiece::UseWithOtherMsg(msg); + + _flag = true; + setVisible(false); + setPosition(Point(0, 0)); + petMoveToHiddenRoom(); + + CAddHeadPieceMsg addMsg(getName()); + if (addMsg._value != "NULL") + addMsg.execute("MouthSlot"); + + return true; +} + +bool CMouth::MovieEndMsg(CMovieEndMsg *msg) { + return true; +} + +bool CMouth::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + _visibleFrame = 2; + loadFrame(2); + setVisible(true); + if (!_field13C) { + stateInc38(); + _field13C = true; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/mouth.h b/engines/titanic/carry/mouth.h new file mode 100644 index 0000000000..f5f0f53b45 --- /dev/null +++ b/engines/titanic/carry/mouth.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_MOUTH_H +#define TITANIC_MOUTH_H + +#include "titanic/carry/head_piece.h" + +namespace Titanic { + +class CMouth : public CHeadPiece { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); +public: + CLASSDEF; + CMouth(); + + /** + * 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_MOUTH_H */ diff --git a/engines/titanic/carry/napkin.cpp b/engines/titanic/carry/napkin.cpp new file mode 100644 index 0000000000..d25e8b5975 --- /dev/null +++ b/engines/titanic/carry/napkin.cpp @@ -0,0 +1,60 @@ +/* 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/carry/napkin.h" +#include "titanic/carry/chicken.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNapkin, CCarry) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CNapkin::CNapkin() : CCarry() { +} + +void CNapkin::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CNapkin::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CNapkin::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CChicken *chicken = static_cast<CChicken *>(msg->_other); + if (chicken) { + if (chicken->_string6 == "None" || chicken->_field12C) { + CActMsg actMsg("Clean"); + actMsg.execute("Chicken"); + } else { + petDisplayMessage("The Chicken is already quite clean enough, thank you."); + } + } + + petAddToInventory(); + return CCarry::UseWithOtherMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/napkin.h b/engines/titanic/carry/napkin.h new file mode 100644 index 0000000000..ce47dd6059 --- /dev/null +++ b/engines/titanic/carry/napkin.h @@ -0,0 +1,51 @@ +/* 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_NAPKIN_H +#define TITANIC_NAPKIN_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CNapkin : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +public: + CLASSDEF; + CNapkin(); + + /** + * 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_NAPKIN_H */ diff --git a/engines/titanic/carry/nose.cpp b/engines/titanic/carry/nose.cpp new file mode 100644 index 0000000000..a08d02a88c --- /dev/null +++ b/engines/titanic/carry/nose.cpp @@ -0,0 +1,65 @@ +/* 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/carry/nose.h" +#include "titanic/game/head_slot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNose, CHeadPiece) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CNose::CNose() : CHeadPiece() { +} + +void CNose::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CHeadPiece::save(file, indent); +} + +void CNose::load(SimpleFile *file) { + file->readNumber(); + CHeadPiece::load(file); +} + +bool CNose::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + // WORKAROUND: Redundant code in original skipped + return true; +} + +bool CNose::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CHeadSlot *slot = dynamic_cast<CHeadSlot *>(msg->_other); + if (!slot) + return CCarry::UseWithOtherMsg(msg); + + petMoveToHiddenRoom(); + _flag = false; + CAddHeadPieceMsg addMsg(getName()); + if (addMsg._value != "NULL") + addMsg.execute("NoseSlot"); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/nose.h b/engines/titanic/carry/nose.h new file mode 100644 index 0000000000..6e5be30df2 --- /dev/null +++ b/engines/titanic/carry/nose.h @@ -0,0 +1,51 @@ +/* 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_NOSE_H +#define TITANIC_NOSE_H + +#include "titanic/carry/head_piece.h" + +namespace Titanic { + +class CNose : public CHeadPiece { + DECLARE_MESSAGE_MAP; + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +public: + CLASSDEF; + CNose(); + + /** + * 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_NOSE_H */ diff --git a/engines/titanic/carry/note.cpp b/engines/titanic/carry/note.cpp new file mode 100644 index 0000000000..388f87e638 --- /dev/null +++ b/engines/titanic/carry/note.cpp @@ -0,0 +1,54 @@ +/* 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/carry/note.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNote, CCarry) + ON_MESSAGE(MouseDoubleClickMsg) +END_MESSAGE_MAP() + +CNote::CNote() : CCarry(), _field138(1) { +} + +void CNote::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string6, indent); + file->writeNumberLine(_field138, indent); + + CCarry::save(file, indent); +} + +void CNote::load(SimpleFile *file) { + file->readNumber(); + _string6 = file->readString(); + _field138 = file->readNumber(); + + CCarry::load(file); +} + +bool CNote::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/note.h b/engines/titanic/carry/note.h new file mode 100644 index 0000000000..37ebf96d72 --- /dev/null +++ b/engines/titanic/carry/note.h @@ -0,0 +1,54 @@ +/* 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_NOTE_H +#define TITANIC_NOTE_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CNote : public CCarry { + DECLARE_MESSAGE_MAP; + bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); +private: + CString _string6; + int _field138; +public: + CLASSDEF; + CNote(); + + /** + * 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_NOTE_H */ diff --git a/engines/titanic/carry/parcel.cpp b/engines/titanic/carry/parcel.cpp new file mode 100644 index 0000000000..2ffe8b0aac --- /dev/null +++ b/engines/titanic/carry/parcel.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/carry/parcel.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CParcel, CCarry); + +CParcel::CParcel() : CCarry() { +} + +void CParcel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CParcel::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/parcel.h b/engines/titanic/carry/parcel.h new file mode 100644 index 0000000000..f33c2ff65a --- /dev/null +++ b/engines/titanic/carry/parcel.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_PARCEL_H +#define TITANIC_PARCEL_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CParcel : public CCarry { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CParcel(); + + /** + * 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_PARCEL_H */ diff --git a/engines/titanic/carry/perch.cpp b/engines/titanic/carry/perch.cpp new file mode 100644 index 0000000000..4f0e76bdb0 --- /dev/null +++ b/engines/titanic/carry/perch.cpp @@ -0,0 +1,50 @@ +/* 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/carry/perch.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPerch, CCentralCore) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +void CPerch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCentralCore::save(file, indent); +} + +void CPerch::load(SimpleFile *file) { + file->readNumber(); + CCentralCore::load(file); +} + +bool CPerch::UseWithOtherMsg(CUseWithOtherMsg *msg) { + if (msg->_other->isEquals("SpeechCentre")) { + CShowTextMsg textMsg("This does not reach."); + textMsg.execute("PET"); + } + + return CCentralCore::UseWithOtherMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/perch.h b/engines/titanic/carry/perch.h new file mode 100644 index 0000000000..8941c8ea4d --- /dev/null +++ b/engines/titanic/carry/perch.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_PERCH_H +#define TITANIC_PERCH_H + +#include "titanic/carry/central_core.h" + +namespace Titanic { + +class CPerch : public CCentralCore { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *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_PERCH_H */ diff --git a/engines/titanic/carry/phonograph_cylinder.cpp b/engines/titanic/carry/phonograph_cylinder.cpp new file mode 100644 index 0000000000..41df050d2b --- /dev/null +++ b/engines/titanic/carry/phonograph_cylinder.cpp @@ -0,0 +1,202 @@ +/* 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/carry/phonograph_cylinder.h" +#include "titanic/game/phonograph.h" +#include "titanic/sound/music_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPhonographCylinder, CCarry) + ON_MESSAGE(UseWithOtherMsg) + ON_MESSAGE(QueryCylinderMsg) + ON_MESSAGE(RecordOntoCylinderMsg) + ON_MESSAGE(SetMusicControlsMsg) + ON_MESSAGE(ErasePhonographCylinderMsg) +END_MESSAGE_MAP() + +CPhonographCylinder::CPhonographCylinder() : CCarry(), + _bellsMuteControl(false), _bellsPitchControl(false), + _bellsSpeedControl(false), _bellsDirectionControl(false), + _bellsInversionControl(false), _snakeMuteControl(false), + _snakeSpeedControl(false), _snakePitchControl(false), + _snakeInversionControl(false), _snakeDirectionControl(false), + _pianoMuteControl(false), _pianoSpeedControl(false), + _pianoPitchControl(false), _pianoInversionControl(false), + _pianoDirectionControl(false), _bassMuteControl(false), + _bassSpeedControl(false), _bassPitchControl(false), + _bassInversionControl(false) { +} + +void CPhonographCylinder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_itemName, indent); + file->writeNumberLine(_bellsMuteControl, indent); + file->writeNumberLine(_bellsPitchControl, indent); + file->writeNumberLine(_bellsSpeedControl, indent); + file->writeNumberLine(_bellsDirectionControl, indent); + file->writeNumberLine(_bellsInversionControl, indent); + file->writeNumberLine(_snakeMuteControl, indent); + file->writeNumberLine(_snakeSpeedControl, indent); + file->writeNumberLine(_snakePitchControl, indent); + file->writeNumberLine(_snakeInversionControl, indent); + file->writeNumberLine(_snakeDirectionControl, indent); + file->writeNumberLine(_pianoMuteControl, indent); + file->writeNumberLine(_pianoSpeedControl, indent); + file->writeNumberLine(_pianoPitchControl, indent); + file->writeNumberLine(_pianoInversionControl, indent); + file->writeNumberLine(_pianoDirectionControl, indent); + file->writeNumberLine(_bassMuteControl, indent); + file->writeNumberLine(_bassSpeedControl, indent); + file->writeNumberLine(_bassPitchControl, indent); + file->writeNumberLine(_bassInversionControl, indent); + file->writeNumberLine(_bassDirectionControl, indent); + + CCarry::save(file, indent); +} + +void CPhonographCylinder::load(SimpleFile *file) { + file->readNumber(); + _itemName = file->readString(); + _bellsMuteControl = file->readNumber(); + _bellsPitchControl = file->readNumber(); + _bellsSpeedControl = file->readNumber(); + _bellsDirectionControl = file->readNumber(); + _bellsInversionControl = file->readNumber(); + _snakeMuteControl = file->readNumber(); + _snakeSpeedControl = file->readNumber(); + _snakePitchControl = file->readNumber(); + _snakeInversionControl = file->readNumber(); + _snakeDirectionControl = file->readNumber(); + _pianoMuteControl = file->readNumber(); + _pianoSpeedControl = file->readNumber(); + _pianoPitchControl = file->readNumber(); + _pianoInversionControl = file->readNumber(); + _pianoDirectionControl = file->readNumber(); + _bassMuteControl = file->readNumber(); + _bassSpeedControl = file->readNumber(); + _bassPitchControl = file->readNumber(); + _bassInversionControl = file->readNumber(); + _bassDirectionControl = file->readNumber(); + + CCarry::load(file); +} + +bool CPhonographCylinder::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CPhonograph *phonograph = static_cast<CPhonograph *>(msg->_other); + if (phonograph) { + CSetVarMsg varMsg("m_RecordStatus", 1); + return true; + } else { + return CCarry::UseWithOtherMsg(msg); + } +} + +bool CPhonographCylinder::QueryCylinderMsg(CQueryCylinderMsg *msg) { + msg->_name = _itemName; + return true; +} + +bool CPhonographCylinder::RecordOntoCylinderMsg(CRecordOntoCylinderMsg *msg) { + _itemName = "STMusic"; + + CQueryMusicControlSettingMsg queryMsg; + queryMsg.execute("Bells Mute Control"); + _bellsMuteControl = queryMsg._value; + queryMsg.execute("Bells Pitch Control"); + _bellsPitchControl = queryMsg._value; + queryMsg.execute("Bells Speed Control"); + _bellsSpeedControl = queryMsg._value; + queryMsg.execute("Bells Direction Control"); + _bellsDirectionControl = queryMsg._value; + queryMsg.execute("Bells Inversion Control"); + _bellsInversionControl = queryMsg._value; + queryMsg.execute("Snake Mute Control"); + _snakeMuteControl = queryMsg._value; + queryMsg.execute("Snake Speed Control"); + _snakeSpeedControl = queryMsg._value; + queryMsg.execute("Snake Pitch Control"); + _snakePitchControl = queryMsg._value; + queryMsg.execute("Snake Inversion Control"); + _snakeInversionControl = queryMsg._value; + queryMsg.execute("Snake Direction Control"); + _snakeDirectionControl = queryMsg._value; + queryMsg.execute("Piano Mute Control"); + _pianoMuteControl = queryMsg._value; + queryMsg.execute("Piano Speed Control"); + _pianoSpeedControl = queryMsg._value; + queryMsg.execute("Piano Pitch Control"); + _pianoPitchControl = queryMsg._value; + queryMsg.execute("Piano Inversion Control"); + _pianoInversionControl = queryMsg._value; + queryMsg.execute("Piano Direction Control"); + _pianoDirectionControl = queryMsg._value; + queryMsg.execute("Bass Mute Control"); + _bassMuteControl = queryMsg._value; + queryMsg.execute("Bass Speed Control"); + _bassSpeedControl = queryMsg._value; + queryMsg.execute("Bass Pitch Control"); + _bassPitchControl = queryMsg._value; + queryMsg.execute("Bass Inversion Control"); + _bassInversionControl = queryMsg._value; + + return true; +} + +bool CPhonographCylinder::SetMusicControlsMsg(CSetMusicControlsMsg *msg) { + if (!_itemName.hasPrefix("STMusic")) + return true; + + CMusicRoom *musicRoom = getMusicRoom(); + musicRoom->setItem5(BELLS, _bellsMuteControl); + musicRoom->setItem2(BELLS, _bellsPitchControl); + musicRoom->setItem1(BELLS, _bellsSpeedControl); + musicRoom->setItem4(BELLS, _bellsInversionControl); + musicRoom->setItem3(BELLS, _bellsDirectionControl); + + musicRoom->setItem5(SNAKE, _snakeMuteControl); + musicRoom->setItem2(SNAKE, _snakePitchControl); + musicRoom->setItem1(SNAKE, _snakeSpeedControl); + musicRoom->setItem4(SNAKE, _snakeInversionControl); + musicRoom->setItem3(SNAKE, _snakeDirectionControl); + + musicRoom->setItem5(PIANO, _pianoMuteControl); + musicRoom->setItem2(PIANO, _pianoPitchControl); + musicRoom->setItem1(PIANO, _pianoSpeedControl); + musicRoom->setItem4(PIANO, _pianoInversionControl); + musicRoom->setItem3(PIANO, _pianoDirectionControl); + + musicRoom->setItem5(BASS, _bassMuteControl); + musicRoom->setItem2(BASS, _bassPitchControl); + musicRoom->setItem1(BASS, _bassSpeedControl); + musicRoom->setItem4(BASS, _bassInversionControl); + musicRoom->setItem3(BASS, _bassDirectionControl); + + return true; +} + +bool CPhonographCylinder::ErasePhonographCylinderMsg(CErasePhonographCylinderMsg *msg) { + _itemName.clear(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/phonograph_cylinder.h b/engines/titanic/carry/phonograph_cylinder.h new file mode 100644 index 0000000000..bbb1524cb5 --- /dev/null +++ b/engines/titanic/carry/phonograph_cylinder.h @@ -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. + * + */ + +#ifndef TITANIC_PHONOGRAPH_CYLINDER_H +#define TITANIC_PHONOGRAPH_CYLINDER_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CPhonographCylinder : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); + bool QueryCylinderMsg(CQueryCylinderMsg *msg); + bool RecordOntoCylinderMsg(CRecordOntoCylinderMsg *msg); + bool SetMusicControlsMsg(CSetMusicControlsMsg *msg); + bool ErasePhonographCylinderMsg(CErasePhonographCylinderMsg *msg); +private: + CString _itemName; + bool _bellsMuteControl; + bool _bellsPitchControl; + bool _bellsSpeedControl; + bool _bellsDirectionControl; + bool _bellsInversionControl; + bool _snakeMuteControl; + bool _snakeSpeedControl; + bool _snakePitchControl; + bool _snakeInversionControl; + bool _snakeDirectionControl; + bool _pianoMuteControl; + bool _pianoSpeedControl; + bool _pianoPitchControl; + bool _pianoInversionControl; + bool _pianoDirectionControl; + bool _bassMuteControl; + bool _bassSpeedControl; + bool _bassPitchControl; + bool _bassInversionControl; + bool _bassDirectionControl; +public: + CLASSDEF; + CPhonographCylinder(); + + /** + * 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_PHONOGRAPH_CYLINDER_H */ diff --git a/engines/titanic/carry/phonograph_ear.cpp b/engines/titanic/carry/phonograph_ear.cpp new file mode 100644 index 0000000000..95297a77a1 --- /dev/null +++ b/engines/titanic/carry/phonograph_ear.cpp @@ -0,0 +1,65 @@ +/* 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/carry/phonograph_ear.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPhonographEar, CEar) + ON_MESSAGE(CorrectMusicPlayedMsg) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +void CPhonographEar::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field140, indent); + CEar::save(file, indent); +} + +void CPhonographEar::load(SimpleFile *file) { + file->readNumber(); + _field140 = file->readNumber(); + CEar::load(file); +} + +bool CPhonographEar::CorrectMusicPlayedMsg(CCorrectMusicPlayedMsg *msg) { + _fieldE0 = true; + return true; +} + +bool CPhonographEar::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + if (_field140) { + _field140 = false; + addTimer(1000); + } + + return CEar::PETGainedObjectMsg(msg); +} + +bool CPhonographEar::TimerMsg(CTimerMsg *msg) { + CVisibleMsg visibleMsg; + visibleMsg.execute("Replacement Phonograph Ear"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/phonograph_ear.h b/engines/titanic/carry/phonograph_ear.h new file mode 100644 index 0000000000..b5db015f90 --- /dev/null +++ b/engines/titanic/carry/phonograph_ear.h @@ -0,0 +1,54 @@ +/* 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_PHONOGRAPH_EAR_H +#define TITANIC_PHONOGRAPH_EAR_H + +#include "titanic/carry/ear.h" + +namespace Titanic { + +class CPhonographEar : public CEar { + DECLARE_MESSAGE_MAP; + bool CorrectMusicPlayedMsg(CCorrectMusicPlayedMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool TimerMsg(CTimerMsg *msg); +private: + bool _field140; +public: + CLASSDEF; + CPhonographEar() : CEar(), _field140(true) {} + + /** + * 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_PHONOGRAPH_EYE_H */ diff --git a/engines/titanic/carry/photograph.cpp b/engines/titanic/carry/photograph.cpp new file mode 100644 index 0000000000..039efd0252 --- /dev/null +++ b/engines/titanic/carry/photograph.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 "titanic/carry/photograph.h" +#include "titanic/core/dont_save_file_item.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPhotograph, CCarry) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(PETGainedObjectMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +int CPhotograph::_v1; + +CPhotograph::CPhotograph() : CCarry(), _field12C(0), _field130(0) { +} + +void CPhotograph::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_field130, indent); + + CCarry::save(file, indent); +} + +void CPhotograph::load(SimpleFile *file) { + file->readNumber(); + _field12C = file->readNumber(); + _v1 = file->readNumber(); + _field130 = file->readNumber(); + + CCarry::load(file); +} + +bool CPhotograph::MouseDragEndMsg(CMouseDragEndMsg *msg) { + _v1 = 0; + CGameObject *target = msg->_dropTarget; + + if (target && target->isEquals("NavigationComputer")) { + moveUnder(getDontSave()); + makeDirty(); + playSound("a#46.wav"); + starFn1(14); + showMouse(); + return true; + } else { + return CCarry::MouseDragEndMsg(msg); + } +} + +bool CPhotograph::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkPoint(msg->_mousePos, true, true)) { + _v1 = true; + CActMsg actMsg("PlayerPicksUpPhoto"); + actMsg.execute("Doorbot"); + } + + return CCarry::MouseDragStartMsg(msg); +} + +bool CPhotograph::PETGainedObjectMsg(CPETGainedObjectMsg *msg) { + if (getRoom()->isEquals("Home")) { + CActMsg actMsg("PlayerPutsPhotoInPET"); + actMsg.execute("Doorbot"); + } + + return true; +} + +bool CPhotograph::ActMsg(CActMsg *msg) { + if (msg->_action == "BecomeGettable") { + _fieldE0 = 1; + _cursorId = CURSOR_HAND; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/photograph.h b/engines/titanic/carry/photograph.h new file mode 100644 index 0000000000..9cea1e4799 --- /dev/null +++ b/engines/titanic/carry/photograph.h @@ -0,0 +1,61 @@ +/* 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_PHOTOGRAPH_H +#define TITANIC_PHOTOGRAPH_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CPhotograph : public CCarry { + DECLARE_MESSAGE_MAP; + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool PETGainedObjectMsg(CPETGainedObjectMsg *msg); + bool ActMsg(CActMsg *msg); +private: + static int _v1; +private: + int _field12C; + int _field130; +public: + CLASSDEF; + CPhotograph(); + + /** + * 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_PHOTOGRAPH_H */ diff --git a/engines/titanic/carry/plug_in.cpp b/engines/titanic/carry/plug_in.cpp new file mode 100644 index 0000000000..883458c9b1 --- /dev/null +++ b/engines/titanic/carry/plug_in.cpp @@ -0,0 +1,62 @@ +/* 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/carry/plug_in.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPlugIn, CCarry) + ON_MESSAGE(UseWithOtherMsg) +END_MESSAGE_MAP() + +CPlugIn::CPlugIn() : CCarry(), _field12C(0) { +} + +void CPlugIn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CPlugIn::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CPlugIn::UseWithOtherMsg(CUseWithOtherMsg *msg) { + CGameObject *other = msg->_other; + CString otherName = other->getName(); + + if (otherName == "PET") { + return CCarry::UseWithOtherMsg(msg); + } else if (isEquals("DatasideTransporter")) { + CShowTextMsg textMsg("This item is incorrectly calibrated."); + textMsg.execute("PET"); + } else if (isEquals("DatasideTransporter")) { + error("TODO: Set msg->_other->fieldC4 = 2"); + } else if (isEquals("SendYourself")) { + error("TODO: Set msg->_other->fieldC8 = 1"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/plug_in.h b/engines/titanic/carry/plug_in.h new file mode 100644 index 0000000000..1358a99e39 --- /dev/null +++ b/engines/titanic/carry/plug_in.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_PLUG_IN_H +#define TITANIC_PLUG_IN_H + +#include "titanic/carry/carry.h" + +namespace Titanic { + +class CPlugIn : public CCarry { + DECLARE_MESSAGE_MAP; + bool UseWithOtherMsg(CUseWithOtherMsg *msg); +private: + int _field12C; +public: + CLASSDEF; + CPlugIn(); + + /** + * 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_PLUG_IN_H */ diff --git a/engines/titanic/carry/speech_centre.cpp b/engines/titanic/carry/speech_centre.cpp new file mode 100644 index 0000000000..b8076aee76 --- /dev/null +++ b/engines/titanic/carry/speech_centre.cpp @@ -0,0 +1,45 @@ +/* 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/carry/speech_centre.h" + +namespace Titanic { + +void CSpeechCentre::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field13C, indent); + file->writeQuotedLine(_string1, indent); + file->writeNumberLine(_field14C, indent); + + CBrain::save(file, indent); +} + +void CSpeechCentre::load(SimpleFile *file) { + file->readNumber(); + _field13C = file->readNumber(); + _string1 = file->readString(); + _field14C = file->readNumber(); + + CBrain::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/speech_centre.h b/engines/titanic/carry/speech_centre.h new file mode 100644 index 0000000000..50f47e9c8a --- /dev/null +++ b/engines/titanic/carry/speech_centre.h @@ -0,0 +1,53 @@ +/* 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_SPEECH_CENTRE_H +#define TITANIC_SPEECH_CENTRE_H + +#include "titanic/carry/brain.h" + +namespace Titanic { + +class CSpeechCentre : public CBrain { +private: + int _field13C; + CString _string1; + int _field14C; +public: + CLASSDEF; + CSpeechCentre() : CBrain(), _string1("Summer"), + _field13C(1), _field14C(0) {} + + /** + * 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_SPEECH_CENTRE_H */ diff --git a/engines/titanic/carry/sweets.cpp b/engines/titanic/carry/sweets.cpp new file mode 100644 index 0000000000..f19a8287b7 --- /dev/null +++ b/engines/titanic/carry/sweets.cpp @@ -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. + * + */ + +#include "titanic/carry/sweets.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSweets, CCarry) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +CSweets::CSweets() : CCarry() { +} + +void CSweets::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CCarry::save(file, indent); +} + +void CSweets::load(SimpleFile *file) { + file->readNumber(); + CCarry::load(file); +} + +bool CSweets::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/sweets.h b/engines/titanic/carry/sweets.h new file mode 100644 index 0000000000..3655fabfb9 --- /dev/null +++ b/engines/titanic/carry/sweets.h @@ -0,0 +1,51 @@ +/* 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_SWEETS_H +#define TITANIC_SWEETS_H + +#include "titanic/carry/carry.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CSweets : public CCarry { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +public: + CLASSDEF; + CSweets(); + + /** + * 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_SWEETS_H */ diff --git a/engines/titanic/carry/vision_centre.cpp b/engines/titanic/carry/vision_centre.cpp new file mode 100644 index 0000000000..8c8bab15f8 --- /dev/null +++ b/engines/titanic/carry/vision_centre.cpp @@ -0,0 +1,37 @@ +/* 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/carry/vision_centre.h" + +namespace Titanic { + +void CVisionCentre::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBrain::save(file, indent); +} + +void CVisionCentre::load(SimpleFile *file) { + file->readNumber(); + CBrain::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/carry/vision_centre.h b/engines/titanic/carry/vision_centre.h new file mode 100644 index 0000000000..6cf8e2c653 --- /dev/null +++ b/engines/titanic/carry/vision_centre.h @@ -0,0 +1,47 @@ +/* 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_VISION_CENTRE_H +#define TITANIC_VISION_CENTRE_H + +#include "titanic/carry/brain.h" + +namespace Titanic { + +class CVisionCentre : public CBrain { +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_VISION_CENTRE_H */ diff --git a/engines/titanic/configure.engine b/engines/titanic/configure.engine new file mode 100644 index 0000000000..daf4e6b388 --- /dev/null +++ b/engines/titanic/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine titanic "Starship Titanic" no "" "" "16bit jpeg highres" diff --git a/engines/titanic/continue_save_dialog.cpp b/engines/titanic/continue_save_dialog.cpp new file mode 100644 index 0000000000..39b7d1942a --- /dev/null +++ b/engines/titanic/continue_save_dialog.cpp @@ -0,0 +1,224 @@ +/* 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/continue_save_dialog.h" +#include "titanic/titanic.h" + +namespace Titanic { + +#define SAVEGAME_SLOTS_COUNT 5 +#define RESTORE_X 346 +#define RESTORE_Y 94 +#define START_X 370 +#define START_Y 276 + +CContinueSaveDialog::CContinueSaveDialog() { + g_vm->_events->addTarget(this); + _highlightedSlot = _selectedSlot = -999; + _restoreState = _startState = -1; + _mouseDown = false; + _evilTwinShown = false; + + for (int idx = 0; idx < SAVEGAME_SLOTS_COUNT; ++idx) { + Rect slotRect = getSlotBounds(idx); + _slotNames[idx].setFontNumber(0); + _slotNames[idx].setBounds(slotRect); + _slotNames[idx].resize(3); + _slotNames[idx].setMaxCharsPerLine(22); + _slotNames[idx].setHasBorder(false); + _slotNames[idx].setup(); + } +} + +CContinueSaveDialog::~CContinueSaveDialog() { + g_vm->_events->removeTarget(); +} + +void CContinueSaveDialog::addSavegame(int slot, const CString &name) { + assert(_saves.size() < SAVEGAME_SLOTS_COUNT); + _slotNames[_saves.size()].setText(name); + _saves.push_back(SaveEntry(slot, name)); +} + +Rect CContinueSaveDialog::getSlotBounds(int index) { + return Rect(360, 164 + index * 19, 556, 180 + index * 19); +} + +int CContinueSaveDialog::show() { + // Load images for the dialog + loadImages(); + + // Render the view + render(); + + // Event loop waiting for selection + while (!g_vm->shouldQuit() && _selectedSlot == -999) { + g_vm->_events->pollEventsAndWait(); + } + + return _selectedSlot; +} + +void CContinueSaveDialog::loadImages() { + _backdrop.load("Bitmap/BACKDROP"); + _evilTwin.load("Bitmap/EVILTWIN"); + _restoreD.load("Bitmap/RESTORED"); + _restoreU.load("Bitmap/RESTOREU"); + _restoreF.load("Bitmap/RESTOREF"); + _startD.load("Bitmap/STARTD"); + _startU.load("Bitmap/STARTU"); + _startF.load("Bitmap/STARTF"); +} + +void CContinueSaveDialog::render() { + Graphics::Screen &screen = *g_vm->_screen; + screen.clear(); + screen.blitFrom(_backdrop, Common::Point(48, 22)); + + if (_evilTwinShown) + screen.blitFrom(_evilTwin, Common::Point(78, 59)); + + _restoreState = _startState = -1; + renderButtons(); + renderSlots(); +} + +void CContinueSaveDialog::renderButtons() { + Graphics::Screen &screen = *g_vm->_screen; + Rect restoreRect(RESTORE_X, RESTORE_Y, RESTORE_X + _restoreU.w, RESTORE_Y + _restoreU.h); + Rect startRect(START_X, START_Y, START_X + _startU.w, START_Y + _startU.h); + + // Determine the current state for the buttons + int restoreState, startState; + if (!restoreRect.contains(_mousePos)) + restoreState = 0; + else + restoreState = _mouseDown ? 1 : 2; + + if (!startRect.contains(_mousePos)) + startState = 0; + else + startState = _mouseDown ? 1 : 2; + + // Draw the start button + if (startState != _startState) { + _startState = startState; + switch (_startState) { + case 0: + screen.blitFrom(_startU, Common::Point(START_X, START_Y)); + break; + case 1: + screen.blitFrom(_startD, Common::Point(START_X, START_Y)); + break; + case 2: + screen.blitFrom(_startF, Common::Point(START_X, START_Y)); + break; + default: + break; + } + } + + // Draw the restore button + if (restoreState != _restoreState) { + _restoreState = restoreState; + switch (_restoreState) { + case 0: + screen.blitFrom(_restoreU, Common::Point(RESTORE_X, RESTORE_Y)); + break; + case 1: + screen.blitFrom(_restoreD, Common::Point(RESTORE_X, RESTORE_Y)); + break; + case 2: + screen.blitFrom(_restoreF, Common::Point(RESTORE_X, RESTORE_Y)); + break; + default: + break; + } + } +} + +void CContinueSaveDialog::renderSlots() { + for (int idx = 0; idx < (int)_saves.size(); ++idx) { + byte rgb = (_highlightedSlot == idx) ? 255 : 0; + _slotNames[idx].setColor(rgb, rgb, rgb); + _slotNames[idx].setLineColor(0, rgb, rgb, rgb); + _slotNames[idx].draw(CScreenManager::_screenManagerPtr); + } +} + +void CContinueSaveDialog::mouseMove(const Point &mousePos) { + _mousePos = mousePos; + renderButtons(); +} + +void CContinueSaveDialog::leftButtonDown(const Point &mousePos) { + _mouseDown = true; + mouseMove(mousePos); +} + +void CContinueSaveDialog::leftButtonUp(const Point &mousePos) { + Rect restoreRect(RESTORE_X, RESTORE_Y, RESTORE_X + _restoreU.w, RESTORE_Y + _restoreU.h); + Rect startRect(START_X, START_Y, START_X + _startU.w, START_Y + _startU.h); + _mouseDown = false; + + if (restoreRect.contains(mousePos)) { + // Flag to exit dialog and load highlighted slot. If no slot was + // selected explicitly, then fall back on loading the first slot + _selectedSlot = (_highlightedSlot == -999) ? _saves[0]._slot : + _saves[_highlightedSlot]._slot; + } else if (startRect.contains(mousePos)) { + // Start a new game + _selectedSlot = -1; + } else { + // Check whether a filled in slot was selected + for (uint idx = 0; idx < _saves.size(); ++idx) { + if (getSlotBounds(idx).contains(mousePos)) { + _highlightedSlot = idx; + render(); + break; + } + } + } +} + +void CContinueSaveDialog::rightButtonDown(const Point &mousePos) { + Rect eye1(188, 190, 192, 195), eye2(209, 192, 213, 197); + + if (eye1.contains(mousePos) || eye2.contains(mousePos)) { + _evilTwinShown = true; + render(); + } +} + +void CContinueSaveDialog::rightButtonUp(const Point &mousePos) { + if (_evilTwinShown) { + _evilTwinShown = false; + render(); + } +} + +void CContinueSaveDialog::keyDown(Common::KeyState keyState) { + if (keyState.keycode == Common::KEYCODE_ESCAPE) + _selectedSlot = EXIT_GAME; +} + +} // End of namespace Titanic diff --git a/engines/titanic/continue_save_dialog.h b/engines/titanic/continue_save_dialog.h new file mode 100644 index 0000000000..58c7deef00 --- /dev/null +++ b/engines/titanic/continue_save_dialog.h @@ -0,0 +1,105 @@ +/* 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_CONTINUE_SAVE_DIALOG_H +#define TITANIC_CONTINUE_SAVE_DIALOG_H + +#include "common/array.h" +#include "titanic/events.h" +#include "titanic/support/image.h" +#include "titanic/support/rect.h" +#include "titanic/support/string.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +#define EXIT_GAME -2 + +class CContinueSaveDialog : public CEventTarget { + struct SaveEntry { + int _slot; + CString _name; + SaveEntry() : _slot(0) {} + SaveEntry(int slot, const CString &name) : _slot(slot), _name(name) {} + }; +private: + Common::Array<SaveEntry> _saves; + CPetText _slotNames[5]; + int _highlightedSlot, _selectedSlot; + Point _mousePos; + bool _evilTwinShown; + bool _mouseDown; + int _restoreState, _startState; + Image _backdrop; + Image _evilTwin; + Image _restoreD, _restoreU, _restoreF; + Image _startD, _startU, _startF; +private: + /** + * Load the images + */ + void loadImages(); + + /** + * Render the dialog + */ + void render(); + + /** + * Render the buttons + */ + void renderButtons(); + + /** + * Render the slots + */ + void renderSlots(); + + /** + * Get the area to draw a slot name in + */ + Rect getSlotBounds(int index); +public: + CContinueSaveDialog(); + virtual ~CContinueSaveDialog(); + + virtual void mouseMove(const Point &mousePos); + virtual void leftButtonDown(const Point &mousePos); + virtual void leftButtonUp(const Point &mousePos); + virtual void rightButtonDown(const Point &mousePos); + virtual void rightButtonUp(const Point &mousePos); + virtual void keyDown(Common::KeyState keyState); + + /** + * Add a savegame to the list to be displayed + */ + void addSavegame(int slot, const CString &name); + + /** + * Show the dialog and wait for a slot to be selected + */ + int show(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_CONTINUE_SAVE_DIALOG_H */ diff --git a/engines/titanic/core/background.cpp b/engines/titanic/core/background.cpp new file mode 100644 index 0000000000..733dfc1cf3 --- /dev/null +++ b/engines/titanic/core/background.cpp @@ -0,0 +1,78 @@ +/* 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/core/background.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBackground, CGameObject) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(SetFrameMsg) + ON_MESSAGE(VisibleMsg) +END_MESSAGE_MAP() + +CBackground::CBackground() : CGameObject(), _startFrame(0), _endFrame(0), _fieldDC(0) { +} + +void CBackground::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_startFrame, indent); + file->writeNumberLine(_endFrame, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_fieldDC, indent); + + CGameObject::save(file, indent); +} + +void CBackground::load(SimpleFile *file) { + file->readNumber(); + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + _fieldDC = file->readNumber(); + + CGameObject::load(file); +} + +bool CBackground::StatusChangeMsg(CStatusChangeMsg *msg) { + setVisible(true); + if (_fieldDC) { + playMovie(_startFrame, _endFrame, 16); + } else { + playMovie(_startFrame, _endFrame, 0); + } + return true; +} + +bool CBackground::SetFrameMsg(CSetFrameMsg *msg) { + loadFrame(msg->_frameNumber); + return true; +} + +bool CBackground::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/background.h b/engines/titanic/core/background.h new file mode 100644 index 0000000000..b7f160db28 --- /dev/null +++ b/engines/titanic/core/background.h @@ -0,0 +1,59 @@ +/* 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_BACKGROUND_H +#define TITANIC_BACKGROUND_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CBackground : public CGameObject { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool SetFrameMsg(CSetFrameMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); +protected: + int _startFrame; + int _endFrame; + CString _string1; + CString _string2; + int _fieldDC; +public: + CLASSDEF; + CBackground(); + + /** + * 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_BACKGROUND_H */ diff --git a/engines/titanic/core/click_responder.cpp b/engines/titanic/core/click_responder.cpp new file mode 100644 index 0000000000..9a0e0de7ab --- /dev/null +++ b/engines/titanic/core/click_responder.cpp @@ -0,0 +1,56 @@ +/* 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/core/click_responder.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CClickResponder, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CClickResponder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_message, indent); + file->writeQuotedLine(_soundName, indent); + + CGameObject::save(file, indent); +} + +void CClickResponder::load(SimpleFile *file) { + file->readNumber(); + _message = file->readString(); + _soundName = file->readString(); + + CGameObject::load(file); +} + +bool CClickResponder::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_soundName.empty()) + playSound(_soundName); + if (!_message.empty()) + petDisplayMessage(_message); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/click_responder.h b/engines/titanic/core/click_responder.h new file mode 100644 index 0000000000..40f22d7906 --- /dev/null +++ b/engines/titanic/core/click_responder.h @@ -0,0 +1,51 @@ +/* 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_CLICK_RESPONDER_H +#define TITANIC_CLICK_RESPONDER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CClickResponder : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +protected: + CString _message, _soundName; +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_CLICK_RESPONDER_H */ diff --git a/engines/titanic/core/dont_save_file_item.cpp b/engines/titanic/core/dont_save_file_item.cpp new file mode 100644 index 0000000000..b8864bb2b5 --- /dev/null +++ b/engines/titanic/core/dont_save_file_item.cpp @@ -0,0 +1,37 @@ +/* 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/core/dont_save_file_item.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CDontSaveFileItem, CFileItem); + +void CDontSaveFileItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); +} + +void CDontSaveFileItem::load(SimpleFile *file) { + file->readNumber(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/dont_save_file_item.h b/engines/titanic/core/dont_save_file_item.h new file mode 100644 index 0000000000..f5ec4f791d --- /dev/null +++ b/engines/titanic/core/dont_save_file_item.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_DONT_SAVE_FILE_ITEM_H +#define TITANIC_DONT_SAVE_FILE_ITEM_H + +#include "titanic/core/file_item.h" + +namespace Titanic { + +class CDontSaveFileItem : public CFileItem { + 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_DONT_SAVE_FILE_ITEM_H */ diff --git a/engines/titanic/core/drop_target.cpp b/engines/titanic/core/drop_target.cpp new file mode 100644 index 0000000000..13a31c3f8a --- /dev/null +++ b/engines/titanic/core/drop_target.cpp @@ -0,0 +1,190 @@ +/* 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/core/drop_target.h" +#include "titanic/carry/carry.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDropTarget, CGameObject) + ON_MESSAGE(DropObjectMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(DropZoneLostObjectMsg) +END_MESSAGE_MAP() + +CDropTarget::CDropTarget() : CGameObject(), _itemFrame(0), + _itemMatchSize(0), _showItem(false), _fieldF4(0), _dropFrame(0), + _dragFrame(0), _dragCursorId(CURSOR_ARROW), _dropCursorId(CURSOR_HAND), + _clipFlags(20) { +} + +void CDropTarget::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_pos1, indent); + file->writeNumberLine(_itemFrame, indent); + file->writeQuotedLine(_itemMatchName, indent); + file->writeNumberLine(_itemMatchSize, indent); + file->writeQuotedLine(_soundName, indent); + file->writeNumberLine(_showItem, indent); + file->writeQuotedLine(_itemName, indent); + file->writeNumberLine(_fieldF4, indent); + file->writeNumberLine(_dropFrame, indent); + file->writeNumberLine(_dragFrame, indent); + file->writeQuotedLine(_clipName, indent); + file->writeNumberLine(_dragCursorId, indent); + file->writeNumberLine(_dropCursorId, indent); + file->writeNumberLine(_clipFlags, indent); + + CGameObject::save(file, indent); +} + +void CDropTarget::load(SimpleFile *file) { + file->readNumber(); + _pos1 = file->readPoint(); + _itemFrame = file->readNumber(); + _itemMatchName = file->readString(); + _itemMatchSize = file->readNumber(); + _soundName = file->readString(); + _showItem = file->readNumber(); + _itemName = file->readString(); + _fieldF4 = file->readNumber(); + _dropFrame = file->readNumber(); + _dragFrame = file->readNumber(); + _clipName = file->readString(); + _dragCursorId = (CursorId)file->readNumber(); + _dropCursorId = (CursorId)file->readNumber(); + _clipFlags = file->readNumber(); + + CGameObject::load(file); +} + +bool CDropTarget::DropObjectMsg(CDropObjectMsg *msg) { + if (!_itemName.empty()) { + if (msg->_item->getName() != _itemName) { + if (findByName(_itemName, true)) + return false; + } + } + + if (!msg->_item->isEquals(_itemMatchName, _itemMatchSize)) + return false; + + msg->_item->detach(); + msg->_item->addUnder(this); + msg->_item->setPosition(Point(_bounds.left, _bounds.top)); + + msg->_item->loadFrame(_itemFrame); + if (_showItem) + msg->_item->setVisible(false); + + CDropZoneGotObjectMsg gotMsg(this); + gotMsg.execute(msg->_item); + playSound(_soundName); + + if (_clipName.empty()) { + loadFrame(_dropFrame); + } else { + playClip(_clipName, _clipFlags); + } + + _cursorId = _dropCursorId; + return true; +} + +bool CDropTarget::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) + return false; + //msg->_dragItem = msg->_dragItem; + + CGameObject *obj = dynamic_cast<CGameObject *>(findByName(_itemName)); + if (_itemName.empty() || _fieldF4 || !obj) + return false; + + CDropZoneLostObjectMsg lostMsg; + lostMsg._object = this; + lostMsg.execute(obj); + + loadFrame(_dragFrame); + _cursorId = _dragCursorId; + + if (obj->_visible) { + msg->execute(obj); + } else { + msg->_dragItem = obj; + CPassOnDragStartMsg passMsg(msg->_mousePos, 1); + passMsg.execute(obj); + setVisible(true); + } + + return true; +} + +bool CDropTarget::EnterViewMsg(CEnterViewMsg *msg) { + if (!_itemName.empty()) { + CGameObject *obj = dynamic_cast<CGameObject *>(findByName(_itemName)); + if (!obj) { + loadFrame(_dragFrame); + _cursorId = _dragCursorId; + } else if (_clipName.empty()) { + loadFrame(_dropFrame); + } else { + playClip(_clipName, _clipFlags); + } + + _cursorId = _dropCursorId; + } + + return true; +} + +bool CDropTarget::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + _fieldF4 = !msg->_visible; + return true; +} + +bool CDropTarget::DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg) { + if (!_itemName.empty()) { + CGameObject *obj = dynamic_cast<CGameObject *>(findByName(_itemName)); + if (obj) { + if (msg->_object) { + obj->detach(); + obj->addUnder(msg->_object); + } else if (dynamic_cast<CCarry *>(obj)) { + obj->petAddToInventory(); + } + + setVisible(true); + CDropZoneLostObjectMsg lostMsg(this); + lostMsg.execute(obj); + } + + loadFrame(_dragFrame); + _cursorId = _dragCursorId; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/drop_target.h b/engines/titanic/core/drop_target.h new file mode 100644 index 0000000000..e07b640c9f --- /dev/null +++ b/engines/titanic/core/drop_target.h @@ -0,0 +1,69 @@ +/* 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_DROP_TARGET_H +#define TITANIC_DROP_TARGET_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CDropTarget : public CGameObject { + DECLARE_MESSAGE_MAP; + bool DropObjectMsg(CDropObjectMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool DropZoneLostObjectMsg(CDropZoneLostObjectMsg *msg); +protected: + Point _pos1; + int _itemFrame; + CString _itemMatchName; + int _itemMatchSize; + CString _soundName; + bool _showItem; + CString _itemName; + int _fieldF4; + int _dropFrame; + int _dragFrame; + CString _clipName; + CursorId _dragCursorId; + CursorId _dropCursorId; + uint _clipFlags; +public: + CLASSDEF; + CDropTarget(); + + /** + * 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_DROP_TARGET_H */ diff --git a/engines/titanic/core/file_item.cpp b/engines/titanic/core/file_item.cpp new file mode 100644 index 0000000000..b783c758df --- /dev/null +++ b/engines/titanic/core/file_item.cpp @@ -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. + * + */ + +#include "titanic/core/file_item.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CFileItem, CTreeItem); + +void CFileItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + CTreeItem::save(file, indent); +} + +void CFileItem::load(SimpleFile *file) { + file->readNumber(); + + CTreeItem::load(file); +} + +CString CFileItem::formFilename() const { + return ""; +} + +CString CFileItem::getFilename() const { + //dynamic_cast<CFileItem *>(getRoot())->formDataPath(); + return _filename; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/file_item.h b/engines/titanic/core/file_item.h new file mode 100644 index 0000000000..4cecee4882 --- /dev/null +++ b/engines/titanic/core/file_item.h @@ -0,0 +1,67 @@ +/* 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_FILE_ITEM_H +#define TITANIC_FILE_ITEM_H + +#include "titanic/support/string.h" +#include "titanic/core/list.h" +#include "titanic/core/tree_item.h" + +namespace Titanic { + +class CFileItem: public CTreeItem { + DECLARE_MESSAGE_MAP; +private: + CString _filename; +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); + + /** + * Returns true if the item is a file item + */ + virtual bool isFileItem() const { return true; } + + /** + * Form a filename for the file item + */ + CString formFilename() const; + + /** + * Get a string? + */ + CString getFilename() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_FILE_ITEM_H */ diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp new file mode 100644 index 0000000000..0289e78823 --- /dev/null +++ b/engines/titanic/core/game_object.cpp @@ -0,0 +1,1689 @@ +/* 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/core/game_object.h" +#include "titanic/core/mail_man.h" +#include "titanic/core/resource_key.h" +#include "titanic/core/room_item.h" +#include "titanic/npcs/true_talk_npc.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/star_control/star_control.h" +#include "titanic/support/files_manager.h" +#include "titanic/support/screen_manager.h" +#include "titanic/support/video_surface.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CGameObject, CNamedItem); + +CCreditText *CGameObject::_credits; +int CGameObject::_soundHandles[4]; + +void CGameObject::init() { + _credits = nullptr; + _soundHandles[0] = _soundHandles[1] = 0; + _soundHandles[2] = _soundHandles[3] = -1; +} + +void CGameObject::deinit() { + if (_credits) { + _credits->clear(); + delete _credits; + _credits = nullptr; + } +} + +CGameObject::CGameObject(): CNamedItem() { + _bounds = Rect(0, 0, 15, 15); + _field34 = 0; + _field38 = 0; + _field3C = 0; + _field40 = 0; + _field44 = 0xF0; + _field48 = 0xF0; + _field4C = 0xFF; + _isMail = false; + _id = 0; + _roomFlags = 0; + _visible = true; + _field60 = 0; + _cursorId = CURSOR_ARROW; + _initialFrame = 0; + _frameNumber = -1; + _text = nullptr; + _textBorder = _textBorderRight = 0; + _field9C = 0; + _surface = nullptr; + _fieldB8 = 0; +} + +CGameObject::~CGameObject() { + delete _surface; + delete _text; +} + +void CGameObject::save(SimpleFile *file, int indent) { + file->writeNumberLine(7, indent); + _movieRangeInfoList.destroyContents(); + + if (_surface) { + const CMovieRangeInfoList *rangeList = _surface->getMovieRangeInfo(); + + if (rangeList) { + for (CMovieRangeInfoList::const_iterator i = rangeList->begin(); + i != rangeList->end(); ++i) { + CMovieRangeInfo *rangeInfo = new CMovieRangeInfo(*i); + rangeInfo->_initialFrame = (i == rangeList->begin()) ? getMovieFrame() : -1; + } + } + } + + _movieRangeInfoList.save(file, indent); + _movieRangeInfoList.destroyContents(); + + file->writeNumberLine(getMovieFrame(), indent + 1); + file->writeNumberLine(_cursorId, indent + 1); + _movieClips.save(file, indent + 1); + file->writeNumberLine(_field60, indent + 1); + file->writeNumberLine(_field40, indent + 1); + file->writeQuotedLine(_resource, indent + 1); + file->writeBounds(_bounds, indent + 1); + + file->writeFloatLine(_field34, indent + 1); + file->writeFloatLine(_field38, indent + 1); + file->writeFloatLine(_field3C, indent + 1); + + file->writeNumberLine(_field44, indent + 1); + file->writeNumberLine(_field48, indent + 1); + file->writeNumberLine(_field4C, indent + 1); + file->writeNumberLine(_fieldB8, indent + 1); + file->writeNumberLine(_visible, indent + 1); + file->writeNumberLine(_isMail, indent + 1); + file->writeNumberLine(_id, indent + 1); + file->writeNumberLine(_roomFlags, indent + 1); + + if (_surface) { + _surface->_resourceKey.save(file, indent); + } else { + CResourceKey resourceKey; + resourceKey.save(file, indent); + } + file->writeNumberLine(_surface != nullptr, indent); + + CNamedItem::save(file, indent); +} + +void CGameObject::load(SimpleFile *file) { + int val = file->readNumber(); + CResourceKey resourceKey; + + switch (val) { + case 7: + _movieRangeInfoList.load(file); + _frameNumber = file->readNumber(); + // Deliberate fall-through + + case 6: + _cursorId = (CursorId)file->readNumber(); + // Deliberate fall-through + + case 5: + _movieClips.load(file); + // Deliberate fall-through + + case 4: + _field60 = file->readNumber(); + // Deliberate fall-through + + case 3: + _field40 = file->readNumber(); + // Deliberate fall-through + + case 2: + _resource = file->readString(); + // Deliberate fall-through + + case 1: + _bounds = file->readBounds(); + _field34 = file->readFloat(); + _field38 = file->readFloat(); + _field3C = file->readFloat(); + _field44 = file->readNumber(); + _field48 = file->readNumber(); + _field4C = file->readNumber(); + _fieldB8 = file->readNumber(); + _visible = file->readNumber() != 0; + _isMail = file->readNumber(); + _id = file->readNumber(); + _roomFlags = file->readNumber(); + + resourceKey.load(file); + _surface = nullptr; + val = file->readNumber(); + if (val) { + _resource = resourceKey.getString(); + } + break; + + default: + break; + } + + CNamedItem::load(file); +} + +void CGameObject::draw(CScreenManager *screenManager) { + if (!_visible) + return; + if (_credits && _credits->_objectP == this) { + if (!_credits->draw()) + CGameObject::deinit(); + + return; + } + + if (_field40) { + // If a text object is defined, handle drawing it + if (_text && _bounds.intersects(getGameManager()->_bounds)) + _text->draw(screenManager); + + return; + } else { + if (!_surface) { + if (!_resource.empty()) { + loadResource(_resource); + _resource = ""; + } + } + + if (_surface) { + _bounds.setWidth(_surface->getWidth()); + _bounds.setHeight(_surface->getHeight()); + + if (!_bounds.width() || !_bounds.height()) + return; + + if (_frameNumber >= 0) { + loadFrame(_frameNumber); + _frameNumber = -1; + } + + if (!_movieRangeInfoList.empty()) + processMoveRangeInfo(); + + if (_bounds.intersects(getGameManager()->_bounds)) { + if (_surface) { + Point destPos(_bounds.left, _bounds.top); + screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &destPos); + } + + if (_text) + _text->draw(screenManager); + } + } + } +} + +Rect CGameObject::getBounds() const { + return (_surface && _surface->hasFrame()) ? _bounds : Rect(); +} + +void CGameObject::viewChange() { + // Handle freeing the surfaces of objects when their view is left + if (_surface) { + _resource = _surface->_resourceKey.getString(); + _initialFrame = getMovieFrame(); + + delete _surface; + _surface = nullptr; + } +} + +void CGameObject::stopMovie() { + if (_surface) + _surface->stopMovie(); +} + +bool CGameObject::checkPoint(const Point &pt, bool ignore40, bool visibleOnly) { + if ((!_visible && visibleOnly) || !_bounds.contains(pt)) + return false; + + if (ignore40 || _field40) + return true; + + if (!_surface) { + if (_frameNumber == -1) + return true; + loadFrame(_frameNumber); + if (!_surface) + return true; + } + + Common::Point pixelPos = pt - _bounds; + if (_surface->_transBlitFlag) { + pixelPos.y = ((_bounds.height() - _bounds.top) / 2) * 2 - pixelPos.y; + } + + uint transColor = _surface->getTransparencyColor(); + uint pixel = _surface->getPixel(pixelPos); + return pixel != transColor; +} + +bool CGameObject::clipRect(const Rect &rect1, Rect &rect2) const { + if (!rect2.intersects(rect1)) + return false; + + rect2.clip(rect1); + return true; +} + +void CGameObject::draw(CScreenManager *screenManager, const Rect &destRect, const Rect &srcRect) { + Rect tempRect = destRect; + if (clipRect(srcRect, tempRect)) { + if (!_surface && !_resource.empty()) { + loadResource(_resource); + _resource.clear(); + } + + if (_surface) + screenManager->blitFrom(SURFACE_PRIMARY, &tempRect, _surface); + } +} + +void CGameObject::draw(CScreenManager *screenManager, const Point &destPos) { + if (!_surface && !_resource.empty()) { + loadResource(_resource); + _resource.clear(); + } + + if (_surface) { + int xSize = _surface->getWidth(); + int ySize = _surface->getHeight(); + + if (xSize > 0 && ySize > 0) { + screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &destPos); + } + } +} + +void CGameObject::draw(CScreenManager *screenManager, const Point &destPos, const Rect &srcRect) { + draw(screenManager, Rect(destPos.x, destPos.y, destPos.x + 52, destPos.y + 52), srcRect); +} + +bool CGameObject::isPet() const { + return isInstanceOf(CPetControl::_type); +} + +void CGameObject::loadResource(const CString &name) { + switch (name.fileTypeSuffix()) { + case FILETYPE_IMAGE: + loadImage(name); + break; + case FILETYPE_MOVIE: + loadMovie(name); + break; + default: + break; + } +} + +void CGameObject::loadMovie(const CString &name, bool pendingFlag) { + g_vm->_filesManager->preload(name); + + // Create the surface if it doesn't already exist + if (!_surface) { + CGameManager *gameManager = getGameManager(); + _surface = new OSVideoSurface(gameManager->setScreenManager(), nullptr); + } + + // Load the new movie resource + CResourceKey key(name); + _surface->loadResource(key); + + if (_surface->hasSurface() && !pendingFlag) { + _bounds.setWidth(_surface->getWidth()); + _bounds.setHeight(_surface->getHeight()); + } + + if (_initialFrame) + loadFrame(_initialFrame); +} + +void CGameObject::loadImage(const CString &name, bool pendingFlag) { + // Get a refernce to the game and screen managers + CGameManager *gameManager = getGameManager(); + CScreenManager *screenManager; + + if (gameManager && (screenManager = CScreenManager::setCurrent()) != nullptr) { + // Destroy the object's surface if it already had one + if (_surface) { + delete _surface; + _surface = nullptr; + } + + g_vm->_filesManager->preload(name); + + if (!name.empty()) { + _surface = new OSVideoSurface(screenManager, CResourceKey(name), pendingFlag); + } + + if (_surface && !pendingFlag) { + _bounds.right = _surface->getWidth(); + _bounds.bottom = _surface->getHeight(); + } + + // Mark the object's area as dirty, so that on the next frame rendering + // this object will be redrawn + makeDirty(); + } + + _initialFrame = 0; +} + +void CGameObject::loadFrame(int frameNumber) { + if (frameNumber != -1 && !_resource.empty()) + loadResource(_resource); + + if (_surface) + _surface->setMovieFrame(frameNumber); + + makeDirty(); +} + +void CGameObject::processMoveRangeInfo() { + for (CMovieRangeInfoList::iterator i = _movieRangeInfoList.begin(); i != _movieRangeInfoList.end(); ++i) + (*i)->process(this); + + _movieRangeInfoList.destroyContents(); +} + +void CGameObject::makeDirty(const Rect &r) { + CGameManager *gameManager = getGameManager(); + if (gameManager) + gameManager->extendBounds(r); +} + +void CGameObject::makeDirty() { + makeDirty(_bounds); +} + +bool CGameObject::isSoundActive(int handle) const { + if (handle != 0 && handle != -1) { + CGameManager *gameManager = getGameManager(); + if (gameManager) + return gameManager->_sound.isActive(handle); + } + + return false; +} + +void CGameObject::playGlobalSound(const CString &resName, int mode, bool initialMute, bool repeated, int handleIndex) { + if (handleIndex < 0 || handleIndex > 3) + return; + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return; + + // Preload the file, and stop any existing sound using the given slot + CSound &sound = gameManager->_sound; + g_vm->_filesManager->preload(resName); + if (_soundHandles[handleIndex] != -1) { + sound.stopSound(_soundHandles[handleIndex]); + _soundHandles[handleIndex] = -1; + } + + // If no new name specified, then exit + if (resName.empty()) + return; + + uint newVolume = sound._soundManager.getModeVolume(mode); + uint volume = initialMute ? 0 : newVolume; + + CProximity prox; + prox._channelVolume = volume; + prox._repeated = repeated; + + switch (handleIndex) { + case 0: + prox._channel = 6; + break; + case 1: + prox._channel = 7; + break; + case 2: + prox._channel = 8; + break; + case 3: + prox._channel = 9; + break; + default: + break; + } + + _soundHandles[handleIndex] = sound.playSound(resName, prox); + + if (_soundHandles[handleIndex]) + sound.setVolume(_soundHandles[handleIndex], newVolume, 2); +} + +void CGameObject::setSoundVolume(int handle, uint percent, uint seconds) { + if (handle != 0 && handle != -1) { + CGameManager *gameManager = getGameManager(); + if (gameManager) + return gameManager->_sound.setVolume(handle, percent, seconds); + } +} + +void CGameObject::stopGlobalSound(bool transition, int handleIndex) { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return; + CSound &sound = gameManager->_sound; + + if (handleIndex == -1) { + for (int idx = 0; idx < 4; ++idx) { + if (_soundHandles[idx] != -1) { + sound.setVolume(_soundHandles[idx], 0, transition ? 1 : 0); + sound.setCanFree(_soundHandles[idx]); + _soundHandles[idx] = -1; + } + } + } else if (handleIndex >= 0 && handleIndex <= 2 && _soundHandles[handleIndex] != -1) { + if (transition) { + // Transitioning to silent over 1 second + sound.setVolume(_soundHandles[handleIndex], 0, 1); + sleep(1000); + } + + sound.stopSound(_soundHandles[handleIndex]); + _soundHandles[handleIndex] = -1; + } + warning("CGameObject::soundFn4"); +} + +void CGameObject::setGlobalSoundVolume(int mode, uint seconds, int handleIndex) { + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return; + CSound &sound = gameManager->_sound; + + if (handleIndex == -1) { + // Iterate through calling the method for each handle + for (int idx = 0; idx < 3; ++idx) + setGlobalSoundVolume(mode, seconds, idx); + } else if (handleIndex >= 0 && handleIndex <= 3 && _soundHandles[handleIndex] != -1) { + uint newVolume = sound._soundManager.getModeVolume(mode); + sound.setVolume(_soundHandles[handleIndex], newVolume, seconds); + } +} + +void CGameObject::sound8(bool flag) const { + getGameManager()->_sound.stopChannel(flag ? 3 : 0); +} + +void CGameObject::setVisible(bool val) { + if (val != _visible) { + _visible = val; + makeDirty(); + } +} + +void CGameObject::petHighlightGlyph(int val) { + CPetControl *pet = getPetControl(); + if (pet) + pet->highlightGlyph(val); +} + +void CGameObject::petHideCursor() { + CPetControl *pet = getPetControl(); + if (pet) + pet->hideCursor(); +} + +void CGameObject::petShowCursor() { + CPetControl *pet = getPetControl(); + if (pet) + pet->showCursor(); +} + +void CGameObject::petShow() { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + gameManager->_gameState._petActive = true; + gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + gameManager->initBounds(); + } +} + +void CGameObject::petHide() { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + gameManager->_gameState._petActive = false; + gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + gameManager->initBounds(); + } +} + +void CGameObject::petSetRemoteTarget() { + CPetControl *pet = getPetControl(); + if (pet) + pet->setRemoteTarget(this); +} + +void CGameObject::playMovie(uint flags) { + _frameNumber = -1; + + if (!_surface && !_resource.empty()) { + loadResource(_resource); + _resource.clear(); + } + + CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr; + if (_surface) { + _surface->playMovie(flags, obj); + if (flags & MOVIE_GAMESTATE) + getGameManager()->_gameState.addMovie(_surface->_movie); + } +} + +void CGameObject::playMovie(int startFrame, int endFrame, uint flags) { + _frameNumber = -1; + + if (!_surface) { + if (!_resource.empty()) + loadResource(_resource); + _resource.clear(); + } + + CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr; + if (_surface) { + _surface->playMovie(startFrame, endFrame, flags, obj); + if (flags & MOVIE_GAMESTATE) + getGameManager()->_gameState.addMovie(_surface->_movie); + } +} + + +void CGameObject::playMovie(int startFrame, int endFrame, int initialFrame, uint flags) { + _frameNumber = -1; + + if (!_surface) { + if (!_resource.empty()) + loadResource(_resource); + _resource.clear(); + } + + CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr; + if (_surface) { + _surface->playMovie(startFrame, endFrame, initialFrame, flags, obj); + if (flags & MOVIE_GAMESTATE) + getGameManager()->_gameState.addMovie(_surface->_movie); + } +} + +void CGameObject::playClip(const CString &name, uint flags) { + _frameNumber = -1; + CMovieClip *clip = _movieClips.findByName(name); + if (clip) + playMovie(clip->_startFrame, clip->_endFrame, flags); +} + +void CGameObject::playClip(uint startFrame, uint endFrame) { + CMovieClip *clip = new CMovieClip("", startFrame, endFrame); + CGameManager *gameManager = getGameManager(); + CRoomItem *room = gameManager->getRoom(); + + gameManager->playClip(clip, room, room); +} + +void CGameObject::playRandomClip(const char *const *names, uint flags) { + // Count size of array + int count = 0; + for (const char *const *p = names; *p; ++p) + ++count; + + // Play clip + const char *name = names[g_vm->getRandomNumber(count - 1)]; + playClip(name, flags); +} + +void CGameObject::playCutscene(uint startFrame, uint endFrame) { + if (!_surface) { + if (!_resource.empty()) + loadResource(_resource); + _resource.clear(); + } + + if (_surface && _surface->loadIfReady() && _surface->_movie) { + disableMouse(); + _surface->_movie->playCutscene(_bounds, startFrame, endFrame); + enableMouse(); + } +} + +void CGameObject::savePosition() { + _savedPos = _bounds; +} + +void CGameObject::resetPosition() { + setPosition(_savedPos); +} + +void CGameObject::setPosition(const Point &newPos) { + makeDirty(); + _bounds.moveTo(newPos); + makeDirty(); +} + +bool CGameObject::checkStartDragging(CMouseDragStartMsg *msg) { + if (_visible && checkPoint(msg->_mousePos, msg->_handled, 1)) { + savePosition(); + msg->_dragItem = this; + return true; + } else { + return false; + } +} + +bool CGameObject::hasActiveMovie() const { + if (_surface && _surface->_movie) + return _surface->_movie->isActive(); + return false; +} + +int CGameObject::getMovieFrame() const { + if (_surface && _surface->_movie) + return _surface->_movie->getFrame(); + return _initialFrame; +} + +bool CGameObject::surfaceHasFrame() const { + return _surface ? _surface->hasFrame() : false; +} + +void CGameObject::loadSound(const CString &name) { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + g_vm->_filesManager->preload(name); + if (!name.empty()) + gameManager->_sound.loadSound(name); + } +} + +int CGameObject::playSound(const CString &name, uint volume, int val3, bool repeated) { + CProximity prox; + prox._channelVolume = volume; + prox._fieldC = val3; + prox._repeated = repeated; + return playSound(name, prox); +} + +int CGameObject::playSound(const CString &name, CProximity &prox) { + if (prox._positioningMode == POSMODE_VECTOR) { + // If the proximity doesn't have a position defined, default it to + // the position of the view to which the game object belongs + if (prox._posX == 0.0 && prox._posY == 0.0 && prox._posZ == 0.0) + findView()->getPosition(prox._posX, prox._posY, prox._posZ); + } + + CGameManager *gameManager = getGameManager(); + if (gameManager) { + g_vm->_filesManager->preload(name); + + gameManager->_sound.playSound(name, prox); + } + + return 0; +} + +int CGameObject::queueSound(const CString &name, uint priorHandle, uint volume, int val3, bool repeated) { + CProximity prox; + prox._fieldC = val3; + prox._repeated = repeated; + prox._channelVolume = volume; + prox._priorSoundHandle = priorHandle; + + return playSound(name, prox); +} + +void CGameObject::stopSound(int handle, uint seconds) { + if (handle != 0 && handle != -1) { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + if (seconds) { + gameManager->_sound.setVolume(handle, 0, seconds); + gameManager->_sound.setCanFree(handle); + } else { + gameManager->_sound.stopSound(handle); + } + } + } +} + +int CGameObject::addTimer(int endVal, uint firstDuration, uint repeatDuration) { + CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration != 0, + firstDuration, repeatDuration, this, endVal, CString()); + + getGameManager()->addTimer(timer); + return timer->_id; +} + +int CGameObject::addTimer(uint firstDuration, uint repeatDuration) { + CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration != 0, + firstDuration, repeatDuration, this, 0, CString()); + + getGameManager()->addTimer(timer); + return timer->_id; +} + +void CGameObject::stopTimer(int id) { + getGameManager()->stopTimer(id); +} + +int CGameObject::startAnimTimer(const CString &action, uint firstDuration, uint repeatDuration) { + CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration > 0, + firstDuration, repeatDuration, this, 0, action); + getGameManager()->addTimer(timer); + + return timer->_id; +} + +void CGameObject::stopAnimTimer(int id) { + getGameManager()->stopTimer(id); +} + +void CGameObject::gotoView(const CString &viewName, const CString &clipName) { + CViewItem *newView = parseView(viewName); + CGameManager *gameManager = getGameManager(); + CViewItem *oldView = gameManager ? gameManager->getView() : newView; + if (!oldView || !newView) + return; + + CMovieClip *clip = nullptr; + if (clipName.empty()) { + CLinkItem *link = oldView->findLink(newView); + if (link) + clip = link->getClip(); + } else { + clip = oldView->findNode()->findRoom()->findClip(clipName); + } + + // Change the view + gameManager->_gameState.changeView(newView, clip); +} + +CViewItem *CGameObject::parseView(const CString &viewString) { + int firstIndex = viewString.indexOf('.'); + int lastIndex = viewString.lastIndexOf('.'); + CString roomName, nodeName, viewName; + + if (firstIndex == -1) { + roomName = viewString; + } else { + roomName = viewString.left(firstIndex); + + if (lastIndex > firstIndex) { + nodeName = viewString.mid(firstIndex + 1, lastIndex - firstIndex - 1); + viewName = viewString.mid(lastIndex + 1); + } else { + nodeName = viewString.mid(firstIndex + 1); + } + } + + CGameManager *gameManager = getGameManager(); + if (!gameManager) + return nullptr; + + CRoomItem *room = gameManager->getRoom(); + CProjectItem *project = room->getRoot(); + + // Ensure we have the specified room + if (project) { + if (room->getName() != roomName) { + // Scan for the correct room + for (room = project->findFirstRoom(); room && room->getName() != roomName; + room = project->findNextRoom(room)) ; + } + } + if (!room) + return nullptr; + + // Find the designated node within the room + CNodeItem *node = static_cast<CNodeItem *>(room->findChildInstanceOf(CNodeItem::_type)); + while (node && node->getName() != nodeName) + node = static_cast<CNodeItem *>(room->findNextInstanceOf(CNodeItem::_type, node)); + if (!node) + return nullptr; + + CViewItem *view = static_cast<CViewItem *>(node->findChildInstanceOf(CViewItem::_type)); + while (view && view->getName() != viewName) + view = static_cast<CViewItem *>(node->findNextInstanceOf(CViewItem::_type, view)); + if (!view) + return nullptr; + + // Find the view, so return it + return view; +} + +CString CGameObject::getViewFullName() const { + CGameManager *gameManager = getGameManager(); + CViewItem *view = gameManager->getView(); + CNodeItem *node = view->findNode(); + CRoomItem *room = node->findRoom(); + + return CString::format("%s.%s.%s", room->getName().c_str(), + node->getName().c_str(), view->getName().c_str()); +} + +void CGameObject::sleep(uint milli) { + g_vm->_events->sleep(milli); +} + +Point CGameObject::getMousePos() const { + return getGameManager()->_gameState.getMousePos(); +} + +bool CGameObject::compareViewNameTo(const CString &name) const { + return getViewFullName().compareToIgnoreCase(name); +} + +int CGameObject::compareRoomNameTo(const CString &name) { + CRoomItem *room = getGameManager()->getRoom(); + return room->getName().compareToIgnoreCase(name); +} + +CString CGameObject::getRoomName() const { + CRoomItem *room = getRoom(); + return room ? room->getName() : CString(); +} + +CString CGameObject::getRoomNodeName() const { + CNodeItem *node = getNode(); + if (!node) + return CString(); + + CRoomItem *room = node->findRoom(); + + return CString::format("%s.%s", room->getName().c_str(), node->getName().c_str()); +} + +CString CGameObject::getFullViewName() { + CGameManager *gameManager = getGameManager(); + return gameManager ? gameManager->getFullViewName() : CString(); +} + +CGameObject *CGameObject::getMailManFirstObject() const { + CMailMan *mailMan = getMailMan(); + return mailMan ? mailMan->getFirstObject() : nullptr; +} + +CGameObject *CGameObject::getMailManNextObject(CGameObject *prior) const { + CMailMan *mailMan = getMailMan(); + return mailMan ? mailMan->getNextObject(prior) : nullptr; +} + +CGameObject *CGameObject::findMailByFlags(int mode, uint roomFlags) { + CMailMan *mailMan = getMailMan(); + if (!mailMan) + return nullptr; + + for (CGameObject *obj = mailMan->getFirstObject(); obj; + obj = mailMan->getNextObject(obj)) { + if (compareRoomFlags(mode, roomFlags, obj->_roomFlags)) + return obj; + } + + return nullptr; +} + +CGameObject *CGameObject::getNextMail(CGameObject *prior) { + CMailMan *mailMan = getMailMan(); + return mailMan ? mailMan->getNextObject(prior) : nullptr; +} + +CGameObject *CGameObject::findRoomObject(const CString &name) const { + return static_cast<CGameObject *>(findRoom()->findByName(name)); +} + +CGameObject *CGameObject::findInRoom(const CString &name) { + CRoomItem *room = getRoom(); + return room ? static_cast<CGameObject *>(room->findByName(name)) : nullptr; +} + +Found CGameObject::find(const CString &name, CGameObject **item, int findAreas) { + CGameObject *go; + *item = nullptr; + + // Scan under PET if flagged + if (findAreas & FIND_PET) { + for (go = getPetControl()->getFirstObject(); go; go = getPetControl()->getNextObject(go)) { + if (go->getName() == name) { + *item = go; + return FOUND_PET; + } + } + } + + if (findAreas & FIND_MAILMAN) { + for (go = getMailManFirstObject(); go; go = getMailManNextObject(go)) { + if (go->getName() == name) { + *item = go; + return FOUND_MAILMAN; + } + } + } + + if (findAreas & FIND_GLOBAL) { + go = static_cast<CGameObject *>(getRoot()->findByName(name)); + if (go) { + *item = go; + return FOUND_GLOBAL; + } + } + + if (findAreas & FIND_ROOM) { + go = findRoomObject(name); + if (go) { + *item = go; + return FOUND_ROOM; + } + } + + return FOUND_NONE; +} + +void CGameObject::moveToView() { + CViewItem *view = getGameManager()->getView(); + detach(); + addUnder(view); +} + +void CGameObject::moveToView(const CString &name) { + CViewItem *view = parseView(name); + detach(); + addUnder(view); +} + +void CGameObject::stateInc14() { + getGameManager()->_gameState.inc14(); +} + +int CGameObject::stateGet14() const { + return getGameManager()->_gameState._field14; +} + +void CGameObject::stateSet24() { + getGameManager()->_gameState.set24(1); +} + +int CGameObject::stateGet24() const { + return getGameManager()->_gameState.get24(); +} + +void CGameObject::stateInc38() { + getGameManager()->_gameState.inc38(); +} + +int CGameObject::stateGet38() const { + return getGameManager()->_gameState._field38; +} + +void CGameObject::quitGame() { + getGameManager()->_gameState._quitGame = true; +} + +void CGameObject::inc54() { + getGameManager()->inc54(); +} + +void CGameObject::dec54() { + getGameManager()->dec54(); +} + +void CGameObject::setMovieFrameRate(double rate) { + if (_surface) + _surface->setMovieFrameRate(rate); +} + +void CGameObject::setText(const CString &str, int border, int borderRight) { + if (!_text) + _text = new CPetText(); + _textBorder = border; + _textBorderRight = borderRight; + + _text->setText(str); + CScreenManager *screenManager = getGameManager()->setScreenManager(); + _text->scrollToTop(screenManager); +} + +void CGameObject::setTextHasBorders(bool hasBorders) { + if (!_text) + _text = new CPetText(); + + _text->setHasBorder(hasBorders); +} + +void CGameObject::setTextBounds() { + Rect rect = _bounds; + rect.grow(_textBorder); + rect.right -= _textBorderRight; + + _text->setBounds(rect); + makeDirty(); +} + +void CGameObject::setTextColor(byte r, byte g, byte b) { + if (!_text) + _text = new CPetText(); + + _text->setColor(r, g, b); +} + +void CGameObject::setTextFontNumber(int fontNumber) { + if (!_text) + _text = new CPetText(); + + _text->setFontNumber(fontNumber); +} + +int CGameObject::getTextWidth() const { + assert(_text); + return _text->getTextWidth(CScreenManager::_screenManagerPtr); +} + +CTextCursor *CGameObject::getTextCursor() const { + return CScreenManager::_screenManagerPtr->_textCursor; +} + +void CGameObject::scrollTextUp() { + if (_text) + _text->scrollUp(CScreenManager::_screenManagerPtr); +} + +void CGameObject::scrollTextDown() { + if (_text) + _text->scrollDown(CScreenManager::_screenManagerPtr); +} + +void CGameObject::lockMouse() { + CGameManager *gameMan = getGameManager(); + gameMan->lockInputHandler(); + + if (CScreenManager::_screenManagerPtr->_mouseCursor) + CScreenManager::_screenManagerPtr->_mouseCursor->hide(); +} + +void CGameObject::hideMouse() { + CScreenManager::_screenManagerPtr->_mouseCursor->hide(); +} + +void CGameObject::showMouse() { + CScreenManager::_screenManagerPtr->_mouseCursor->show(); +} + +void CGameObject::disableMouse() { + lockInputHandler(); + hideMouse(); +} + +void CGameObject::enableMouse() { + unlockInputHandler(); + showMouse(); +} + +void CGameObject::mouseLockE4() { + CScreenManager::_screenManagerPtr->_mouseCursor->lockE4(); +} + +void CGameObject::mouseUnlockE4() { + CScreenManager::_screenManagerPtr->_mouseCursor->unlockE4(); +} + +void CGameObject::mouseSaveState(int v1, int v2, int v3) { + CScreenManager::_screenManagerPtr->_mouseCursor->saveState(v1, v2, v3); +} + +void CGameObject::lockInputHandler() { + getGameManager()->lockInputHandler(); +} + +void CGameObject::unlockInputHandler() { + getGameManager()->unlockInputHandler(); +} + +void CGameObject::unlockMouse() { + if (CScreenManager::_screenManagerPtr->_mouseCursor) + CScreenManager::_screenManagerPtr->_mouseCursor->show(); + + CGameManager *gameMan = getGameManager(); + gameMan->unlockInputHandler(); +} + +void CGameObject::loadSurface() { + if (!_surface && !_resource.empty()) { + loadResource(_resource); + _resource.clear(); + } + + if (_surface) + _surface->loadIfReady(); +} + +bool CGameObject::changeView(const CString &viewName) { + return changeView(viewName, ""); +} + +bool CGameObject::changeView(const CString &viewName, const CString &clipName) { + CViewItem *newView = parseView(viewName); + CGameManager *gameManager = getGameManager(); + CViewItem *oldView = gameManager->getView(); + + if (!oldView || !newView) + return false; + + CMovieClip *clip = nullptr; + if (!clipName.empty()) { + clip = oldView->findNode()->findRoom()->findClip(clipName); + } else { + CLinkItem *link = oldView->findLink(newView); + if (link) + clip = link->getClip(); + } + + gameManager->_gameState.changeView(newView, clip); + return true; +} + +void CGameObject::dragMove(const Point &pt) { + if (_surface) { + _bounds.setWidth(_surface->getWidth()); + _bounds.setHeight(_surface->getHeight()); + } + + setPosition(Point(pt.x - _bounds.width() / 2, pt.y - _bounds.height() / 2)); +} + +CGameObject *CGameObject::getDraggingObject() const { + CTreeItem *item = getGameManager()->_dragItem; + return static_cast<CGameObject *>(item); +} + +Point CGameObject::getControid() const { + return Point(_bounds.left + _bounds.width() / 2, + _bounds.top + _bounds.height() / 2); +} + +bool CGameObject::clipExistsByStart(const CString &name, int startFrame) const { + return _movieClips.existsByStart(name, startFrame); +} + +bool CGameObject::clipExistsByEnd(const CString &name, int endFrame) const { + return _movieClips.existsByEnd(name, endFrame); +} + +void CGameObject::petClear() const { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->resetActiveNPC(); +} + +CDontSaveFileItem *CGameObject::getDontSave() const { + CProjectItem *project = getRoot(); + return project ? project->getDontSaveFileItem() : nullptr; +} + +CPetControl *CGameObject::getPetControl() const { + return static_cast<CPetControl *>(getDontSaveChild(CPetControl::_type)); +} + +CMailMan *CGameObject::getMailMan() const { + return dynamic_cast<CMailMan *>(getDontSaveChild(CMailMan::_type)); +} + +CTreeItem *CGameObject::getDontSaveChild(ClassDef *classDef) const { + CProjectItem *root = getRoot(); + if (!root) + return nullptr; + + CDontSaveFileItem *dontSave = root->getDontSaveFileItem(); + if (!dontSave) + return nullptr; + + return dontSave->findChildInstanceOf(classDef); +} + +CRoomItem *CGameObject::getHiddenRoom() const { + CProjectItem *root = getRoot(); + return root ? root->findHiddenRoom() : nullptr; +} + +CRoomItem *CGameObject::locateRoom(const CString &name) const { + if (name.empty()) + return nullptr; + + CProjectItem *project = getRoot(); + for (CRoomItem *room = project->findFirstRoom(); room; room = project->findNextRoom(room)) { + if (!room->getName().compareToIgnoreCase(name)) + return room; + } + + return nullptr; +} + +CGameObject *CGameObject::getHiddenObject(const CString &name) const { + CRoomItem *room = getHiddenRoom(); + return room ? static_cast<CGameObject *>(findUnder(room, name)) : nullptr; +} + +CTreeItem *CGameObject::findUnder(CTreeItem *parent, const CString &name) const { + if (!parent) + return nullptr; + + for (CTreeItem *item = parent->getFirstChild(); item; item = item->scan(parent)) { + if (item->getName() == name) + return item; + } + + return nullptr; +} + +CRoomItem *CGameObject::findRoomByName(const CString &name) { + CProjectItem *project = getRoot(); + for (CRoomItem *room = project->findFirstRoom(); room; room = project->findNextRoom(room)) { + if (!room->getName().compareToIgnoreCase(name)) + return room; + } + + return nullptr; +} + +CMusicRoom *CGameObject::getMusicRoom() const { + CGameManager *gameManager = getGameManager(); + return gameManager ? &gameManager->_musicRoom : nullptr; +} + +int CGameObject::getPassengerClass() const { + CGameManager *gameManager = getGameManager(); + return gameManager ? gameManager->_gameState._passengerClass : 3; +} + +int CGameObject::getPriorClass() const { + CGameManager *gameManager = getGameManager(); + return gameManager ? gameManager->_gameState._priorClass : 3; +} + +void CGameObject::setPassengerClass(int newClass) { + if (newClass >= 1 && newClass <= 4) { + // Change the passenger class + CGameManager *gameMan = getGameManager(); + gameMan->_gameState._priorClass = gameMan->_gameState._passengerClass; + gameMan->_gameState._passengerClass = newClass; + + // Setup the PET again, so the new class's PET background can take effect + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->setup(); + } +} + +void CGameObject::createCredits() { + _credits = new CCreditText(); + CScreenManager *screenManager = getGameManager()->setScreenManager(); + _credits->load(this, screenManager, _bounds); +} + +void CGameObject::fn10(int v1, int v2, int v3) { + makeDirty(); + _field44 = v1; + _field48 = v2; + _field4C = v3; +} + +void CGameObject::movieSetAudioTiming(bool flag) { + if (!_surface && !_resource.empty()) { + loadResource(_resource); + _resource.clear(); + } + + if (_surface && _surface->_movie) + _surface->_movie->_hasAudioTiming = flag; +} + +void CGameObject::movieEvent(int frameNumber) { + if (_surface) + _surface->addMovieEvent(frameNumber, this); +} + +void CGameObject::movieEvent() { + if (_surface) + _surface->addMovieEvent(-1, this); +} + +int CGameObject::getClipDuration(const CString &name, int frameRate) const { + CMovieClip *clip = _movieClips.findByName(name); + return clip ? (clip->_endFrame - clip->_startFrame) * 1000 / frameRate : 0; +} + +uint32 CGameObject::getTicksCount() { + return g_vm->_events->getTicksCount(); +} + +Common::SeekableReadStream *CGameObject::getResource(const CString &name) { + return g_vm->_filesManager->getResource(name); +} + +bool CGameObject::compareRoomFlags(int mode, uint flags1, uint flags2) { + switch (mode) { + case 1: + return CRoomFlags::compareLocation(flags1, flags2); + + case 2: + return CRoomFlags::compareClassElevator(flags1, flags2); + + case 3: + return CRoomFlags::isTitania(flags1, flags2); + + default: + return false; + } +} + +void CGameObject::setState1C(bool flag) { + getGameManager()->_gameState._field1C = flag; +} + +void CGameObject::addMail(int mailId) { + CMailMan *mailMan = getMailMan(); + if (mailMan) { + makeDirty(); + mailMan->addMail(this, mailId); + } +} + +void CGameObject::setMailId(int mailId) { + CMailMan *mailMan = getMailMan(); + if (mailMan) { + makeDirty(); + mailMan->setMailId(this, mailId); + } +} + +bool CGameObject::mailExists(int id) const { + return findMail(id) != nullptr; +} + +CGameObject *CGameObject::findMail(int id) const { + CMailMan *mailMan = getMailMan(); + return mailMan ? mailMan->findMail(id) : nullptr; +} + +void CGameObject::removeMail(int id, int v) { + CMailMan *mailMan = getMailMan(); + if (mailMan) + mailMan->removeMail(id, v); +} + +void CGameObject::resetMail() { + CMailMan *mailMan = getMailMan(); + if (mailMan) + mailMan->resetValue(); +} + +int CGameObject::getRandomNumber(int max, int *oldVal) { + if (oldVal) { + int startingVal = *oldVal; + while (*oldVal == startingVal && max > 0) + *oldVal = g_vm->getRandomNumber(max); + + return *oldVal; + } else { + return g_vm->getRandomNumber(max); + } +} + +/*------------------------------------------------------------------------*/ + +CRoomItem *CGameObject::getRoom() const { + CGameManager *gameManager = getGameManager(); + return gameManager ? gameManager->getRoom() : nullptr; +} + +CNodeItem *CGameObject::getNode() const { + CGameManager *gameManager = getGameManager(); + return gameManager ? gameManager->getNode() : nullptr; +} + +CViewItem *CGameObject::getView() const { + CGameManager *gameManager = getGameManager(); + return gameManager ? gameManager->getView() : nullptr; +} + +/*------------------------------------------------------------------------*/ + +void CGameObject::petAddToCarryParcel(CGameObject *obj) { + CPetControl *pet = getPetControl(); + if (pet) { + CGameObject *parcel = pet->getHiddenObject("CarryParcel"); + if (parcel) + parcel->moveUnder(obj); + } +} + +void CGameObject::petAddToInventory() { + CPetControl *pet = getPetControl(); + if (pet) { + makeDirty(); + pet->addToInventory(this); + } +} + +CTreeItem *CGameObject::petContainerRemove(CGameObject *obj) { + CPetControl *pet = getPetControl(); + if (!obj || !pet) + return nullptr; + if (!obj->compareRoomNameTo("CarryParcel")) + return obj; + + CGameObject *item = static_cast<CGameObject *>(pet->getLastChild()); + if (item) + item->detach(); + + pet->moveToHiddenRoom(obj); + pet->removeFromInventory(item, false, false); + + return item; +} + +bool CGameObject::petCheckNode(const CString &name) { + CPetControl *pet = getPetControl(); + return pet ? pet->checkNode(name) : false; +} + +bool CGameObject::petDismissBot(const CString &name) { + CPetControl *pet = getPetControl(); + return pet ? pet->dismissBot(name) : false; +} + +bool CGameObject::petDoorOrBellbotPresent() const { + CPetControl *pet = getPetControl(); + return pet ? pet->isDoorOrBellbotPresent() : false; +} + +void CGameObject::petDisplayMessage(int unused, const CString &msg) { + petDisplayMessage(msg); +} + +void CGameObject::petDisplayMessage(const CString &msg) { + CPetControl *pet = getPetControl(); + if (pet) + pet->displayMessage(msg); +} + +void CGameObject::petInvChange() { + CPetControl *pet = getPetControl(); + if (pet) + pet->invChange(this); +} + +void CGameObject::petLockInput() { + getPetControl()->incInputLocks(); +} + +void CGameObject::petMoveToHiddenRoom() { + CPetControl *pet = getPetControl(); + if (pet) { + makeDirty(); + pet->moveToHiddenRoom(this); + } +} + +void CGameObject::petReassignRoom(int passClassNum) { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->reassignRoom(passClassNum); +} + +void CGameObject::petSetArea(PetArea newArea) const { + CPetControl *pet = getPetControl(); + if (pet) + pet->setArea(newArea); +} + +void CGameObject::petSetRoomsWellEntry(int entryNum) { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->setRoomsWellEntry(entryNum); +} + +int CGameObject::petGetRoomsWellEntry() const { + CPetControl *petControl = getPetControl(); + return petControl ? petControl->getRoomsWellEntry() : 0; +} + +void CGameObject::petSetRooms1D4(int v) { + CPetControl *pet = getPetControl(); + if (pet) + pet->setRooms1D4(v); +} + +void CGameObject::petOnSummonBot(const CString &name, int val) { + CPetControl *pet = getPetControl(); + if (pet) + pet->summonBot(name, val); +} + +void CGameObject::petUnlockInput() { + getPetControl()->decInputLocks(); +} + +/*------------------------------------------------------------------------*/ + +CStarControl *CGameObject::getStarControl() const { + CStarControl *starControl = static_cast<CStarControl *>(getDontSaveChild(CStarControl::_type)); + if (!starControl) { + CViewItem *view = getGameManager()->getView(); + if (view) + starControl = static_cast<CStarControl *>(view->findChildInstanceOf(CStarControl::_type)); + } + + return starControl; +} + +void CGameObject::starFn1(int v) { + CStarControl *starControl = getStarControl(); + if (starControl) + starControl->fn1(v); +} + +bool CGameObject::starFn2() { + CStarControl *starControl = getStarControl(); + return starControl ? starControl->fn4() : false; +} + +/*------------------------------------------------------------------------*/ + +void CGameObject::startTalking(const CString &npcName, uint id, CViewItem *view) { + CTrueTalkNPC *npc = static_cast<CTrueTalkNPC *>(getRoot()->findByName(npcName)); + startTalking(npc, id, view); +} + +void CGameObject::startTalking(CTrueTalkNPC *npc, uint id, CViewItem *view) { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + CTrueTalkManager *talkManager = gameManager->getTalkManager(); + if (talkManager) + talkManager->start(npc, id, view); + } +} + +void CGameObject::endTalking(CTrueTalkNPC *npc, bool viewFlag, CViewItem *view) { + CPetControl *pet = getPetControl(); + if (pet) + pet->setActiveNPC(npc); + + if (viewFlag) + npc->setView(view); + + if (pet) + pet->refreshNPC(); +} + +void CGameObject::talkSetDialRegion(const CString &name, int dialNum, int regionNum) { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + CTrueTalkManager *talkManager = gameManager->getTalkManager(); + if (talkManager) { + TTnpcScript *npcScript = talkManager->getTalker(name); + if (npcScript) + npcScript->setDialRegion(dialNum, regionNum); + } + } +} + +int CGameObject::talkGetDialRegion(const CString &name, int dialNum) { + CGameManager *gameManager = getGameManager(); + if (gameManager) { + CTrueTalkManager *talkManager = gameManager->getTalkManager(); + if (talkManager) { + TTnpcScript *npcScript = talkManager->getTalker(name); + if (npcScript) + return npcScript->getDialRegion(dialNum); + } + } + + return 0; +} + +/*------------------------------------------------------------------------*/ + +uint CGameObject::getNodeChangedCtr() const { + return getGameManager()->_gameState.getNodeChangedCtr(); +} + +uint CGameObject::getNodeEnterTicks() const { + return getGameManager()->_gameState.getNodeEnterTicks(); +} + + +} // End of namespace Titanic diff --git a/engines/titanic/core/game_object.h b/engines/titanic/core/game_object.h new file mode 100644 index 0000000000..53e26b5f6b --- /dev/null +++ b/engines/titanic/core/game_object.h @@ -0,0 +1,964 @@ +/* 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_GAME_OBJECT_H +#define TITANIC_GAME_OBJECT_H + +#include "common/stream.h" +#include "titanic/support/mouse_cursor.h" +#include "titanic/support/credit_text.h" +#include "titanic/support/movie_range_info.h" +#include "titanic/sound/proximity.h" +#include "titanic/support/rect.h" +#include "titanic/support/movie_clip.h" +#include "titanic/core/named_item.h" +#include "titanic/pet_control/pet_section.h" +#include "titanic/pet_control/pet_text.h" + +namespace Titanic { + +enum Find { FIND_GLOBAL = 1, FIND_ROOM = 2, FIND_PET = 4, FIND_MAILMAN = 8 }; +enum Found { FOUND_NONE = 0, FOUND_GLOBAL = 1, FOUND_ROOM = 2, FOUND_PET = 3, FOUND_MAILMAN = 4 }; + +class CDontSaveFileItem; +class CMailMan; +class CMusicRoom; +class CRoomItem; +class CStarControl; +class CMouseDragStartMsg; +class CTrueTalkNPC; +class CVideoSurface; +class OSMovie; + +class CGameObject : public CNamedItem { + friend class OSMovie; + DECLARE_MESSAGE_MAP; +private: + static int _soundHandles[4]; +private: + /** + * Load a visual resource for the object + */ + void loadResource(const CString &name); + + /** + * Process and remove any registered movie range info + */ + void processMoveRangeInfo(); + + /** + * Merges one rect into another, and returns true if there was + * a common intersection + */ + bool clipRect(const Rect &rect1, Rect &rect2) const; +protected: + static CCreditText *_credits; +protected: + double _field34; + double _field38; + double _field3C; + int _field40; + int _field44; + int _field48; + int _field4C; + CMovieClipList _movieClips; + int _initialFrame; + CMovieRangeInfoList _movieRangeInfoList; + int _frameNumber; + CPetText *_text; + uint _textBorder; + uint _textBorderRight; + int _field9C; + Common::Point _savedPos; + CVideoSurface *_surface; + CString _resource; + int _fieldB8; +protected: + /** + * Saves the current position the object is located at + */ + void savePosition(); + + /** + * Resets the object back to the previously saved starting position + */ + void resetPosition(); + + /** + * Check for starting to drag the object + */ + bool checkStartDragging(CMouseDragStartMsg *msg); + + /** + * Goto a new view + */ + void gotoView(const CString &viewName, const CString &clipName); + + /** + * Parses a view into it's components of room, node, and view, + * and locates the designated view + */ + CViewItem * parseView(const CString &viewString); + + /** + * Loads a movie + */ + void loadMovie(const CString &name, bool pendingFlag = true); + + /** + * Loads an image + */ + void loadImage(const CString &name, bool pendingFlag = true); + + void inc54(); + void dec54(); + + /** + * Locks/hides the mouse + */ + void lockMouse(); + + /** + * Unlocks/shows the mouse + */ + void unlockMouse(); + + /** + * Hides the mouse cursor + */ + void hideMouse(); + + /** + * Shows the mouse cursor + */ + void showMouse(); + + /** + * Disable the mouse + */ + void disableMouse(); + + /** + * Enable the mouse + */ + void enableMouse(); + + void mouseLockE4(); + void mouseUnlockE4(); + + void mouseSaveState(int v1, int v2, int v3); + + /** + * Lock the input handler + */ + void lockInputHandler(); + + /** + * Unlock the input handler + */ + void unlockInputHandler(); + + /** + * Load a sound + */ + void loadSound(const CString &name); + + /** + * Plays a sound + * @param resName Filename of sound to play + * @param volume Volume level + */ + int playSound(const CString &name, uint volume = 100, int val3 = 0, bool repeated = false); + + /** + * Plays a sound + * @param resName Filename of sound to play + * @param prox Proximity object with the sound data + */ + int playSound(const CString &name, CProximity &prox); + + /** + * Queues a sound to play after a specified one finishes + * @param resName Filename of sound to play + * @param volume Volume level + */ + int queueSound(const CString &name, uint priorHandle, uint volume = 100, int val3 = 0, bool repeated = false); + + /** + * Stop a sound + * @param handle Sound handle + * @param seconds Optional number of seconds to transition sound off + */ + void stopSound(int handle, uint seconds = 0); + + /** + * Returns true if a sound with the specified handle is active + */ + bool isSoundActive(int handle) const; + + /** + * Sets the volume for a sound + * @param handle Sound handle + * @param volume Volume percentage (0 to 100) + * @param seconds Number of seconds to transition to the new volume + */ + void setSoundVolume(int handle, uint percent, uint seconds); + + /** + * Plays a sound, and saves it's handle in the global sound handles list + * @param resName Filename of sound to play + * @param mode Volume mode level + * @param initialMute If set, sound transitions in from mute over 2 seconds + * @param repeated Flag for repeating sounds + * @param handleIndex Slot 0 to 3 in the shared sound handle list to store the sound's handle + */ + void playGlobalSound(const CString &resName, int mode, bool initialMute, bool repeated, int handleIndex); + + /** + * Stops a sound saved in the global sound handle list + * @param transition If set, the sound transitions to silent before stopping + * @param handleIndex Index of sound to stop. If -1, all global sounds are stopped + */ + void stopGlobalSound(bool transition, int handleIndex); + + /** + * Updates the volume for a global sound based on the specified mode's volume + * @param mode Volume level mode + * @param seconds Number of seconds to transition to new volume + * @param handleIndex Index of global sound to update. If -1, all global sounds are updated + */ + void setGlobalSoundVolume(int mode, uint seconds, int handleIndex); + + void sound8(bool flag) const; + + /** + * Adds a timer + */ + int addTimer(int endVal, uint firstDuration, uint repeatDuration); + + /** + * Adds a timer + */ + int addTimer(uint firstDuration, uint repeatDuration = 0); + + /** + * Stops a timer + */ + void stopTimer(int id); + + /** + * Start an animation timer + */ + int startAnimTimer(const CString &action, uint firstDuration, uint repeatDuration = 0); + + /** + * Stop an animation timer + */ + void stopAnimTimer(int id); + + /** + * Causes the game to sleep for the specified time + */ + void sleep(uint milli); + + /** + * Get the current mouse cursor position + */ + Point getMousePos() const; + + /* + * Compares the current view's name in a Room.Node.View tuplet + * string form to the passed string + */ + bool compareViewNameTo(const CString &name) const; + + /** + * Compare the name of the parent room to the item to a passed string + */ + int compareRoomNameTo(const CString &name); + + /** + * Gets the first object under the system MailMan + */ + CGameObject *getMailManFirstObject() const; + + /** + * Gets the next object under the system MailMan + */ + CGameObject *getMailManNextObject(CGameObject *prior) const; + + /** + * Find mail by room flags + */ + CGameObject *findMailByFlags(int mode, uint roomFlags); + + /** + * Find next mail from a given prior one + */ + CGameObject *getNextMail(CGameObject *prior); + + /** + * Finds an object by name within the object's room + */ + CGameObject *findRoomObject(const CString &name) const; + + /** + * FInds an object under the current room + */ + CGameObject *findInRoom(const CString &name); + + /** + * Moves the object to be under the current view + */ + void moveToView(); + + /** + * Moves the object to be under the specified view + */ + void moveToView(const CString &name); + + /** + * Change the view + */ + bool changeView(const CString &viewName, const CString &clipName); + + /** + * Change the view + */ + bool changeView(const CString &viewName); + + /** + * Play an arbitrary clip + */ + void playClip(const CString &name, uint flags = 0); + + /** + * Play a clip + */ + void playClip(uint startFrame, uint endFrame); + + /** + * Play a cutscene + */ + void playCutscene(uint startFrame, uint endFrame); + + /** + * Play a clip randomly from a passed list of names + */ + void playRandomClip(const char *const *names, uint flags = 0); + + /** + * Return the current view/node/room as a single string + */ + CString getViewFullName() const; + + /** + * Returns true if a clip exists in the list with a given name + * and starting frame number + */ + bool clipExistsByStart(const CString &name, int startFrame = 0) const; + + /** + * Returns true if a clip exists in the list with a given name + * and ending frame number + */ + bool clipExistsByEnd(const CString &name, int endFrame = 0) const; + + /** + * Clear the PET display + */ + void petClear() const; + + /** + * Returns the MailMan + */ + CMailMan *getMailMan() const; + + /** + * Gets the don't save container object + */ + CDontSaveFileItem *getDontSave() const; + + /** + * Returns a child of the Dont Save area of the project of the given class + */ + CTreeItem *getDontSaveChild(ClassDef *classDef) const; + + /** + * Returns the special hidden room container + */ + CRoomItem *getHiddenRoom() const; + + /** + * Locates a room with the given name + */ + CRoomItem *locateRoom(const CString &name) const; + + /** + * Scan the specified room for an item by name + */ + CTreeItem *findUnder(CTreeItem *parent, const CString &name) const; + + /** + * Finds a room by name + */ + CRoomItem *findRoomByName(const CString &name); + + /** + * Returns the music room instance from the game manager + */ + CMusicRoom *getMusicRoom() const; + + /** + * Set's the player's passenger class + */ + void setPassengerClass(int newClass); + + /** + * Overrides whether the object's movie has audio timing + */ + void movieSetAudioTiming(bool flag); + + void fn10(int v1, int v2, int v3); + + /** + * Gets the duration of a specified clip in milliseconds + */ + int getClipDuration(const CString &name, int frameRate = 14) const; + + /** + * Returns the current system tick count + */ + uint32 getTicksCount(); + + /** + * Gets a resource from the DAT file + */ + Common::SeekableReadStream *getResource(const CString &name); + + /** + * Returns true if a mail with a specified Id exists + */ + bool mailExists(int id) const; + + /** + * Returns a specified mail, if one exists + */ + CGameObject *findMail(int id) const; + + /** + * Resets the Mail Man value + */ + void resetMail(); + + /** + * Locks the PET, disabling all input. Can be called multiple times + */ + void petLockInput(); + + /** + * Unlocks PET input + */ + void petUnlockInput(); + + /** + * Flag to quit the game + */ + void quitGame(); + + /** + * Set the frame rate for the currently loaded movie + */ + void setMovieFrameRate(double rate); + + /** + * Set up the text and borders for the object + */ + void setText(const CString &str, int border = 0, int borderRight = 0); + + /** + * Sets whether the text will use borders + */ + void setTextHasBorders(bool hasBorders); + + /** + * Sets the bounds for a previously defined text area + */ + void setTextBounds(); + + /** + * Sets the color for the object's text + */ + void setTextColor(byte r, byte g, byte b); + + /** + * Sets the font number to use for text + */ + void setTextFontNumber(int fontNumber); + + /** + * Gets the width of the text contents + */ + int getTextWidth() const; + + /** + * Returns the text cursor + */ + CTextCursor *getTextCursor() const; + + /** + * Scroll text up + */ + void scrollTextUp(); + + /** + * Scroll text down + */ + void scrollTextDown(); + + /** + * Gets a new random number + */ + int getRandomNumber(int max, int *oldVal = nullptr); +public: + Rect _bounds; + bool _isMail; + int _id; + uint _roomFlags; + int _field60; + CursorId _cursorId; + bool _visible; +public: + /** + * Initializes statics + */ + static void init(); + + /** + * Deinitializes statics + */ + static void deinit(); +public: + CLASSDEF; + CGameObject(); + ~CGameObject(); + + /** + * 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); + + /** + * Returns the clip list, if any, associated with the item + */ + virtual const CMovieClipList *getMovieClips() const { return &_movieClips; } + + /** + * Allows the item to draw itself + */ + virtual void draw(CScreenManager *screenManager); + + /** + * Gets the bounds occupied by the item + */ + virtual Rect getBounds() const; + + /** + * Called when the view changes + */ + virtual void viewChange(); + + /** + * Allows the item to draw itself + */ + void draw(CScreenManager *screenManager, const Rect &destRect, const Rect &srcRect); + + /** + * Allows the item to draw itself + */ + void draw(CScreenManager *screenManager, const Point &destPos); + + /** + * Allows the item to draw itself + */ + void draw(CScreenManager *screenManager, const Point &destPos, const Rect &srcRect); + + /** + * Returns true if the item is the PET control + */ + virtual bool isPet() const; + + /** + * Checks the passed point is validly in the object, + * with extra checking of object flags status + */ + bool checkPoint(const Point &pt, bool ignore40 = false, bool visibleOnly = false); + + /** + * Set the position of the object + */ + void setPosition(const Point &newPos); + + /** + * Get the centre of the game object's bounds + */ + Point getControid() const; + + /** + * Change the object's status + */ + void playMovie(uint flags); + + /** + * Play the movie specified in _resource + */ + void playMovie(int startFrame, int endFrame, uint flags); + + /** + * Play the movie specified in _resource + */ + void playMovie(int startFrame, int endFrame, int initialFrame, uint flags); + + /** + * Returns true if the object has a currently active movie + */ + bool hasActiveMovie() const; + + /** + * Stops any movie currently playing for the object + */ + void stopMovie(); + + /** + * Get the current movie frame + */ + int getMovieFrame() const; + + /** + * Returns the object's frame number + */ + int getFrameNumber() const { return _frameNumber; } + + /** + * Loads a frame + */ + void loadFrame(int frameNumber); + + /** + * Load the surface + */ + void loadSurface(); + + /** + * Marks the area occupied by the object as dirty, requiring re-rendering + */ + void makeDirty(); + + /** + * Marks the area in the passed rect as dirty, and requiring re-rendering + */ + void makeDirty(const Rect &r); + + /** + * Sets whether the object is visible + */ + void setVisible(bool val); + + /** + * Return the player's passenger class + */ + int getPassengerClass() const; + + /** + * Return the player's previous passenger class + */ + int getPriorClass() const; + + /** + * Sets the mail identifier for an object + */ + void setMailId(int mailId); + + /** + * Returns true if there's an attached surface which has a frame + * ready for display + */ + bool surfaceHasFrame() const; + + /** + * Finds an item in various system areas + */ + Found find(const CString &name, CGameObject **item, int findAreas); + + /** + * Returns a hidden object + */ + CGameObject *getHiddenObject(const CString &name) const; + + /** + * Sets up credits text + */ + void createCredits(); + + /** + * Support function for drag moving + */ + void dragMove(const Point &pt); + + /** + * Returns the currently dragging item (if any) if it's a game object + */ + CGameObject *getDraggingObject() const; + + bool compareRoomFlags(int mode, uint flags1, uint flags2); + + /*--- CGameManager Methods ---*/ + + /** + * Return the current room + */ + CRoomItem *getRoom() const; + + /** + * Return the current node + */ + CNodeItem *getNode() const; + + /** + * Return the current room + */ + CViewItem *getView() const; + + /** + * Get the current room name + */ + CString getRoomName() const; + + /** + * Get the current node and room in the form "room.node" + */ + CString getRoomNodeName() const; + + /** + * Adds an object to the mail list + */ + void addMail(int mailId); + + /** + * Remove an object from the mail list + */ + void removeMail(int id, int v); + + /** + * Return the full Id of the current view in a + * room.node.view tuplet form + */ + CString getFullViewName(); + + /*--- CPetControl Methods ---*/ + + /** + * Returns the PET control + */ + CPetControl *getPetControl() const; + + /** + * Moves a specified item to the carry parcel + */ + void petAddToCarryParcel(CGameObject *obj); + + /** + * Add the item to the inventory + */ + void petAddToInventory(); + + CTreeItem *petContainerRemove(CGameObject *obj); + + bool petCheckNode(const CString &name); + + /** + * Dismiss a bot + */ + bool petDismissBot(const CString &name); + + /** + * Is Doorbot or Bellbot present in the current view + */ + bool petDoorOrBellbotPresent() const; + + /** + * Display a message in the PET + */ + void petDisplayMessage(int unused, const CString &msg); + + /** + * Display a message in the PET + */ + void petDisplayMessage(const CString &msg); + + /** + * Gets the entry number used when last arriving at the well + */ + int petGetRoomsWellEntry() const; + + /** + * Hide the PET + */ + void petHide(); + + /** + * Hides the text cursor in the current section, if applicable + */ + void petHideCursor(); + + /** + * Highlights a glyph in the currently active PET section + */ + void petHighlightGlyph(int id); + + /** + * Called when the status of an item in the inventory has changed + */ + void petInvChange(); + + /** + * Moves the item from it's original position to be under the hidden room + */ + void petMoveToHiddenRoom(); + + /** + * Gives the player a new assigned room in the specified passenger class + */ + void petReassignRoom(int passClassNum); + + /** + * Sets a new area in the PET + */ + void petSetArea(PetArea newArea) const; + + /** + * Set the remote target in the PET to this object + */ + void petSetRemoteTarget(); + + /** + * Sets the entry number for arriving at the well + */ + void petSetRoomsWellEntry(int entryNum); + + void petSetRooms1D4(int v); + + + /** + * Show the PET + */ + void petShow(); + + /** + * Shows the text cursor in the current section, if applicable + */ + void petShowCursor(); + + /** + * Summon a bot + */ + void petOnSummonBot(const CString &name, int val); + + /*--- CStarControl Methods ---*/ + + /** + * Returns the star control + */ + CStarControl *getStarControl() const; + + void starFn1(int v); + bool starFn2(); + + /*--- CTrueTalkManager Methods ---*/ + + /** + * Stop a conversation with the NPC + */ + void endTalking(CTrueTalkNPC *npc, bool viewFlag, CViewItem *view = nullptr); + + /** + * Start a conversation with the NPC + */ + void startTalking(CTrueTalkNPC *npc, uint id, CViewItem *view = nullptr); + + /** + * Start a conversation with the NPC + */ + void startTalking(const CString &name, uint id, CViewItem *view = nullptr); + + /** + * Sets a dial region for a given NPC + */ + void talkSetDialRegion(const CString &name, int dialNum, int regionNum); + + /** + * Gets a dial region for a given NPC + */ + int talkGetDialRegion(const CString &name, int dialNum); + + /*--- CVideoSurface Methods ---*/ + + /** + * Signal a movie event for the given frame + */ + void movieEvent(int frameNumber); + + /** + * Signal a movie event at the end of all currently + * playing ranges + */ + void movieEvent(); + + /*--- CGameState Methods ---*/ + + void setState1C(bool flag); + void stateInc14(); + int stateGet14() const; + void stateSet24(); + int stateGet24() const; + void stateInc38(); + int stateGet38() const; + + /** + * Gets the game state node changed counter + */ + uint getNodeChangedCtr() const; + + /** + * Gets the game state node enter ticks + */ + uint getNodeEnterTicks() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_GAME_OBJECT_H */ diff --git a/engines/titanic/core/game_object_desc_item.cpp b/engines/titanic/core/game_object_desc_item.cpp new file mode 100644 index 0000000000..409334c9d7 --- /dev/null +++ b/engines/titanic/core/game_object_desc_item.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/core/game_object_desc_item.h" + +namespace Titanic { + +CGameObjectDescItem::CGameObjectDescItem(): CTreeItem() { +} + +void CGameObjectDescItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + _clipList.save(file, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + _list1.save(file, indent); + _list2.save(file, indent); + + CTreeItem::save(file, indent); +} + +void CGameObjectDescItem::load(SimpleFile *file) { + int val = file->readNumber(); + + if (val != 1) { + if (val) + _clipList.load(file); + + _string1 = file->readString(); + _string2 = file->readString(); + _list1.load(file); + _list1.load(file); + } + + CTreeItem::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/game_object_desc_item.h b/engines/titanic/core/game_object_desc_item.h new file mode 100644 index 0000000000..7bfecaf5a2 --- /dev/null +++ b/engines/titanic/core/game_object_desc_item.h @@ -0,0 +1,56 @@ +/* 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_GAME_OBJECT_DESK_ITEM_H +#define TITANIC_GAME_OBJECT_DESK_ITEM_H + +#include "titanic/support/movie_clip.h" +#include "titanic/core/tree_item.h" +#include "titanic/core/list.h" + +namespace Titanic { + +class CGameObjectDescItem : public CTreeItem { +protected: + CString _string1; + CString _string2; + List<ListItem> _list1; + List<ListItem> _list2; + CMovieClipList _clipList; +public: + CLASSDEF; + CGameObjectDescItem(); + + /** + * 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_GAME_OBJECT_DESK_ITEM_H */ diff --git a/engines/titanic/core/link_item.cpp b/engines/titanic/core/link_item.cpp new file mode 100644 index 0000000000..f77d081c61 --- /dev/null +++ b/engines/titanic/core/link_item.cpp @@ -0,0 +1,176 @@ +/* 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/core/link_item.h" +#include "titanic/core/node_item.h" +#include "titanic/core/project_item.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CLinkItem, CNamedItem); + +CLinkItem::CLinkItem() : CNamedItem() { + _roomNumber = -1; + _nodeNumber = -1; + _viewNumber = -1; + _linkMode = 0; + _cursorId = CURSOR_ARROW; + _name = "Link"; +} + +CString CLinkItem::formName() { + CViewItem *view = findView(); + CNodeItem *node = view->findNode(); + CRoomItem *room = node->findRoom(); + + CViewItem *destView = getDestView(); + CNodeItem *destNode = destView->findNode(); + CRoomItem *destRoom = destNode->findRoom(); + + switch (_linkMode) { + case 1: + return CString::format("_PANL,%d,%s,%s", node->_nodeNumber, + view->getName().c_str(), destView->getName().c_str()); + + case 2: + return CString::format("_PANR,%d,%s,%s", node->_nodeNumber, + view->getName().c_str(), destView->getName().c_str()); + + case 3: + return CString::format("_TRACK,%d,%s,%d,%s", + node->_nodeNumber, view->getName().c_str(), + destNode->_nodeNumber, destView->getName().c_str()); + + case 4: + return CString::format("_EXIT,%d,%d,%s,%d,%d,%s", + room->_roomNumber, node->_nodeNumber, view->getName().c_str(), + destRoom->_roomNumber, destNode->_nodeNumber, destView->getName().c_str()); + + default: + return getName().c_str(); + } +} + +void CLinkItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(2, indent); + file->writeQuotedLine("L", indent); + file->writeNumberLine(_cursorId, indent + 1); + file->writeNumberLine(_linkMode, indent + 1); + file->writeNumberLine(_roomNumber, indent + 1); + file->writeNumberLine(_nodeNumber, indent + 1); + file->writeNumberLine(_viewNumber, indent + 1); + + file->writeQuotedLine("Hotspot", indent + 1); + file->writeNumberLine(_bounds.left, indent + 2); + file->writeNumberLine(_bounds.top, indent + 2); + file->writeNumberLine(_bounds.right, indent + 2); + file->writeNumberLine(_bounds.bottom, indent + 2); + + CNamedItem::save(file, indent); +} + +void CLinkItem::load(SimpleFile *file) { + int val = file->readNumber(); + file->readBuffer(); + + switch (val) { + case 2: + _cursorId = (CursorId)file->readNumber(); + // Deliberate fall-through + + case 1: + _linkMode = file->readNumber(); + // Deliberate fall-through + + case 0: + _roomNumber = file->readNumber(); + _nodeNumber = file->readNumber(); + _viewNumber = file->readNumber(); + + file->readBuffer(); + _bounds.left = file->readNumber(); + _bounds.top = file->readNumber(); + _bounds.right = file->readNumber(); + _bounds.bottom = file->readNumber(); + break; + + default: + break; + } + + CNamedItem::load(file); + + if (val < 2) { + switch (_linkMode) { + case 2: + _cursorId = CURSOR_MOVE_LEFT; + break; + case 3: + _cursorId = CURSOR_MOVE_RIGHT; + break; + case 5: + _cursorId = CURSOR_MOVE_FORWARD; + break; + default: + _cursorId = CURSOR_MOVE_FORWARD2; + break; + } + } +} + +bool CLinkItem::connectsTo(CViewItem *destView) const { + CNodeItem *destNode = destView->findNode(); + CRoomItem *destRoom = destNode->findRoom(); + + return _viewNumber == destView->_viewNumber && + _nodeNumber == destNode->_nodeNumber && + _roomNumber == destRoom->_roomNumber; +} + +void CLinkItem::setDestination(int roomNumber, int nodeNumber, + int viewNumber, int linkMode) { + _roomNumber = roomNumber; + _nodeNumber = nodeNumber; + _viewNumber = viewNumber; + _linkMode = linkMode; + + _name = formName(); +} + +CViewItem *CLinkItem::getDestView() const { + return getRoot()->findView(_roomNumber, _nodeNumber, _viewNumber); +} + +CNodeItem *CLinkItem::getDestNode() const { + return getDestView()->findNode(); +} + +CRoomItem *CLinkItem::getDestRoom() const { + return getDestNode()->findRoom(); +} + +CMovieClip *CLinkItem::getClip() const { + return findRoom()->findClip(getName()); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/link_item.h b/engines/titanic/core/link_item.h new file mode 100644 index 0000000000..dd93e2a0bf --- /dev/null +++ b/engines/titanic/core/link_item.h @@ -0,0 +1,100 @@ +/* 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_LINK_ITEM_H +#define TITANIC_LINK_ITEM_H + +#include "titanic/support/mouse_cursor.h" +#include "titanic/core/named_item.h" +#include "titanic/support/movie_clip.h" + +namespace Titanic { + +class CViewItem; +class CNodeItem; +class CRoomItem; + +class CLinkItem : public CNamedItem { + DECLARE_MESSAGE_MAP; +private: + /** + * Returns a new name for the link item, based on the + * current values for it's destination + */ + CString formName(); +protected: + int _roomNumber; + int _nodeNumber; + int _viewNumber; + int _linkMode; +public: + Rect _bounds; + CursorId _cursorId; +public: + CLASSDEF; + CLinkItem(); + + /** + * 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); + + /** + * Returns true if the given item connects to another specified view + */ + virtual bool connectsTo(CViewItem *destView) const; + + /** + * Set the destination for the link item + */ + virtual void setDestination(int roomNumber, int nodeNumber, + int viewNumber, int linkMode); + + /** + * Get the destination view for the link item + */ + virtual CViewItem *getDestView() const; + + /** + * Get the destination node for the link item + */ + virtual CNodeItem *getDestNode() const; + + /** + * Get the destination view for the link item + */ + virtual CRoomItem *getDestRoom() const; + + /** + * Get the movie clip, if any, that's used when the link is used + */ + CMovieClip *getClip() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_LINK_ITEM_H */ diff --git a/engines/titanic/core/list.cpp b/engines/titanic/core/list.cpp new file mode 100644 index 0000000000..8e90e9ff40 --- /dev/null +++ b/engines/titanic/core/list.cpp @@ -0,0 +1,35 @@ +/* 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/core/list.h" + +namespace Titanic { + +void ListItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); +} + +void ListItem::load(SimpleFile *file) { + file->readNumber(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/list.h b/engines/titanic/core/list.h new file mode 100644 index 0000000000..91a74adbdc --- /dev/null +++ b/engines/titanic/core/list.h @@ -0,0 +1,164 @@ +/* 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_LIST_H +#define TITANIC_LIST_H + +#include "common/scummsys.h" +#include "common/list.h" +#include "titanic/support/simple_file.h" +#include "titanic/core/saveable_object.h" + +namespace Titanic { + +/** + * Base list item class + */ +class ListItem: public CSaveableObject { +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); +}; + +/** + * List item macro for managed pointers an item + */ +#define PTR_LIST_ITEM(T) class T##ListItem : public ListItem { \ + public: T *_item; \ + T##ListItem() : _item(nullptr) {} \ + T##ListItem(T *item) : _item(item) {} \ + virtual ~T##ListItem() { delete _item; } \ + } + +template<typename T> +class PtrListItem : public ListItem { +public: + T *_item; +public: + PtrListItem() : _item(nullptr) {} + PtrListItem(T *item) : _item(item) {} + virtual ~PtrListItem() { delete _item; } +}; + +template<typename T> +class List : public CSaveableObject, public Common::List<T *> { +public: + virtual ~List() { destroyContents(); } + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + + // Write out number of items + file->writeQuotedLine("L", indent); + file->writeNumberLine(Common::List<T *>::size(), indent); + + // Iterate through writing entries + typename Common::List<T *>::iterator i; + for (i = Common::List<T *>::begin(); i != Common::List<T *>::end(); ++i) { + ListItem *item = *i; + item->saveHeader(file, indent); + item->save(file, indent + 1); + item->saveFooter(file, indent); + } + + } + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file) { + file->readNumber(); + file->readBuffer(); + + Common::List<T *>::clear(); + uint count = file->readNumber(); + + for (uint idx = 0; idx < count; ++idx) { + // Validate the class start header + if (!file->IsClassStart()) + error("Unexpected class end"); + + // Get item's class name and use it to instantiate an item + CString className = file->readString(); + T *newItem = dynamic_cast<T *>(CSaveableObject::createInstance(className)); + if (!newItem) + error("Could not create instance of %s", className.c_str()); + + // Load the item's data and add it to the list + newItem->load(file); + Common::List<T *>::push_back(newItem); + + // Validate the class end footer + if (file->IsClassStart()) + error("Unexpected class start"); + } + } + + /** + * Clear the list and destroy any items in it + */ + void destroyContents() { + typename Common::List<T *>::iterator i; + for (i = Common::List<T *>::begin(); + i != Common::List<T *>::end(); ++i) { + CSaveableObject *obj = *i; + delete obj; + } + + Common::List<T *>::clear(); + } + + /** + * Add a new item to the list of the type the list contains + */ + T *add() { + T *item = new T(); + Common::List<T *>::push_back(item); + return item; + } + + bool contains(const T *item) const { + for (typename Common::List<T *>::const_iterator i = Common::List<T *>::begin(); + i != Common::List<T *>::end(); ++i) { + if (*i == item) + return true; + } + + return false; + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_LIST_H */ diff --git a/engines/titanic/core/mail_man.cpp b/engines/titanic/core/mail_man.cpp new file mode 100644 index 0000000000..afe13bebad --- /dev/null +++ b/engines/titanic/core/mail_man.cpp @@ -0,0 +1,81 @@ +/* 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/core/mail_man.h" + +namespace Titanic { + +void CMailMan::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CMailMan::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +CGameObject *CMailMan::getFirstObject() const { + return static_cast<CGameObject *>(getFirstChild()); +} + +CGameObject *CMailMan::getNextObject(CGameObject *prior) const { + if (!prior || prior->getParent() != this) + return nullptr; + + return static_cast<CGameObject *>(prior->getNextSibling()); +} + +void CMailMan::addMail(CGameObject *obj, int id) { + obj->detach(); + obj->addUnder(this); + setMailId(obj, id); +} + +void CMailMan::setMailId(CGameObject *obj, int id) { + obj->_id = id; + obj->_roomFlags = 0; + obj->_isMail = true; +} + +CGameObject *CMailMan::findMail(int id) const { + for (CGameObject *obj = getFirstObject(); obj; obj = getNextObject(obj)) { + if (obj->_isMail && obj->_id == id) + return obj; + } + + return nullptr; +} + +void CMailMan::removeMail(int id, int roomFlags) { + for (CGameObject *obj = getFirstObject(); obj; obj = getNextObject(obj)) { + if (obj->_isMail && obj->_id == id) { + obj->_isMail = false; + obj->_roomFlags = roomFlags; + break; + } + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/mail_man.h b/engines/titanic/core/mail_man.h new file mode 100644 index 0000000000..4c63cdfa13 --- /dev/null +++ b/engines/titanic/core/mail_man.h @@ -0,0 +1,84 @@ +/* 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_MAIL_MAN_H +#define TITANIC_MAIL_MAN_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CMailMan : public CGameObject { +public: + int _value; +public: + CLASSDEF; + CMailMan() : CGameObject(), _value(1) {} + + /** + * 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); + + /** + * 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; + + /** + * Add an object to the mail list + */ + void addMail(CGameObject *obj, int id); + + /** + * Sets the mail identifier for an object + */ + static void setMailId(CGameObject *obj, int id); + + /** + * Scan the mail list for a specified item + */ + CGameObject *findMail(int id) const; + + /** + * Remove a mail item + */ + void removeMail(int id, int v); + + void resetValue() { _value = 0; } +}; + + +} // End of namespace Titanic + +#endif /* TITANIC_MAIL_MAN_H */ diff --git a/engines/titanic/core/message_target.cpp b/engines/titanic/core/message_target.cpp new file mode 100644 index 0000000000..4815d03973 --- /dev/null +++ b/engines/titanic/core/message_target.cpp @@ -0,0 +1,50 @@ +/* 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/core/message_target.h" + +namespace Titanic { + +const MSGMAP *CMessageTarget::getMessageMap() const { + return getThisMessageMap(); +} + +const MSGMAP *CMessageTarget::getThisMessageMap() { + static const MSGMAP_ENTRY _messageEntries[] = { + { (PMSG)nullptr, nullptr } + }; + + static const MSGMAP messageMap = { nullptr, &_messageEntries[0] }; + return &messageMap; +} + +void CMessageTarget::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + CSaveableObject::save(file, indent); +} + +void CMessageTarget::load(SimpleFile *file) { + file->readNumber(); + CSaveableObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/message_target.h b/engines/titanic/core/message_target.h new file mode 100644 index 0000000000..a382b6392d --- /dev/null +++ b/engines/titanic/core/message_target.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_MESSAGE_TARGET_H +#define TITANIC_MESSAGE_TARGET_H + +#include "titanic/core/saveable_object.h" + +namespace Titanic { + +class CMessageTarget; +class CMessage; + +typedef bool (CMessageTarget::*PMSG)(CMessage *msg); + +struct MSGMAP_ENTRY { + PMSG _fn; + ClassDef *_class; +}; + +struct MSGMAP { + const MSGMAP *(* pFnGetBaseMap)(); + const MSGMAP_ENTRY *lpEntries; +}; + +#define DECLARE_MESSAGE_MAP \ +protected: \ + static const MSGMAP *getThisMessageMap(); \ + virtual const MSGMAP *getMessageMap() const + +#define BEGIN_MESSAGE_MAP(theClass, baseClass) \ + const MSGMAP *theClass::getMessageMap() const \ + { return getThisMessageMap(); } \ + const MSGMAP *theClass::getThisMessageMap() \ + { \ + typedef theClass ThisClass; \ + typedef baseClass TheBaseClass; \ + typedef bool (theClass::*FNPTR)(CMessage *msg); \ + static const MSGMAP_ENTRY _messageEntries[] = { + +#define ON_MESSAGE(msgClass) \ + { static_cast<PMSG>((FNPTR)&ThisClass::msgClass), C##msgClass::_type }, + +#define END_MESSAGE_MAP() \ + { (PMSG)nullptr, nullptr } \ + }; \ + static const MSGMAP messageMap = \ + { &TheBaseClass::getThisMessageMap, &_messageEntries[0] }; \ + return &messageMap; \ + } + +#define EMPTY_MESSAGE_MAP(theClass, baseClass) \ + const MSGMAP *theClass::getMessageMap() const \ + { return getThisMessageMap(); } \ + const MSGMAP *theClass::getThisMessageMap() \ + { \ + typedef baseClass TheBaseClass; \ + static const MSGMAP_ENTRY _messageEntries[] = { \ + { (PMSG)nullptr, nullptr } \ + }; \ + static const MSGMAP messageMap = \ + { &TheBaseClass::getThisMessageMap, &_messageEntries[0] }; \ + return &messageMap; \ + } \ + enum { DUMMY } + +class CMessageTarget: public CSaveableObject { + 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_MESSAGE_TARGET_H */ diff --git a/engines/titanic/core/multi_drop_target.cpp b/engines/titanic/core/multi_drop_target.cpp new file mode 100644 index 0000000000..b95696577f --- /dev/null +++ b/engines/titanic/core/multi_drop_target.cpp @@ -0,0 +1,64 @@ +/* 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/core/multi_drop_target.h" +#include "titanic/support/string_parser.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMultiDropTarget, CDropTarget) + ON_MESSAGE(DropObjectMsg) +END_MESSAGE_MAP() + +void CMultiDropTarget::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string5, indent); + file->writeQuotedLine(_string6, indent); + + CDropTarget::save(file, indent); +} + +void CMultiDropTarget::load(SimpleFile *file) { + file->readNumber(); + _string5 = file->readString(); + _string6 = file->readString(); + + CDropTarget::load(file); +} + +bool CMultiDropTarget::DropObjectMsg(CDropObjectMsg *msg) { + CStringParser parser1(_string5); + CStringParser parser2(_string6); + CString seperatorChars = ","; + + while (parser2.parse(_itemMatchName, seperatorChars)) { + _dropFrame = parser1.readInt(); + CDropTarget::DropObjectMsg(msg); + + parser1.skipSeperators(seperatorChars); + parser2.skipSeperators(seperatorChars); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/multi_drop_target.h b/engines/titanic/core/multi_drop_target.h new file mode 100644 index 0000000000..ab552f96e1 --- /dev/null +++ b/engines/titanic/core/multi_drop_target.h @@ -0,0 +1,53 @@ +/* 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_MULTI_DROP_TARGET_H +#define TITANIC_MULTI_DROP_TARGET_H + +#include "titanic/core/drop_target.h" + +namespace Titanic { + +class CMultiDropTarget : public CDropTarget { + DECLARE_MESSAGE_MAP; + bool DropObjectMsg(CDropObjectMsg *msg); +public: + CString _string5; + CString _string6; +public: + CLASSDEF; + CMultiDropTarget() : CDropTarget(), _string5("1,2") {} + + /** + * 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_CLICK_RESPONDER_H */ diff --git a/engines/titanic/core/named_item.cpp b/engines/titanic/core/named_item.cpp new file mode 100644 index 0000000000..9c4c28d04d --- /dev/null +++ b/engines/titanic/core/named_item.cpp @@ -0,0 +1,92 @@ +/* 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/core/named_item.h" +#include "titanic/core/node_item.h" +#include "titanic/core/room_item.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CNamedItem, CTreeItem); + +CString CNamedItem::dumpItem(int indent) const { + CString result = CTreeItem::dumpItem(indent); + result += " " + _name; + + return result; +} + +void CNamedItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + file->writeQuotedLine(_name, indent); + + CTreeItem::save(file, indent); +} + +void CNamedItem::load(SimpleFile *file) { + int val = file->readNumber(); + if (!val) + _name = file->readString(); + + CTreeItem::load(file); +} + +bool CNamedItem::isEquals(const CString &name, int maxLen) const { + if (maxLen) { + return getName().left(maxLen).compareToIgnoreCase(name) == 0; + } else { + return getName().compareToIgnoreCase(name) == 0; + } +} + +CViewItem *CNamedItem::findView() const { + for (CTreeItem *parent = getParent(); parent; parent = parent->getParent()) { + CViewItem *view = dynamic_cast<CViewItem *>(parent); + if (view) + return view; + } + + error("Couldn't find parent view"); +} + +CNodeItem *CNamedItem::findNode() const { + for (CTreeItem *parent = getParent(); parent; parent = parent->getParent()) { + CNodeItem *node = dynamic_cast<CNodeItem *>(parent); + if (node) + return node; + } + + error("Couldn't find parent node"); +} + +CRoomItem *CNamedItem::findRoom() const { + for (CTreeItem *parent = getParent(); parent; parent = parent->getParent()) { + CRoomItem *room = dynamic_cast<CRoomItem *>(parent); + if (room) + return room; + } + + error("Couldn't find parent node"); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/named_item.h b/engines/titanic/core/named_item.h new file mode 100644 index 0000000000..9ee3d490ae --- /dev/null +++ b/engines/titanic/core/named_item.h @@ -0,0 +1,84 @@ +/* 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_NAMED_ITEM_H +#define TITANIC_NAMED_ITEM_H + +#include "titanic/core/tree_item.h" + +namespace Titanic { + +class CViewItem; +class CNodeItem; +class CRoomItem; + +class CNamedItem: public CTreeItem { + DECLARE_MESSAGE_MAP; +public: + CString _name; +public: + CLASSDEF; + + /** + * Dump the item + */ + virtual CString dumpItem(int indent) const; + + /** + * 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); + + /** + * Gets the name of the item, if any + */ + virtual const CString getName() const { return _name; } + + /** + * Returns true if the item's name matches a passed name + */ + virtual bool isEquals(const CString &name, int maxLen = 0) const; + + /** + * Find a parent node for the item + */ + virtual CViewItem *findView() const; + + /** + * Find a parent node for the item + */ + virtual CNodeItem *findNode() const; + + /** + * Find a parent room item for the item + */ + virtual CRoomItem *findRoom() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_NAMED_ITEM_H */ diff --git a/engines/titanic/core/node_item.cpp b/engines/titanic/core/node_item.cpp new file mode 100644 index 0000000000..85d3f548c0 --- /dev/null +++ b/engines/titanic/core/node_item.cpp @@ -0,0 +1,63 @@ +/* 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/core/node_item.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CNodeItem, CNamedItem); + +CNodeItem::CNodeItem() : CNamedItem(), _nodeNumber(0) { +} + +void CNodeItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + file->writeQuotedLine("N", indent); + file->writeNumberLine(_nodePos.x, indent + 1); + file->writeNumberLine(_nodePos.y, indent + 1); + + file->writeQuotedLine("N", indent); + file->writeNumberLine(_nodeNumber, indent + 1); + + CNamedItem::save(file, indent); +} + +void CNodeItem::load(SimpleFile *file) { + file->readNumber(); + file->readBuffer(); + _nodePos.x = file->readNumber(); + _nodePos.y = file->readNumber(); + + file->readBuffer(); + _nodeNumber = file->readNumber(); + + CNamedItem::load(file); +} + +void CNodeItem::getPosition(double &xp, double &yp, double &zp) { + CRoomItem *room = findRoom(); + room->calcNodePosition(_nodePos, xp, yp); + zp = 0.0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/node_item.h b/engines/titanic/core/node_item.h new file mode 100644 index 0000000000..ea403ddc3a --- /dev/null +++ b/engines/titanic/core/node_item.h @@ -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. + * + */ + +#ifndef TITANIC_NODE_ITEM_H +#define TITANIC_NODE_ITEM_H + +#include "titanic/core/named_item.h" + +namespace Titanic { + +class CNodeItem : public CNamedItem { + DECLARE_MESSAGE_MAP; +public: + int _nodeNumber; + Point _nodePos; +public: + CLASSDEF; + CNodeItem(); + + /** + * 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); + + /** + * Gets the relative position of the node within the owning room + */ + void getPosition(double &xp, double &yp, double &zp); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_FILE_ITEM_H */ diff --git a/engines/titanic/core/project_item.cpp b/engines/titanic/core/project_item.cpp new file mode 100644 index 0000000000..76293233b0 --- /dev/null +++ b/engines/titanic/core/project_item.cpp @@ -0,0 +1,549 @@ +/* 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/file.h" +#include "common/savefile.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" +#include "titanic/core/dont_save_file_item.h" +#include "titanic/core/node_item.h" +#include "titanic/core/project_item.h" +#include "titanic/core/view_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +#define CURRENT_SAVEGAME_VERSION 1 +#define MAX_SAVEGAME_SLOTS 99 +#define MINIMUM_SAVEGAME_VERSION 1 + +static const char *const SAVEGAME_STR = "TNIC"; +#define SAVEGAME_STR_SIZE 4 + +EMPTY_MESSAGE_MAP(CProjectItem, CFileItem); + +void CFileListItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + file->writeQuotedLine(_name, indent); + + ListItem::save(file, indent); +} + +void CFileListItem::load(SimpleFile *file) { + file->readNumber(); + _name = file->readString(); + + ListItem::load(file); +} + +/*------------------------------------------------------------------------*/ + +CProjectItem::CProjectItem() : _nextRoomNumber(0), _nextMessageNumber(0), + _nextObjectNumber(0), _gameManager(nullptr) { +} + +void CProjectItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(6, indent); + file->writeQuotedLine("Next Avail. Object Number", indent); + file->writeNumberLine(_nextObjectNumber, indent); + file->writeQuotedLine("Next Avail. Message Number", indent); + file->writeNumberLine(_nextMessageNumber, indent); + + file->writeQuotedLine("", indent); + _files.save(file, indent); + + file->writeQuotedLine("Next Avail. Room Number", indent); + file->writeNumberLine(_nextRoomNumber, indent); + + CTreeItem::save(file, indent); +} + +void CProjectItem::buildFilesList() { + _files.destroyContents(); + + CTreeItem *treeItem = getFirstChild(); + while (treeItem) { + if (treeItem->isFileItem()) { + CString name = static_cast<CFileItem *>(treeItem)->getFilename(); + _files.add()->_name = name; + } + + treeItem = getNextSibling(); + } +} + +void CProjectItem::load(SimpleFile *file) { + int val = file->readNumber(); + _files.destroyContents(); + int count; + + switch (val) { + case 1: + file->readBuffer(); + _nextRoomNumber = file->readNumber(); + // Deliberate fall-through + + case 0: + // Load the list of files + count = file->readNumber(); + for (int idx = 0; idx < count; ++idx) { + CString name = file->readString(); + _files.add()->_name = name; + } + break; + + case 6: + file->readBuffer(); + _nextObjectNumber = file->readNumber(); + // Deliberate fall-through + + case 5: + file->readBuffer(); + _nextMessageNumber = file->readNumber(); + // Deliberate fall-through + + case 4: + file->readBuffer(); + // Deliberate fall-through + + case 2: + case 3: + _files.load(file); + file->readBuffer(); + _nextRoomNumber = file->readNumber(); + break; + + default: + break; + } + + CTreeItem::load(file); +} + +CGameManager *CProjectItem::getGameManager() const { + return _gameManager; +} + +void CProjectItem::setGameManager(CGameManager *gameManager) { + if (!_gameManager) + _gameManager = gameManager; +} + +void CProjectItem::resetGameManager() { + _gameManager = nullptr; +} + +void CProjectItem::loadGame(int slotId) { + CompressedFile file; + + // Clear any existing project contents and call preload code + clear(); + preLoad(); + + // Open either an existing savegame slot or the new game template + if (slotId >= 0) { + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( + g_vm->generateSaveName(slotId)); + file.open(saveFile); + } else { + Common::File *newFile = new Common::File(); + if (!newFile->open("newgame.st")) + error("Could not open newgame.st"); + file.open(newFile); + } + + // Load the savegame header in + TitanicSavegameHeader header; + readSavegameHeader(&file, header); + delete header._thumbnail; + + // Load the contents in + CProjectItem *newProject = loadData(&file); + file.IsClassStart(); + getGameManager()->load(&file); + + file.close(); + + // Clear existing project + clear(); + + // Detach each item under the loaded project, and re-attach them + // to the existing project instance (this) + CTreeItem *item; + while ((item = newProject->getFirstChild()) != nullptr) { + item->detach(); + item->addUnder(this); + } + + // Loaded project instance is no longer needed + newProject->destroyAll(); + + // Post-load processing + postLoad(); +} + +void CProjectItem::saveGame(int slotId, const CString &desc) { + CompressedFile file; + Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving( + g_vm->generateSaveName(slotId), false); + file.open(saveFile); + + // Signal the game is being saved + preSave(); + + // Write out the savegame header + TitanicSavegameHeader header; + header._saveName = desc; + writeSavegameHeader(&file, header); + + // Save the contents out + saveData(&file, this); + + // Save the game manager data + _gameManager->save(&file); + + // Close the file and signal that the saving has finished + file.close(); + postSave(); +} + +void CProjectItem::clear() { + CTreeItem *item; + while ((item = getFirstChild()) != nullptr) + item->destroyAll(); +} + +CProjectItem *CProjectItem::loadData(SimpleFile *file) { + if (!file->IsClassStart()) + return nullptr; + + CProjectItem *root = nullptr; + CTreeItem *parent = nullptr; + CTreeItem *item = nullptr; + + do { + CString entryString = file->readString(); + + if (entryString == "ALONG") { + // Move along, nothing needed + } else if (entryString == "UP") { + // Move up + if (parent == nullptr || + (parent = parent->getParent()) == nullptr) + break; + } else if (entryString == "DOWN") { + // Move down + if (parent == nullptr) + parent = item; + else + parent = parent->getLastChild(); + } else { + // Create new class instance + item = dynamic_cast<CTreeItem *>(CSaveableObject::createInstance(entryString)); + assert(item); + + if (root) { + // Already created root project + item->addUnder(parent); + } else { + root = dynamic_cast<CProjectItem *>(item); + assert(root); + root->_filename = _filename; + } + + // Load the data for the item + item->load(file); + } + + file->IsClassStart(); + } while (file->IsClassStart()); + + return root; +} + +void CProjectItem::saveData(SimpleFile *file, CTreeItem *item) const { + while (item) { + item->saveHeader(file, 0); + item->save(file, 1); + item->saveFooter(file, 0); + + CTreeItem *child = item->getFirstChild(); + if (child) { + file->write("\n{\n", 3); + file->writeQuotedString("DOWN"); + file->write("\n}\n", 3); + saveData(file, child); + file->write("\n{\n", 3); + file->writeQuotedString("UP"); + } else { + file->write("\n{\n", 3); + file->writeQuotedString("ALONG"); + } + + file->write("\n}\n", 3); + item = item->getNextSibling(); + } +} + +void CProjectItem::preLoad() { + if (_gameManager) + _gameManager->preLoad(); +} + +void CProjectItem::postLoad() { + CGameManager *gameManager = getGameManager(); + if (gameManager) + gameManager->postLoad(this); + + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->postLoad(); +} + +void CProjectItem::preSave() { + if (_gameManager) + _gameManager->preSave(this); +} + +void CProjectItem::postSave() { + if (_gameManager) + _gameManager->postSave(); +} + +CPetControl *CProjectItem::getPetControl() const { + CDontSaveFileItem *fileItem = getDontSaveFileItem(); + CTreeItem *treeItem; + + if (!fileItem || (treeItem = fileItem->getLastChild()) == nullptr) + return nullptr; + + while (treeItem) { + CPetControl *petControl = dynamic_cast<CPetControl *>(treeItem); + if (petControl) + return petControl; + + treeItem = treeItem->getPriorSibling(); + } + + return nullptr; +} + +CRoomItem *CProjectItem::findFirstRoom() const { + return dynamic_cast<CRoomItem *>(findChildInstance(CRoomItem::_type)); +} + +CTreeItem *CProjectItem::findChildInstance(ClassDef *classDef) const { + CTreeItem *treeItem = getFirstChild(); + if (treeItem == nullptr) + return nullptr; + + do { + CTreeItem *childItem = treeItem->getFirstChild(); + if (childItem) { + do { + if (childItem->isInstanceOf(classDef)) + return childItem; + } while ((childItem = childItem->getNextSibling()) != nullptr); + } + } while ((treeItem = treeItem->getNextSibling()) != nullptr); + + return nullptr; +} + +CRoomItem *CProjectItem::findNextRoom(CRoomItem *priorRoom) const { + return dynamic_cast<CRoomItem *>(findSiblingInstanceOf(CRoomItem::_type, priorRoom)); +} + +CTreeItem *CProjectItem::findSiblingInstanceOf(ClassDef *classDef, CTreeItem *startItem) const { + CTreeItem *treeItem = startItem->getParent()->getNextSibling(); + if (treeItem == nullptr) + return nullptr; + + return findChildInstance(classDef); +} + +CDontSaveFileItem *CProjectItem::getDontSaveFileItem() const { + for (CTreeItem *treeItem = getFirstChild(); treeItem; treeItem = treeItem->getNextSibling()) { + if (treeItem->isInstanceOf(CDontSaveFileItem::_type)) + return dynamic_cast<CDontSaveFileItem *>(treeItem); + } + + return nullptr; +} + +CRoomItem *CProjectItem::findHiddenRoom() { + return dynamic_cast<CRoomItem *>(findByName("HiddenRoom")); +} + +CViewItem *CProjectItem::findView(int roomNumber, int nodeNumber, int viewNumber) { + CTreeItem *treeItem = getFirstChild(); + CRoomItem *roomItem = nullptr; + + // Scan for the specified room + if (treeItem) { + do { + CTreeItem *childItem = treeItem->getFirstChild(); + CRoomItem *rItem = dynamic_cast<CRoomItem *>(childItem); + if (rItem && rItem->_roomNumber == roomNumber) { + roomItem = rItem; + break; + } + } while ((treeItem = treeItem->getNextSibling()) != nullptr); + } + if (!roomItem) + return nullptr; + + // Scan for the specified node within the room + CNodeItem *nodeItem = nullptr; + + CNodeItem *nItem = dynamic_cast<CNodeItem *>( + roomItem->findChildInstanceOf(CNodeItem::_type)); + for (; nItem && !nodeItem; nItem = dynamic_cast<CNodeItem *>( + findNextInstanceOf(CNodeItem::_type, nItem))) { + if (nItem->_nodeNumber == nodeNumber) + nodeItem = nItem; + } + if (!nodeItem) + return nullptr; + + // Scan for the specified view within the node + CViewItem *viewItem = dynamic_cast<CViewItem *>( + nodeItem->findChildInstanceOf(CViewItem::_type)); + for (; viewItem; viewItem = dynamic_cast<CViewItem *>( + findNextInstanceOf(CViewItem::_type, viewItem))) { + if (viewItem->_viewNumber == viewNumber) + return viewItem; + } + + return nullptr; +} + +SaveStateList CProjectItem::getSavegameList(const Common::String &target) { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.0??", target.c_str()); + TitanicSavegameHeader header; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + const char *ext = strrchr(file->c_str(), '.'); + int slot = ext ? atoi(ext + 1) : -1; + + if (slot >= 0 && slot < MAX_SAVEGAME_SLOTS) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + SimpleFile f; + f.open(in); + if (!readSavegameHeader(&f, header)) + continue; + + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + header._thumbnail->free(); + delete header._thumbnail; + delete in; + } + } + } + + return saveList; +} + +bool CProjectItem::readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = nullptr; + + // Validate the header Id + file->unsafeRead(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) { + file->seek(-SAVEGAME_STR_SIZE, SEEK_CUR); + header._saveName = "Unnamed"; + return true; + } + + header._version = file->readByte(); + if (header._version < MINIMUM_SAVEGAME_VERSION || header._version > CURRENT_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)file->readByte()) != '\0') header._saveName += ch; + + // Get the thumbnail + header._thumbnail = Graphics::loadThumbnail(*file); + if (!header._thumbnail) + return false; + + // Read in save date/time + header._year = file->readUint16LE(); + header._month = file->readUint16LE(); + header._day = file->readUint16LE(); + header._hour = file->readUint16LE(); + header._minute = file->readUint16LE(); + header._totalFrames = file->readUint32LE(); + + return true; +} + +void CProjectItem::writeSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header) { + // Write out a savegame header + file->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + file->writeByte(CURRENT_SAVEGAME_VERSION); + + // Write savegame name + file->write(header._saveName.c_str(), header._saveName.size()); + file->writeByte('\0'); + + // Create a thumbnail of the screen and save it out + Graphics::Surface *thumb = createThumbnail(); + Graphics::saveThumbnail(*file, *thumb); + thumb->free(); + delete thumb; + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + file->writeUint16LE(td.tm_year + 1900); + file->writeUint16LE(td.tm_mon + 1); + file->writeUint16LE(td.tm_mday); + file->writeUint16LE(td.tm_hour); + file->writeUint16LE(td.tm_min); + file->writeUint32LE(g_vm->_events->getFrameCounter()); +} + +Graphics::Surface *CProjectItem::createThumbnail() { + Graphics::Surface *thumb = new Graphics::Surface(); + + ::createThumbnailFromScreen(thumb); + return thumb; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/project_item.h b/engines/titanic/core/project_item.h new file mode 100644 index 0000000000..473ffd9556 --- /dev/null +++ b/engines/titanic/core/project_item.h @@ -0,0 +1,234 @@ +/* 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_PROJECT_ITEM_H +#define TITANIC_PROJECT_ITEM_H + +#include "common/scummsys.h" +#include "common/str.h" +#include "engines/savestate.h" +#include "graphics/surface.h" +#include "titanic/support/simple_file.h" +#include "titanic/core/dont_save_file_item.h" +#include "titanic/core/file_item.h" +#include "titanic/core/list.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +struct TitanicSavegameHeader { + uint8 _version; + CString _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + + +class CGameManager; +class CPetControl; +class CViewItem; + +/** + * File list item + */ +class CFileListItem : public ListItem { +public: + CString _name; +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); +}; + +/** + * Filename list + */ +class CFileList: public List<CFileListItem> { +}; + +class CProjectItem : public CFileItem { + DECLARE_MESSAGE_MAP; +private: + CString _filename; + CFileList _files; + int _nextRoomNumber; + int _nextMessageNumber; + int _nextObjectNumber; + CGameManager *_gameManager; + + /** + * Called during save, iterates through the children to do some stuff + */ + void buildFilesList(); + + /** + * Called at the beginning of loading a game + */ + void preLoad(); + + /** + * Does post-loading processing + */ + void postLoad(); + + /** + * Called when a game is about to be saved + */ + void preSave(); + + /** + * Called when a game has finished being saved + */ + void postSave(); + + /** + * Finds the first child instance of a given class type + */ + CTreeItem *findChildInstance(ClassDef *classDef) const; + + /** + * Finds the next sibling occurance of a given class type + */ + CTreeItem *findSiblingInstanceOf(ClassDef *classDef, CTreeItem *startItem) const; +private: + /** + * Load project data from the passed file + */ + CProjectItem *loadData(SimpleFile *file); + + /** + * Save project data to the passed file + */ + void saveData(SimpleFile *file, CTreeItem *item) const; + + /** + * Creates a thumbnail for the current on-screen contents + */ + static Graphics::Surface *createThumbnail(); +public: + /** + * Load a list of savegames + */ + static SaveStateList getSavegameList(const Common::String &target); + + /** + * Write out the header information for a savegame + */ + static void writeSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header); + + /** + * Read in the header information for a savegame + */ + static bool readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header); +public: + CLASSDEF; + CProjectItem(); + + /** + * 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); + + /** + * Get the game manager for the project + */ + virtual CGameManager *getGameManager() const; + + /** + * Sets the game manager for the project, if not already set + */ + void setGameManager(CGameManager *gameManager); + + /** + * Get a reference to the PET control + */ + CPetControl *getPetControl() const; + + /** + * Resets the game manager field + */ + void resetGameManager(); + + /** + * Load the entire project data for a given slot Id + */ + void loadGame(int slotId); + + /** + * Save the entire project data to a given savegame slot + */ + void saveGame(int slotId, const CString &desc); + + /** + * Clear any currently loaded project + */ + void clear(); + + /** + * Set the proejct's name + */ + void setFilename(const CString &name) { _filename = name; } + + /** + * Returns a reference to the first room item in the project + */ + CRoomItem *findFirstRoom() const; + + /** + * Returns a reference to the next room following the specified room + */ + CRoomItem *findNextRoom(CRoomItem *priorRoom) const; + + /** + * Returns the don't save file item, if it exists in the project + */ + CDontSaveFileItem *getDontSaveFileItem() const; + + /** + * Finds the hidden room node of the project + */ + CRoomItem *findHiddenRoom(); + + /** + * Finds a view + */ + CViewItem *findView(int roomNumber, int nodeNumber, int viewNumber); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PROJECT_ITEM_H */ diff --git a/engines/titanic/core/resource_key.cpp b/engines/titanic/core/resource_key.cpp new file mode 100644 index 0000000000..3b390af2d4 --- /dev/null +++ b/engines/titanic/core/resource_key.cpp @@ -0,0 +1,89 @@ +/* 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/file.h" +#include "titanic/titanic.h" +#include "titanic/support/simple_file.h" +#include "titanic/core/resource_key.h" + +namespace Titanic { + +void CResourceKey::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine("Resource Key...", indent); + file->writeQuotedLine(_key, indent); + + CSaveableObject::save(file, indent); +} + +void CResourceKey::load(SimpleFile *file) { + int val = file->readNumber(); + + if (val == 0 || val == 1) { + file->readBuffer(); + CString str = file->readString(); + setValue(str); + } + + CSaveableObject::load(file); +} + +void CResourceKey::setValue(const CString &name) { + CString nameStr = name; + nameStr.toLowercase(); + _key = nameStr; + + _value = nameStr; + int idx = _value.lastIndexOf('\\'); + if (idx >= 0) + _value = _value.mid(idx + 1); +} + +CString CResourceKey::exists() const { + CString name = _key; + + // Check for a resource being specified within an ST container + int idx = name.indexOf('#'); + if (idx >= 0) { + name = name.left(idx); + name += ".st"; + } + + // The original did tests for the file in the different + // asset paths, which aren't needed in ScummVM + Common::File f; + return f.exists(name) ? name : CString(); +} + +bool CResourceKey::scanForFile() const { + return g_vm->_filesManager->scanForFile(_value); +} + +FileType CResourceKey::fileTypeSuffix() const { + return _value.fileTypeSuffix(); +} + +ImageType CResourceKey::imageTypeSuffix() const { + return _value.imageTypeSuffix(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/resource_key.h b/engines/titanic/core/resource_key.h new file mode 100644 index 0000000000..27b23ed1e7 --- /dev/null +++ b/engines/titanic/core/resource_key.h @@ -0,0 +1,81 @@ +/* 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_RESOURCE_KEY_H +#define TITANIC_RESOURCE_KEY_H + +#include "titanic/support/string.h" +#include "titanic/core/saveable_object.h" + +namespace Titanic { + +class CResourceKey: public CSaveableObject { +private: + CString _key; + CString _value; + + void setValue(const CString &name); +public: + CLASSDEF; + CResourceKey() {} + CResourceKey(const CString &name) { setValue(name); } + + /** + * 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); + + /** + * Return the key + */ + const CString &getString() const { return _key; } + + /** + * Checks whether a file for the given key exists, + * and returns it's filename if it does + */ + CString exists() const; + + /** + * Scans for a file with a matching name + */ + bool scanForFile() const; + + /** + * Returns the type of the resource based on it's extension + */ + FileType fileTypeSuffix() const; + + /** + * Returns the type of the resource based on it's extension + */ + ImageType imageTypeSuffix() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_RESOURCE_KEY_H */ diff --git a/engines/titanic/core/room_item.cpp b/engines/titanic/core/room_item.cpp new file mode 100644 index 0000000000..541a8e1a9e --- /dev/null +++ b/engines/titanic/core/room_item.cpp @@ -0,0 +1,198 @@ +/* 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/core/room_item.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CRoomItem, CNamedItem); + +CRoomItem::CRoomItem() : CNamedItem(), _roomNumber(0), + _roomDimensionX(0.0), _roomDimensionY(0.0) { +} + +void CRoomItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(3, indent); + file->writeQuotedLine("Exit Movies", indent); + _exitMovieKey.save(file, indent); + + file->writeQuotedLine("Room dimensions x 1000", indent); + file->writeNumberLine(_roomDimensionX * 1000.0, indent + 1); + file->writeNumberLine(_roomDimensionY * 1000.0, indent + 1); + + file->writeQuotedLine("Transition Movie", indent); + _transitionMovieKey.save(file, indent); + + file->writeQuotedLine("Movie Clip list", indent); + _clipList.save(file, indent + 1); + + file->writeQuotedLine("Room Rect", indent); + file->writeNumberLine(_roomRect.left, indent + 1); + file->writeNumberLine(_roomRect.top, indent + 1); + file->writeNumberLine(_roomRect.right, indent + 1); + file->writeNumberLine(_roomRect.bottom, indent + 1); + + file->writeQuotedLine("Room Number", indent); + file->writeNumberLine(_roomNumber, indent); + + CNamedItem::save(file, indent); +} + +void CRoomItem::load(SimpleFile *file) { + int val = file->readNumber(); + + switch (val) { + case 3: + // Read exit movie + file->readBuffer(); + _exitMovieKey.load(file); + // Deliberate fall-through + + case 2: + // Read room dimensions + file->readBuffer(); + _roomDimensionX = (double)file->readNumber() / 1000.0; + _roomDimensionY = (double)file->readNumber() / 1000.0; + // Deliberate fall-through + + case 1: + // Read transition movie key and clip list + file->readBuffer(); + _transitionMovieKey.load(file); + + file->readBuffer(); + _clipList.load(file); + postLoad(); + // Deliberate fall-through + + case 0: + // Read room rect + file->readBuffer(); + _roomRect.left = file->readNumber(); + _roomRect.top = file->readNumber(); + _roomRect.right = file->readNumber(); + _roomRect.bottom = file->readNumber(); + file->readBuffer(); + _roomNumber = file->readNumber(); + break; + + default: + break; + } + + CNamedItem::load(file); +} + +void CRoomItem::postLoad() { + if (!_exitMovieKey.exists().empty()) + return; + + CString name = _transitionMovieKey.exists(); + if (name.right(7) == "nav.avi") { + _exitMovieKey = CResourceKey(name.left(name.size() - 7) + "exit.avi"); + } +} + +void CRoomItem::calcNodePosition(const Point &nodePos, double &xVal, double &yVal) const { + xVal = yVal = 0.0; + + if (_roomDimensionX >= 0.0 && _roomDimensionY >= 0.0) { + xVal = _roomRect.width() / _roomDimensionX; + yVal = _roomRect.height() / _roomDimensionY; + + xVal = (nodePos.x - _roomRect.left) / xVal; + yVal = (nodePos.y - _roomRect.top) / yVal; + } +} + +int CRoomItem::getScriptId() const { + CString name = getName(); + if (name == "1stClassLobby") + return 130; + else if (name == "1stClassRestaurant") + return 132; + else if (name == "1stClassState") + return 131; + else if (name == "2ndClassLobby") + return 128; + else if (name == "Bar") + return 112; + else if (name == "BottomOfWell") + return 108; + else if (name == "Bridge") + return 121; + else if (name == "Dome") + return 122; + else if (name == "Home") + return 100; + else if (name == "Lift") + return 103; + else if (name == "MusicRoom") + return 117; + else if (name == "MusicRoomLobby") + return 118; + else if (name == "ParrotLobby") + return 111; + else if (name == "Pellerator") + return 104; + else if (name == "PromenadeDeck") + return 114; + else if (name == "SculptureChamber") + return 116; + else if (name == "secClassState") + return 129; + else if (name == "ServiceElevator") + return 102; + else if (name == "SGTLeisure") + return 125; + else if (name == "SGTLittleLift") + return 105; + else if (name == "SgtLobby") + return 124; + else if (name == "SGTState") + return 126; + else if (name == "Titania") + return 123; + else if (name == "TopOfWell") + return 107; + else if (name == "EmbLobby" || name == "MoonEmbLobby") + return 110; + else if (name == "CreatorsChamber" || name == "CreatorsChamberOn") + return 113; + else if (name == "Arboretum" || name == "FrozenArboretum") + return 115; + else if (name == "BilgeRoom" || name == "BilgeRoomWith") + return 101; + + return 0; +} + +CResourceKey CRoomItem::getTransitionMovieKey() { + _transitionMovieKey.scanForFile(); + return _transitionMovieKey; +} + +CResourceKey CRoomItem::getExitMovieKey() { + return _exitMovieKey; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/room_item.h b/engines/titanic/core/room_item.h new file mode 100644 index 0000000000..cb343a15d2 --- /dev/null +++ b/engines/titanic/core/room_item.h @@ -0,0 +1,84 @@ +/* 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_ROOM_ITEM_H +#define TITANIC_ROOM_ITEM_H + +#include "titanic/support/rect.h" +#include "titanic/core/list.h" +#include "titanic/support/movie_clip.h" +#include "titanic/core/named_item.h" +#include "titanic/core/resource_key.h" + +namespace Titanic { + +class CRoomItem : public CNamedItem { + DECLARE_MESSAGE_MAP; +private: + /** + * Handles post-load processing + */ + void postLoad(); +public: + Rect _roomRect; + CMovieClipList _clipList; + int _roomNumber; + CResourceKey _transitionMovieKey; + CResourceKey _exitMovieKey; + double _roomDimensionX, _roomDimensionY; +public: + CLASSDEF; + CRoomItem(); + + /** + * 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); + + /** + * Return a movie clip for the room by name + */ + CMovieClip *findClip(const CString &name) { return _clipList.findByName(name); } + + /** + * Calculates the positioning of a node within the overall room + */ + void calcNodePosition(const Point &nodePos, double &xVal, double &yVal) const; + + /** + * Get the TrueTalk script Id associated with the room + */ + int getScriptId() const; + + CResourceKey getTransitionMovieKey(); + + CResourceKey getExitMovieKey(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_ROOM_ITEM_H */ diff --git a/engines/titanic/core/saveable_object.cpp b/engines/titanic/core/saveable_object.cpp new file mode 100644 index 0000000000..eee71cfc43 --- /dev/null +++ b/engines/titanic/core/saveable_object.cpp @@ -0,0 +1,1648 @@ +/* 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/carry/arm.h" +#include "titanic/carry/auditory_centre.h" +#include "titanic/carry/bowl_ear.h" +#include "titanic/carry/brain.h" +#include "titanic/carry/bridge_piece.h" +#include "titanic/carry/carry.h" +#include "titanic/carry/carry_parrot.h" +#include "titanic/carry/central_core.h" +#include "titanic/carry/chicken.h" +#include "titanic/carry/crushed_tv.h" +#include "titanic/carry/eye.h" +#include "titanic/carry/feathers.h" +#include "titanic/carry/fruit.h" +#include "titanic/carry/glass.h" +#include "titanic/carry/hammer.h" +#include "titanic/carry/head_piece.h" +#include "titanic/carry/hose.h" +#include "titanic/carry/hose_end.h" +#include "titanic/carry/key.h" +#include "titanic/carry/liftbot_head.h" +#include "titanic/carry/long_stick.h" +#include "titanic/carry/magazine.h" +#include "titanic/carry/maitred_left_arm.h" +#include "titanic/carry/maitred_right_arm.h" +#include "titanic/carry/mouth.h" +#include "titanic/carry/napkin.h" +#include "titanic/carry/nose.h" +#include "titanic/carry/note.h" +#include "titanic/carry/parcel.h" +#include "titanic/carry/perch.h" +#include "titanic/carry/phonograph_cylinder.h" +#include "titanic/carry/phonograph_ear.h" +#include "titanic/carry/photograph.h" +#include "titanic/carry/plug_in.h" +#include "titanic/carry/speech_centre.h" +#include "titanic/carry/sweets.h" +#include "titanic/carry/vision_centre.h" + +#include "titanic/core/saveable_object.h" +#include "titanic/core/background.h" +#include "titanic/core/click_responder.h" +#include "titanic/core/dont_save_file_item.h" +#include "titanic/core/drop_target.h" +#include "titanic/core/file_item.h" +#include "titanic/core/game_object.h" +#include "titanic/core/game_object_desc_item.h" +#include "titanic/core/link_item.h" +#include "titanic/core/list.h" +#include "titanic/core/mail_man.h" +#include "titanic/core/message_target.h" +#include "titanic/support/movie_clip.h" +#include "titanic/core/multi_drop_target.h" +#include "titanic/core/node_item.h" +#include "titanic/core/project_item.h" +#include "titanic/core/room_item.h" +#include "titanic/core/saveable_object.h" +#include "titanic/core/static_image.h" +#include "titanic/core/turn_on_object.h" +#include "titanic/core/turn_on_play_sound.h" +#include "titanic/core/turn_on_turn_off.h" +#include "titanic/core/tree_item.h" +#include "titanic/core/view_item.h" + +#include "titanic/game/announce.h" +#include "titanic/game/annoy_barbot.h" +#include "titanic/game/arb_background.h" +#include "titanic/game/arboretum_gate.h" +#include "titanic/game/auto_animate.h" +#include "titanic/game/bar_bell.h" +#include "titanic/game/bar_menu.h" +#include "titanic/game/bar_menu_button.h" +#include "titanic/game/belbot_get_light.h" +#include "titanic/npcs/bilge_succubus.h" +#include "titanic/game/bomb.h" +#include "titanic/game/bottom_of_well_monitor.h" +#include "titanic/game/bowl_unlocker.h" +#include "titanic/game/brain_slot.h" +#include "titanic/game/bridge_door.h" +#include "titanic/game/bridge_view.h" +#include "titanic/game/broken_pell_base.h" +#include "titanic/game/broken_pellerator.h" +#include "titanic/game/broken_pellerator_froz.h" +#include "titanic/game/cage.h" +#include "titanic/game/captains_wheel.h" +#include "titanic/game/cdrom.h" +#include "titanic/game/cdrom_computer.h" +#include "titanic/game/cdrom_tray.h" +#include "titanic/game/cell_point_button.h" +#include "titanic/game/chev_code.h" +#include "titanic/game/chev_panel.h" +#include "titanic/game/chicken_cooler.h" +#include "titanic/game/chicken_dispensor.h" +#include "titanic/game/close_broken_pel.h" +#include "titanic/game/computer.h" +#include "titanic/game/computer_screen.h" +#include "titanic/game/code_wheel.h" +#include "titanic/game/cookie.h" +#include "titanic/game/credits.h" +#include "titanic/game/credits_button.h" +#include "titanic/game/dead_area.h" +#include "titanic/game/desk_click_responder.h" +#include "titanic/game/doorbot_elevator_handler.h" +#include "titanic/game/doorbot_home_handler.h" +#include "titanic/game/ear_sweet_bowl.h" +#include "titanic/game/eject_phonograph_button.h" +#include "titanic/game/elevator_action_area.h" +#include "titanic/game/emma_control.h" +#include "titanic/game/empty_nut_bowl.h" +#include "titanic/game/end_credit_text.h" +#include "titanic/game/end_credits.h" +#include "titanic/game/end_explode_ship.h" +#include "titanic/game/end_game_credits.h" +#include "titanic/game/end_sequence_control.h" +#include "titanic/game/fan.h" +#include "titanic/game/fan_control.h" +#include "titanic/game/fan_decrease.h" +#include "titanic/game/fan_increase.h" +#include "titanic/game/fan_noises.h" +#include "titanic/game/floor_indicator.h" +#include "titanic/game/games_console.h" +#include "titanic/game/get_lift_eye2.h" +#include "titanic/game/glass_smasher.h" +#include "titanic/game/hammer_clip.h" +#include "titanic/game/hammer_dispensor.h" +#include "titanic/game/hammer_dispensor_button.h" +#include "titanic/game/head_slot.h" +#include "titanic/game/head_smash_event.h" +#include "titanic/game/head_smash_lever.h" +#include "titanic/game/head_spinner.h" +#include "titanic/game/idle_summoner.h" +#include "titanic/game/leave_sec_class_state.h" +#include "titanic/game/lemon_dispensor.h" +#include "titanic/game/light.h" +#include "titanic/game/light_switch.h" +#include "titanic/game/little_lift_button.h" +#include "titanic/game/long_stick_dispenser.h" +#include "titanic/game/missiveomat.h" +#include "titanic/game/missiveomat_button.h" +#include "titanic/game/movie_tester.h" +#include "titanic/game/musical_instrument.h" +#include "titanic/game/music_console_button.h" +#include "titanic/game/music_room_phonograph.h" +#include "titanic/game/music_room_stop_phonograph_button.h" +#include "titanic/game/music_system_lock.h" +#include "titanic/game/nav_helmet.h" +#include "titanic/game/nav_helmet_on.h" +#include "titanic/game/nav_helmet_off.h" +#include "titanic/game/navigation_computer.h" +#include "titanic/game/no_nut_bowl.h" +#include "titanic/game/nose_holder.h" +#include "titanic/game/null_port_hole.h" +#include "titanic/game/nut_replacer.h" +#include "titanic/game/pet_disabler.h" +#include "titanic/game/phonograph.h" +#include "titanic/game/phonograph_lid.h" +#include "titanic/game/play_music_button.h" +#include "titanic/game/play_on_act.h" +#include "titanic/game/port_hole.h" +#include "titanic/game/record_phonograph_button.h" +#include "titanic/game/replacement_ear.h" +#include "titanic/game/reserved_table.h" +#include "titanic/game/restaurant_cylinder_holder.h" +#include "titanic/game/restaurant_phonograph.h" +#include "titanic/game/sauce_dispensor.h" +#include "titanic/game/search_point.h" +#include "titanic/game/season_background.h" +#include "titanic/game/season_barrel.h" +#include "titanic/game/seasonal_adjustment.h" +#include "titanic/game/service_elevator_window.h" +#include "titanic/game/ship_setting.h" +#include "titanic/game/ship_setting_button.h" +#include "titanic/game/show_cell_points.h" +#include "titanic/game/speech_dispensor.h" +#include "titanic/game/splash_animation.h" +#include "titanic/game/starling_puret.h" +#include "titanic/game/start_action.h" +#include "titanic/game/stop_phonograph_button.h" +#include "titanic/game/sub_glass.h" +#include "titanic/game/sub_wrapper.h" +#include "titanic/game/sweet_bowl.h" +#include "titanic/game/television.h" +#include "titanic/game/third_class_canal.h" +#include "titanic/game/throw_tv_down_well.h" +#include "titanic/game/titania_still_control.h" +#include "titanic/game/tow_parrot_nav.h" +#include "titanic/game/up_lighter.h" +#include "titanic/game/useless_lever.h" +#include "titanic/game/volume_control.h" +#include "titanic/game/wheel_button.h" +#include "titanic/game/wheel_hotspot.h" +#include "titanic/game/wheel_spin.h" +#include "titanic/game/wheel_spin_horn.h" +#include "titanic/game/gondolier/gondolier_base.h" +#include "titanic/game/gondolier/gondolier_chest.h" +#include "titanic/game/gondolier/gondolier_face.h" +#include "titanic/game/gondolier/gondolier_mixer.h" +#include "titanic/game/gondolier/gondolier_slider.h" +#include "titanic/game/maitred/maitred_arm_holder.h" +#include "titanic/game/maitred/maitred_body.h" +#include "titanic/game/maitred/maitred_legs.h" +#include "titanic/game/maitred/maitred_prod_receptor.h" +#include "titanic/game/parrot/parrot_lobby_controller.h" +#include "titanic/game/parrot/parrot_lobby_link_updater.h" +#include "titanic/game/parrot/parrot_lobby_object.h" +#include "titanic/game/parrot/parrot_lobby_view_object.h" +#include "titanic/game/parrot/parrot_loser.h" +#include "titanic/game/parrot/parrot_nut_bowl_actor.h" +#include "titanic/game/parrot/parrot_nut_eater.h" +#include "titanic/game/parrot/parrot_perch_holder.h" +#include "titanic/npcs/parrot_succubus.h" +#include "titanic/game/parrot/parrot_trigger.h" +#include "titanic/game/parrot/player_meets_parrot.h" +#include "titanic/game/pet/pet.h" +#include "titanic/game/pet/pet_class1.h" +#include "titanic/game/pet/pet_class2.h" +#include "titanic/game/pet/pet_class3.h" +#include "titanic/game/pet/pet_lift.h" +#include "titanic/game/pet/pet_monitor.h" +#include "titanic/game/pet/pet_pellerator.h" +#include "titanic/game/pet/pet_position.h" +#include "titanic/game/pet/pet_sentinal.h" +#include "titanic/game/pet/pet_sounds.h" +#include "titanic/game/pet/pet_transition.h" +#include "titanic/game/pet/pet_transport.h" +#include "titanic/game/pickup/pick_up.h" +#include "titanic/game/pickup/pick_up_bar_glass.h" +#include "titanic/game/pickup/pick_up_hose.h" +#include "titanic/game/pickup/pick_up_lemon.h" +#include "titanic/game/pickup/pick_up_speech_centre.h" +#include "titanic/game/pickup/pick_up_vis_centre.h" +#include "titanic/game/placeholder/bar_shelf_vis_centre.h" +#include "titanic/game/placeholder/lemon_on_bar.h" +#include "titanic/game/placeholder/place_holder.h" +#include "titanic/game/placeholder/tv_on_bar.h" +#include "titanic/game/sgt/armchair.h" +#include "titanic/game/sgt/basin.h" +#include "titanic/game/sgt/bedfoot.h" +#include "titanic/game/sgt/bedhead.h" +#include "titanic/game/sgt/chest_of_drawers.h" +#include "titanic/game/sgt/desk.h" +#include "titanic/game/sgt/deskchair.h" +#include "titanic/game/sgt/drawer.h" +#include "titanic/game/sgt/sgt_doors.h" +#include "titanic/game/sgt/sgt_nav.h" +#include "titanic/game/sgt/sgt_navigation.h" +#include "titanic/game/sgt/sgt_restaurant_doors.h" +#include "titanic/game/sgt/sgt_state_control.h" +#include "titanic/game/sgt/sgt_state_room.h" +#include "titanic/game/sgt/sgt_tv.h" +#include "titanic/game/sgt/sgt_upper_doors_sound.h" +#include "titanic/game/sgt/toilet.h" +#include "titanic/game/sgt/vase.h" +#include "titanic/game/sgt/washstand.h" +#include "titanic/game/transport/gondolier.h" +#include "titanic/game/transport/lift.h" +#include "titanic/game/transport/lift_indicator.h" +#include "titanic/game/transport/pellerator.h" +#include "titanic/game/transport/service_elevator.h" +#include "titanic/game/transport/transport.h" +#include "titanic/gfx/act_button.h" +#include "titanic/gfx/changes_season_button.h" +#include "titanic/gfx/chev_left_off.h" +#include "titanic/gfx/chev_left_on.h" +#include "titanic/gfx/chev_right_off.h" +#include "titanic/gfx/chev_right_on.h" +#include "titanic/gfx/chev_send_rec_switch.h" +#include "titanic/gfx/chev_switch.h" +#include "titanic/gfx/edit_control.h" +#include "titanic/gfx/elevator_button.h" +#include "titanic/gfx/get_from_succ.h" +#include "titanic/gfx/helmet_on_off.h" +#include "titanic/gfx/home_photo.h" +#include "titanic/gfx/icon_nav_action.h" +#include "titanic/gfx/icon_nav_butt.h" +#include "titanic/gfx/icon_nav_down.h" +#include "titanic/gfx/icon_nav_image.h" +#include "titanic/gfx/icon_nav_left.h" +#include "titanic/gfx/icon_nav_receive.h" +#include "titanic/gfx/icon_nav_right.h" +#include "titanic/gfx/icon_nav_send.h" +#include "titanic/gfx/icon_nav_up.h" +#include "titanic/gfx/keybrd_butt.h" +#include "titanic/gfx/move_object_button.h" +#include "titanic/gfx/music_control.h" +#include "titanic/gfx/music_slider_pitch.h" +#include "titanic/gfx/music_slider_speed.h" +#include "titanic/gfx/music_switch.h" +#include "titanic/gfx/music_switch_inversion.h" +#include "titanic/gfx/music_switch_reverse.h" +#include "titanic/gfx/music_voice_mute.h" +#include "titanic/gfx/send_to_succ.h" +#include "titanic/gfx/sgt_selector.h" +#include "titanic/gfx/slider_button.h" +#include "titanic/gfx/small_chev_left_off.h" +#include "titanic/gfx/small_chev_left_on.h" +#include "titanic/gfx/small_chev_right_off.h" +#include "titanic/gfx/small_chev_right_on.h" +#include "titanic/gfx/status_change_button.h" +#include "titanic/gfx/st_button.h" +#include "titanic/gfx/toggle_button.h" +#include "titanic/gfx/text_down.h" +#include "titanic/gfx/text_skrew.h" +#include "titanic/gfx/text_up.h" +#include "titanic/gfx/toggle_switch.h" + +#include "titanic/messages/messages.h" +#include "titanic/messages/auto_sound_event.h" +#include "titanic/messages/bilge_auto_sound_event.h" +#include "titanic/messages/bilge_dispensor_event.h" +#include "titanic/messages/door_auto_sound_event.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/messages/pet_messages.h" +#include "titanic/messages/service_elevator_door.h" + +#include "titanic/moves/call_pellerator.h" +#include "titanic/moves/enter_bomb_room.h" +#include "titanic/moves/enter_bridge.h" +#include "titanic/moves/enter_exit_first_class_state.h" +#include "titanic/moves/enter_exit_mini_lift.h" +#include "titanic/moves/enter_exit_sec_class_mini_lift.h" +#include "titanic/moves/enter_exit_view.h" +#include "titanic/moves/enter_sec_class_state.h" +#include "titanic/moves/exit_arboretum.h" +#include "titanic/moves/exit_bridge.h" +#include "titanic/moves/exit_lift.h" +#include "titanic/moves/exit_pellerator.h" +#include "titanic/moves/exit_state_room.h" +#include "titanic/moves/exit_tiania.h" +#include "titanic/moves/move_player_in_parrot_room.h" +#include "titanic/moves/move_player_to.h" +#include "titanic/moves/move_player_to_from.h" +#include "titanic/moves/multi_move.h" +#include "titanic/moves/pan_from_pel.h" +#include "titanic/moves/restaurant_pan_handler.h" +#include "titanic/moves/restricted_move.h" +#include "titanic/moves/scraliontis_table.h" +#include "titanic/moves/trip_down_canal.h" + +#include "titanic/npcs/barbot.h" +#include "titanic/npcs/bellbot.h" +#include "titanic/npcs/callbot.h" +#include "titanic/npcs/deskbot.h" +#include "titanic/npcs/doorbot.h" +#include "titanic/npcs/liftbot.h" +#include "titanic/npcs/maitre_d.h" +#include "titanic/npcs/mobile.h" +#include "titanic/npcs/parrot.h" +#include "titanic/npcs/starlings.h" +#include "titanic/npcs/succubus.h" +#include "titanic/npcs/summon_bots.h" +#include "titanic/npcs/titania.h" +#include "titanic/npcs/true_talk_npc.h" + +#include "titanic/pet_control/pet_control.h" +#include "titanic/pet_control/pet_drag_chev.h" +#include "titanic/pet_control/pet_graphic.h" +#include "titanic/pet_control/pet_graphic2.h" +#include "titanic/pet_control/pet_leaf.h" +#include "titanic/pet_control/pet_mode_off.h" +#include "titanic/pet_control/pet_mode_on.h" +#include "titanic/pet_control/pet_mode_panel.h" +#include "titanic/pet_control/pet_pannel1.h" +#include "titanic/pet_control/pet_pannel2.h" +#include "titanic/pet_control/pet_pannel3.h" + +#include "titanic/sound/auto_music_player.h" +#include "titanic/sound/auto_music_player_base.h" +#include "titanic/sound/auto_sound_player.h" +#include "titanic/sound/auto_sound_player_adsr.h" +#include "titanic/sound/background_sound_maker.h" +#include "titanic/sound/bird_song.h" +#include "titanic/sound/dome_from_top_of_well.h" +#include "titanic/sound/gondolier_song.h" +#include "titanic/sound/enter_view_toggles_other_music.h" +#include "titanic/sound/music_player.h" +#include "titanic/sound/node_auto_sound_player.h" +#include "titanic/sound/restricted_auto_music_player.h" +#include "titanic/sound/room_auto_sound_player.h" +#include "titanic/sound/room_trigger_auto_music_player.h" +#include "titanic/sound/season_noises.h" +#include "titanic/sound/seasonal_music_player.h" +#include "titanic/sound/titania_speech.h" +#include "titanic/sound/trigger_auto_music_player.h" +#include "titanic/sound/view_auto_sound_player.h" +#include "titanic/sound/view_toggles_other_music.h" +#include "titanic/sound/water_lapping_sounds.h" + +#include "titanic/star_control/star_control.h" +#include "titanic/support/time_event_info.h" + +namespace Titanic { + +CSaveableObject *ClassDef::create() { + return new CSaveableObject(); +} + +/*------------------------------------------------------------------------*/ + +Common::HashMap<Common::String, CSaveableObject::CreateFunction> * + CSaveableObject::_classList = nullptr; +Common::List<ClassDef *> *CSaveableObject::_classDefs; + +#define DEFFN(T) CSaveableObject *Function##T() { return new T(); } \ + ClassDef *T::_type +#define ADDFN(CHILD, PARENT) \ + CHILD::_type = new TypeTemplate<CHILD>(#CHILD, PARENT::_type); \ + (*_classList)[#CHILD] = Function##CHILD + +DEFFN(CArm); +DEFFN(CAuditoryCentre); +DEFFN(CBowlEar); +DEFFN(CBrain); +DEFFN(CBridgePiece); +DEFFN(CCarry); +DEFFN(CCarryParrot); +DEFFN(CCentralCore); +DEFFN(CChicken); +DEFFN(CCrushedTV); +DEFFN(CEar); +DEFFN(CEye); +DEFFN(CFeathers); +DEFFN(CFruit); +DEFFN(CGlass); +DEFFN(CHammer); +DEFFN(CHeadPiece); +DEFFN(CHose); +DEFFN(CHoseEnd); +DEFFN(CKey); +DEFFN(CLiftbotHead); +DEFFN(CLongStick); +DEFFN(CMagazine); +DEFFN(CMaitreDLeftArm); +DEFFN(CMaitreDRightArm); +DEFFN(CMouth); +DEFFN(CNapkin); +DEFFN(CNose); +DEFFN(CNote); +DEFFN(CParcel); +DEFFN(CPerch); +DEFFN(CPhonographCylinder); +DEFFN(CPhonographEar); +DEFFN(CPhotograph); +DEFFN(CPlugIn); +DEFFN(CSpeechCentre); +DEFFN(CSweets); +DEFFN(CVisionCentre); + +DEFFN(CBackground); +DEFFN(CClickResponder); +DEFFN(CDontSaveFileItem); +DEFFN(CDropTarget); +DEFFN(CFileItem); +DEFFN(CFileListItem); +DEFFN(CGameObject); +DEFFN(CGameObjectDescItem); +DEFFN(CLinkItem); +DEFFN(ListItem); +DEFFN(CMailMan); +DEFFN(CMessageTarget); +DEFFN(CMovieClip); +DEFFN(CMultiDropTarget); +DEFFN(CNamedItem); +DEFFN(CNodeItem); +DEFFN(CProjectItem); +DEFFN(CResourceKey); +DEFFN(CRoomItem); +DEFFN(CSaveableObject); +DEFFN(CStaticImage); +DEFFN(CTurnOnObject); +DEFFN(CTurnOnPlaySound); +DEFFN(CTurnOnTurnOff); +DEFFN(CTreeItem); +DEFFN(CViewItem); + +DEFFN(CAnnounce); +DEFFN(CAnnoyBarbot); +DEFFN(CArbBackground); +DEFFN(CArboretumGate); +DEFFN(CAutoAnimate); +DEFFN(CBarBell); +DEFFN(CBarMenu); +DEFFN(CBarMenuButton); +DEFFN(CBelbotGetLight); +DEFFN(CBilgeSuccUBus); +DEFFN(CBomb); +DEFFN(CBottomOfWellMonitor); +DEFFN(CBowlUnlocker); +DEFFN(CBrainSlot); +DEFFN(CBridgeDoor); +DEFFN(CBridgeView); +DEFFN(CBrokenPellBase); +DEFFN(CBrokenPellerator); +DEFFN(CBrokenPelleratorFroz); +DEFFN(CCage); +DEFFN(CCallPellerator); +DEFFN(CCaptainsWheel); +DEFFN(CCDROM); +DEFFN(CCDROMComputer); +DEFFN(CCDROMTray); +DEFFN(CCellPointButton); +DEFFN(CChevCode); +DEFFN(CChevPanel); +DEFFN(CChickenCooler); +DEFFN(CChickenDispensor); +DEFFN(CCloseBrokenPel); +DEFFN(CodeWheel); +DEFFN(CComputer); +DEFFN(CComputerScreen); +DEFFN(CCookie); +DEFFN(CCredits); +DEFFN(CCreditsButton); +DEFFN(CDeadArea); +DEFFN(CDeskClickResponder); +DEFFN(CDoorbotElevatorHandler); +DEFFN(CDoorbotHomeHandler); +DEFFN(CEarSweetBowl); +DEFFN(CEjectPhonographButton); +DEFFN(CElevatorActionArea); +DEFFN(CEmmaControl); +DEFFN(CEmptyNutBowl); +DEFFN(CEndCreditText); +DEFFN(CEndCredits); +DEFFN(CEndExplodeShip); +DEFFN(CEndGameCredits); +DEFFN(CEndSequenceControl); +DEFFN(CFan); +DEFFN(CFanControl); +DEFFN(CFanDecrease); +DEFFN(CFanIncrease); +DEFFN(CFanNoises); +DEFFN(CFloorIndicator); +DEFFN(CGamesConsole); +DEFFN(CGetLiftEye2); +DEFFN(CGlassSmasher); +DEFFN(CHammerClip); +DEFFN(CHammerDispensor); +DEFFN(CHammerDispensorButton); +DEFFN(CHeadSlot); +DEFFN(CHeadSmashEvent); +DEFFN(CHeadSmashLever); +DEFFN(CHeadSpinner); +DEFFN(CIdleSummoner); +DEFFN(CLeaveSecClassState); +DEFFN(CLemonDispensor); +DEFFN(CLight); +DEFFN(CLightSwitch); +DEFFN(CLittleLiftButton); +DEFFN(CLongStickDispenser); +DEFFN(CMissiveOMat); +DEFFN(CMissiveOMatButton); +DEFFN(CMovieTester); +DEFFN(CMusicalInstrument); +DEFFN(CMusicConsoleButton); +DEFFN(CMusicRoomPhonograph); +DEFFN(CMusicRoomStopPhonographButton); +DEFFN(CMusicSystemLock); +DEFFN(CNavHelmet); +DEFFN(CNavHelmetOn); +DEFFN(CNavHelmetOff); +DEFFN(CNavigationComputer); +DEFFN(CNoNutBowl); +DEFFN(CNoseHolder); +DEFFN(CNullPortHole); +DEFFN(CNutReplacer); +DEFFN(CPetDisabler); +DEFFN(CPhonograph); +DEFFN(CPhonographLid); +DEFFN(CPlayMusicButton); +DEFFN(CPlayOnAct); +DEFFN(CPortHole); +DEFFN(CRecordPhonographButton); +DEFFN(CReplacementEar); +DEFFN(CReservedTable); +DEFFN(CRestaurantCylinderHolder); +DEFFN(CRestaurantPhonograph); +DEFFN(CSauceDispensor); +DEFFN(CSearchPoint); +DEFFN(CSeasonBackground); +DEFFN(CSeasonBarrel); +DEFFN(CSeasonalAdjustment); +DEFFN(CServiceElevatorWindow); +DEFFN(CShipSetting); +DEFFN(CShipSettingButton); +DEFFN(CShowCellpoints); +DEFFN(CSpeechDispensor); +DEFFN(CSplashAnimation); +DEFFN(CStarlingPuret); +DEFFN(CStartAction); +DEFFN(CStopPhonographButton); +DEFFN(CSUBGlass); +DEFFN(CSUBWrapper); +DEFFN(CSweetBowl); +DEFFN(CTelevision); +DEFFN(CThirdClassCanal); +DEFFN(CThrowTVDownWell); +DEFFN(CTitaniaStillControl); +DEFFN(CTOWParrotNav); +DEFFN(CUpLighter); +DEFFN(CUselessLever); +DEFFN(CVolumeControl); +DEFFN(CWheelButton); +DEFFN(CWheelHotSpot); +DEFFN(CWheelSpin); +DEFFN(CWheelSpinHorn); +DEFFN(CGondolierBase); +DEFFN(CGondolierChest); +DEFFN(CGondolierFace); +DEFFN(CGondolierMixer); +DEFFN(CGondolierSlider); +DEFFN(CMaitreDArmHolder); +DEFFN(CMaitreDBody); +DEFFN(CMaitreDLegs); +DEFFN(CMaitreDProdReceptor); +DEFFN(CParrotLobbyController); +DEFFN(CParrotLobbyLinkUpdater); +DEFFN(CParrotLobbyObject); +DEFFN(CParrotLobbyViewObject); +DEFFN(CParrotLoser); +DEFFN(CParrotNutBowlActor); +DEFFN(CParrotNutEater); +DEFFN(CParrotPerchHolder); +DEFFN(CParrotSuccUBus); +DEFFN(CParrotTrigger); +DEFFN(CPlayerMeetsParrot); +DEFFN(CPET); +DEFFN(CPETClass1); +DEFFN(CPETClass2); +DEFFN(CPETClass3); +DEFFN(CPetControl); +DEFFN(CPetDragChev); +DEFFN(CPetGraphic); +DEFFN(CPetGraphic2); +DEFFN(PETLeaf); +DEFFN(CPETLift); +DEFFN(CPETMonitor); +DEFFN(CPETPellerator); +DEFFN(CPETPosition); +DEFFN(CPETSentinal); +DEFFN(CPETSounds); +DEFFN(CPETTransition); +DEFFN(CPETTransport); +DEFFN(CPickUp); +DEFFN(CPickUpBarGlass); +DEFFN(CPickUpHose); +DEFFN(CPickUpLemon); +DEFFN(CPickUpSpeechCentre); +DEFFN(CPickUpVisCentre); +DEFFN(CBarShelfVisCentre); +DEFFN(CLemonOnBar); +DEFFN(CPlaceHolder); +DEFFN(CTVOnBar); +DEFFN(CArmchair); +DEFFN(CBasin); +DEFFN(CBedfoot); +DEFFN(CBedhead); +DEFFN(CChestOfDrawers); +DEFFN(CDesk); +DEFFN(CDeskchair); +DEFFN(CDrawer); +DEFFN(CSGTDoors); +DEFFN(SGTNav); +DEFFN(CSGTNavigation); +DEFFN(CSGTRestaurantDoors); +DEFFN(CSGTStateControl); +DEFFN(CSGTStateRoom); +DEFFN(CSGTTV); +DEFFN(CSGTUpperDoorsSound); +DEFFN(CToilet); +DEFFN(CVase); +DEFFN(CWashstand); + +DEFFN(CGondolier); +DEFFN(CLift); +DEFFN(CLiftindicator); +DEFFN(CPellerator); +DEFFN(CServiceElevator); +DEFFN(CTransport); + +DEFFN(CActButton); +DEFFN(CChangesSeasonButton); +DEFFN(CChevLeftOff); +DEFFN(CChevLeftOn); +DEFFN(CChevRightOff); +DEFFN(CChevRightOn); +DEFFN(CChevSendRecSwitch); +DEFFN(CChevSwitch); +DEFFN(CEditControl); +DEFFN(CElevatorButton); +DEFFN(CGetFromSucc); +DEFFN(CHelmetOnOff); +DEFFN(CHomePhoto); +DEFFN(CIconNavAction); +DEFFN(CIconNavButt); +DEFFN(CIconNavDown); +DEFFN(CIconNavImage); +DEFFN(CIconNavLeft); +DEFFN(CIconNavReceive); +DEFFN(CIconNavRight); +DEFFN(CIconNavSend); +DEFFN(CIconNavUp); +DEFFN(CKeybrdButt); +DEFFN(CMoveObjectButton); +DEFFN(CMusicControl); +DEFFN(CMusicSlider); +DEFFN(CMusicSliderPitch); +DEFFN(CMusicSliderSpeed); +DEFFN(CMusicSwitch); +DEFFN(CMusicSwitchInversion); +DEFFN(CMusicSwitchReverse); +DEFFN(CMusicVoiceMute); +DEFFN(CPetModeOff); +DEFFN(CPetModeOn); +DEFFN(CPetModePanel); +DEFFN(CPetPannel1); +DEFFN(CPetPannel2); +DEFFN(CPetPannel3); +DEFFN(CSendToSucc); +DEFFN(CSGTSelector); +DEFFN(CSliderButton); +DEFFN(CSmallChevLeftOff); +DEFFN(CSmallChevLeftOn); +DEFFN(CSmallChevRightOff); +DEFFN(CSmallChevRightOn); +DEFFN(CStatusChangeButton); +DEFFN(CSTButton); +DEFFN(CTextDown); +DEFFN(CTextSkrew); +DEFFN(CTextUp); +DEFFN(CToggleButton); +DEFFN(CToggleSwitch); + +DEFFN(CActMsg); +DEFFN(CActivationmsg); +DEFFN(CAddHeadPieceMsg); +DEFFN(CAnimateMaitreDMsg); +DEFFN(CArboretumGateMsg); +DEFFN(CArmPickedUpFromTableMsg); +DEFFN(CAutoSoundEvent); +DEFFN(CBilgeAutoSoundEvent); +DEFFN(CBilgeDispensorEvent); +DEFFN(CBodyInBilgeRoomMsg); +DEFFN(CBowlStateChangeMsg); +DEFFN(CCarryObjectArrivedMsg); +DEFFN(CChangeMusicMsg); +DEFFN(CChangeSeasonMsg); +DEFFN(CCheckAllPossibleCodes); +DEFFN(CCheckChevCode); +DEFFN(CChildDragEndMsg); +DEFFN(CChildDragMoveMsg); +DEFFN(CChildDragStartMsg); +DEFFN(CClearChevPanelBits); +DEFFN(CCorrectMusicPlayedMsg); +DEFFN(CCreateMusicPlayerMsg); +DEFFN(CCylinderHolderReadyMsg); +DEFFN(CDeactivationMsg); +DEFFN(CDeliverCCarryMsg); +DEFFN(CDisableMaitreDProdReceptor); +DEFFN(CDismissBotMsg); +DEFFN(CDoffNavHelmet); +DEFFN(CDonNavHelmet); +DEFFN(CDoorAutoSoundEvent); +DEFFN(CDoorbotNeededInElevatorMsg); +DEFFN(CDoorbotNeededInHomeMsg); +DEFFN(CDropObjectMsg); +DEFFN(CDropZoneGotObjectMsg); +DEFFN(CDropZoneLostObjectMsg); +DEFFN(CEditControlMsg); +DEFFN(CEnterNodeMsg); +DEFFN(CEnterRoomMsg); +DEFFN(CEnterViewMsg); +DEFFN(CEjectCylinderMsg); +DEFFN(CErasePhonographCylinderMsg); +DEFFN(CFrameMsg); +DEFFN(CFreshenCookieMsg); +DEFFN(CGetChevClassBits); +DEFFN(CGetChevClassNum); +DEFFN(CGetChevCodeFromRoomNameMsg); +DEFFN(CGetChevFloorBits); +DEFFN(CGetChevFloorNum); +DEFFN(CGetChevLiftBits); +DEFFN(CGetChevLiftNum); +DEFFN(CGetChevRoomBits); +DEFFN(CGetChevRoomNum); +DEFFN(CHoseConnectedMsg); +DEFFN(CInitializeAnimMsg); +DEFFN(CIsEarBowlPuzzleDone); +DEFFN(CIsHookedOnMsg); +DEFFN(CIsParrotPresentMsg); +DEFFN(CKeyCharMsg); +DEFFN(CLeaveNodeMsg); +DEFFN(CLeaveRoomMsg); +DEFFN(CLeaveViewMsg); +DEFFN(CLemonFallsFromTreeMsg); +DEFFN(CLightsMsg); +DEFFN(CLoadSuccessMsg); +DEFFN(CLockPhonographMsg); +DEFFN(CMaitreDDefeatedMsg); +DEFFN(CMaitreDHappyMsg); +DEFFN(CMessage); +DEFFN(CMissiveOMatActionMsg); +DEFFN(CMouseMsg); +DEFFN(CMouseMoveMsg); +DEFFN(CMouseButtonMsg); +DEFFN(CMouseButtonDownMsg); +DEFFN(CMouseButtonUpMsg); +DEFFN(CMouseDoubleClickMsg); +DEFFN(CMouseDragMsg); +DEFFN(CMouseDragStartMsg); +DEFFN(CMouseDragMoveMsg); +DEFFN(CMouseDragEndMsg); +DEFFN(CMoveToStartPosMsg); +DEFFN(CMovieEndMsg); +DEFFN(CMovieFrameMsg); +DEFFN(CMusicHasStartedMsg); +DEFFN(CMusicHasStoppedMsg); +DEFFN(CMusicSettingChangedMsg); +DEFFN(CNPCPlayAnimationMsg); +DEFFN(CNPCPlayIdleAnimationMsg); +DEFFN(CNPCPlayTalkingAnimationMsg); +DEFFN(CNPCQueueIdleAnimMsg); +DEFFN(CNutPuzzleMsg); +DEFFN(COnSummonBotMsg); +DEFFN(COpeningCreditsMsg); +DEFFN(CPETDeliverMsg); +DEFFN(CPETGainedObjectMsg); +DEFFN(CPETHelmetOnOffMsg); +DEFFN(CPETKeyboardOnOffMsg); +DEFFN(CPETLostObjectMsg); +DEFFN(CPETObjectSelectedMsg); +DEFFN(CPETObjectStateMsg); +DEFFN(CPETPhotoOnOffMsg); +DEFFN(CPETPlaySoundMsg); +DEFFN(CPETReceiveMsg); +DEFFN(CPETSetStarDestinationMsg); +DEFFN(CPETStarFieldLockMsg); +DEFFN(CPETStereoFieldOnOffMsg); +DEFFN(CPETTargetMsg); +DEFFN(CPETUpMsg); +DEFFN(CPETDownMsg); +DEFFN(CPETLeftMsg); +DEFFN(CPETRightMsg); +DEFFN(CPETActivateMsg); +DEFFN(CPanningAwayFromParrotMsg); +DEFFN(CParrotSpeakMsg); +DEFFN(CParrotTriesChickenMsg); +DEFFN(CPassOnDragStartMsg); +DEFFN(CPhonographPlayMsg); +DEFFN(CPhonographReadyToPlayMsg); +DEFFN(CPhonographRecordMsg); +DEFFN(CPhonographStopMsg); +DEFFN(CPlayRangeMsg); +DEFFN(CPlayerTriesRestaurantTableMsg); +DEFFN(CPreEnterNodeMsg); +DEFFN(CPreEnterRoomMsg); +DEFFN(CPreEnterViewMsg); +DEFFN(CPreSaveMsg); +DEFFN(CProdMaitreDMsg); +DEFFN(CPumpingMsg); +DEFFN(CPutBotBackInHisBoxMsg); +DEFFN(CPutParrotBackMsg); +DEFFN(CPuzzleSolvedMsg); +DEFFN(CQueryCylinderHolderMsg); +DEFFN(CQueryCylinderMsg); +DEFFN(CQueryCylinderNameMsg); +DEFFN(CQueryCylinderTypeMsg); +DEFFN(CQueryMusicControlSettingMsg); +DEFFN(CQueryPhonographState); +DEFFN(CRecordOntoCylinderMsg); +DEFFN(CRemoveFromGameMsg); +DEFFN(CReplaceBowlAndNutsMsg); +DEFFN(CRestaurantMusicChanged); +DEFFN(CSendCCarryMsg); +DEFFN(CSenseWorkingMsg); +DEFFN(CServiceElevatorDoor); +DEFFN(CServiceElevatorFloorChangeMsg); +DEFFN(CServiceElevatorFloorRequestMsg); +DEFFN(CServiceElevatorMsg); +DEFFN(CSetChevButtonImageMsg); +DEFFN(CSetChevClassBits); +DEFFN(CSetChevFloorBits); +DEFFN(CSetChevLiftBits); +DEFFN(CSetChevPanelBitMsg); +DEFFN(CSetChevPanelButtonsMsg); +DEFFN(CSetChevRoomBits); +DEFFN(CSetFrameMsg); +DEFFN(CSetMusicControlsMsg); +DEFFN(CSetVarMsg); +DEFFN(CSetVolumeMsg); +DEFFN(CShipSettingMsg); +DEFFN(CShowTextMsg); +DEFFN(CSignalObject); +DEFFN(CSpeechFallsFromTreeMsg); +DEFFN(CStartMusicMsg); +DEFFN(CStatusChangeMsg); +DEFFN(CStopMusicMsg); +DEFFN(CSubAcceptCCarryMsg); +DEFFN(CSubDeliverCCarryMsg); +DEFFN(CSubSendCCarryMsg); +DEFFN(CSUBTransition); +DEFFN(CSubTurnOffMsg); +DEFFN(CSubTurnOnMsg); +DEFFN(CSummonBotMsg); +DEFFN(CSummonBotQueryMsg); +DEFFN(CTakeHeadPieceMsg); +DEFFN(CTextInputMsg); +DEFFN(CTimeDilationMsg); +DEFFN(CTimeMsg); +DEFFN(CTimerMsg); +DEFFN(CTitleSequenceEndedMsg); +DEFFN(CTransitMsg); +DEFFN(CTranslateObjectMsg); +DEFFN(CTransportMsg); +DEFFN(CTriggerAutoMusicPlayerMsg); +DEFFN(CTriggerNPCEvent); +DEFFN(CTrueTalkGetAnimSetMsg); +DEFFN(CTrueTalkGetAssetDetailsMsg); +DEFFN(CTrueTalkGetStateValueMsg); +DEFFN(CTrueTalkNotifySpeechEndedMsg); +DEFFN(CTrueTalkNotifySpeechStartedMsg); +DEFFN(CTrueTalkQueueUpAnimSetMsg); +DEFFN(CTrueTalkSelfQueueAnimSetMsg); +DEFFN(CTrueTalkTriggerActionMsg); +DEFFN(CTurnOff); +DEFFN(CTurnOn); +DEFFN(CUse); +DEFFN(CUseWithCharMsg); +DEFFN(CUseWithOtherMsg); +DEFFN(CVirtualKeyCharMsg); +DEFFN(CVisibleMsg); + +DEFFN(CEnterBombRoom); +DEFFN(CEnterBridge); +DEFFN(CEnterExitFirstClassState); +DEFFN(CEnterExitMiniLift); +DEFFN(CEnterExitSecClassMiniLift); +DEFFN(CEnterExitView); +DEFFN(CEnterSecClassState); +DEFFN(CExitArboretum); +DEFFN(CExitBridge); +DEFFN(CExitLift); +DEFFN(CExitPellerator); +DEFFN(CExitStateRoom); +DEFFN(CExitTiania); +DEFFN(CMovePlayerInParrotRoom); +DEFFN(CMovePlayerTo); +DEFFN(CMovePlayerToFrom); +DEFFN(CMultiMove); +DEFFN(CPanFromPel); +DEFFN(CRestaurantPanHandler); +DEFFN(CScraliontisTable); +DEFFN(CRestrictedMove); +DEFFN(CTripDownCanal); + +DEFFN(CBarbot); +DEFFN(CBellBot); +DEFFN(CCallBot); +DEFFN(CCharacter); +DEFFN(CDeskbot); +DEFFN(CDoorbot); +DEFFN(CLiftBot); +DEFFN(CMaitreD); +DEFFN(CMobile); +DEFFN(CParrot); +DEFFN(CRobotController); +DEFFN(CStarlings); +DEFFN(CSummonBots); +DEFFN(CSuccUBus); +DEFFN(CTitania); +DEFFN(CTrueTalkNPC); +DEFFN(CAutoMusicPlayer); +DEFFN(CAutoMusicPlayerBase); +DEFFN(CAutoSoundPlayer); +DEFFN(CAutoSoundPlayerADSR); +DEFFN(CBackgroundSoundMaker); +DEFFN(CBirdSong); +DEFFN(CDomeFromTopOfWell); +DEFFN(CEnterViewTogglesOtherMusic); +DEFFN(CGondolierSong); +DEFFN(CMusicPlayer); +DEFFN(CNodeAutoSoundPlayer); +DEFFN(CRestrictedAutoMusicPlayer); +DEFFN(CRoomAutoSoundPlayer); +DEFFN(CRoomTriggerAutoMusicPlayer); +DEFFN(CSeasonNoises); +DEFFN(CSeasonalMusicPlayer); +DEFFN(CTitaniaSpeech); +DEFFN(CTriggerAutoMusicPlayer); +DEFFN(CViewAutoSoundPlayer); +DEFFN(CViewTogglesOtherMusic); +DEFFN(CWaterLappingSounds); +DEFFN(CStarControl); +DEFFN(CTimeEventInfo); + +void CSaveableObject::initClassList() { + _classDefs = new Common::List<ClassDef *>(); + _classList = new Common::HashMap<Common::String, CreateFunction>(); + ADDFN(CArm, CCarry); + ADDFN(CAuditoryCentre, CBrain); + ADDFN(CBowlEar, CEar); + ADDFN(CBrain, CCarry); + ADDFN(CBridgePiece, CCarry); + ADDFN(CCarry, CGameObject); + ADDFN(CCarryParrot, CCarry); + ADDFN(CCentralCore, CBrain); + ADDFN(CChicken, CCarry); + ADDFN(CCrushedTV, CCarry); + ADDFN(CEar, CHeadPiece); + ADDFN(CEye, CHeadPiece); + ADDFN(CFeathers, CCarry); + ADDFN(CFruit, CCarry); + ADDFN(CGlass, CCarry); + ADDFN(CHammer, CCarry); + ADDFN(CHeadPiece, CCarry); + ADDFN(CHose, CCarry); + ADDFN(CHoseEnd, CHose); + ADDFN(CKey, CCarry); + ADDFN(CLiftbotHead, CCarry); + ADDFN(CLongStick, CCarry); + ADDFN(CMagazine, CCarry); + ADDFN(CMaitreDLeftArm, CArm); + ADDFN(CMaitreDRightArm, CArm); + ADDFN(CMouth, CHeadPiece); + ADDFN(CNapkin, CCarry); + ADDFN(CNose, CHeadPiece); + ADDFN(CNote, CCarry); + ADDFN(CParcel, CCarry); + ADDFN(CPerch, CCentralCore); + ADDFN(CPhonographCylinder, CCarry); + ADDFN(CPhonographEar, CEar); + ADDFN(CPhotograph, CCarry); + ADDFN(CPlugIn, CCarry); + ADDFN(CSpeechCentre, CBrain); + ADDFN(CSweets, CCarry); + ADDFN(CVisionCentre, CBrain); + + ADDFN(CBackground, CGameObject); + ADDFN(CClickResponder, CGameObject); + ADDFN(CDontSaveFileItem, CFileItem); + ADDFN(CDropTarget, CGameObject); + ADDFN(CFileItem, CTreeItem); + ADDFN(CFileListItem, ListItem); + ADDFN(CGameObject, CNamedItem); + ADDFN(CGameObjectDescItem, CTreeItem); + ADDFN(CLinkItem, CNamedItem); + ADDFN(ListItem, CSaveableObject); + ADDFN(CMessageTarget, CSaveableObject); + ADDFN(CMailMan, CGameObject); + ADDFN(CMovieClip, ListItem); + ADDFN(CMultiDropTarget, CDropTarget); + ADDFN(CNamedItem, CTreeItem); + ADDFN(CNodeItem, CNamedItem); + ADDFN(CProjectItem, CFileItem); + ADDFN(CResourceKey, CSaveableObject); + ADDFN(CRoomItem, CNamedItem); + ADDFN(CSaveableObject, CSaveableObject); + ADDFN(CStaticImage, CGameObject); + ADDFN(CTurnOnObject, CBackground); + ADDFN(CTreeItem, CMessageTarget); + ADDFN(CTurnOnPlaySound, CTurnOnObject); + ADDFN(CTurnOnTurnOff, CBackground); + ADDFN(CViewItem, CNamedItem); + + ADDFN(CAnnounce, CGameObject); + ADDFN(CAnnoyBarbot, CGameObject); + ADDFN(CArbBackground, CBackground); + ADDFN(CArboretumGate, CBackground); + ADDFN(CAutoAnimate, CBackground); + ADDFN(CBarBell, CGameObject); + ADDFN(CBarMenu, CGameObject); + ADDFN(CBarMenuButton, CGameObject); + ADDFN(CBelbotGetLight, CGameObject); + ADDFN(CBilgeSuccUBus, CSuccUBus); + ADDFN(CBomb, CBackground); + ADDFN(CBottomOfWellMonitor, CGameObject); + ADDFN(CBowlUnlocker, CGameObject); + ADDFN(CBrainSlot, CGameObject); + ADDFN(CBridgeDoor, CGameObject); + ADDFN(CBridgeView, CBackground); + ADDFN(CBrokenPellBase, CBackground); + ADDFN(CBrokenPellerator, CBrokenPellBase); + ADDFN(CBrokenPelleratorFroz, CBrokenPellBase); + ADDFN(CCage, CBackground); + ADDFN(CCallPellerator, CGameObject); + ADDFN(CCaptainsWheel, CBackground); + ADDFN(CCDROM, CGameObject); + ADDFN(CCDROMComputer, CGameObject); + ADDFN(CCDROMTray, CGameObject); + ADDFN(CCellPointButton, CBackground); + ADDFN(CChevCode, CGameObject); + ADDFN(CChevPanel, CGameObject); + ADDFN(CChickenCooler, CGameObject); + ADDFN(CChickenDispensor, CBackground); + ADDFN(CodeWheel, CBomb); + ADDFN(CCloseBrokenPel, CBackground); + ADDFN(CComputer, CBackground); + ADDFN(CComputerScreen, CGameObject); + ADDFN(CCookie, CGameObject); + ADDFN(CCredits, CGameObject); + ADDFN(CCreditsButton, CBackground); + ADDFN(CDeadArea, CGameObject); + ADDFN(CDeskClickResponder, CClickResponder); + ADDFN(CDoorbotElevatorHandler, CGameObject); + ADDFN(CDoorbotHomeHandler, CGameObject); + ADDFN(CDropTarget, CGameObject); + ADDFN(CEarSweetBowl, CSweetBowl); + ADDFN(CEjectPhonographButton, CBackground); + ADDFN(CElevatorActionArea, CGameObject); + ADDFN(CEmmaControl, CBackground); + ADDFN(CEmptyNutBowl, CGameObject); + ADDFN(CEndCreditText, CGameObject); + ADDFN(CEndCredits, CGameObject); + ADDFN(CEndExplodeShip, CGameObject); + ADDFN(CEndGameCredits, CGameObject); + ADDFN(CEndSequenceControl, CGameObject); + ADDFN(CFan, CGameObject); + ADDFN(CFanControl, CGameObject); + ADDFN(CFanDecrease, CGameObject); + ADDFN(CFanIncrease, CGameObject); + ADDFN(CFanNoises, CGameObject); + ADDFN(CFloorIndicator, CGameObject); + ADDFN(CGamesConsole, CBackground); + ADDFN(CGetLiftEye2, CGameObject); + ADDFN(CGlassSmasher, CGameObject); + ADDFN(CHammerClip, CGameObject); + ADDFN(CHammerDispensor, CBackground); + ADDFN(CHammerDispensorButton, CStartAction); + ADDFN(CHeadSlot, CGameObject); + ADDFN(CHeadSmashEvent, CBackground); + ADDFN(CHeadSmashLever, CBackground); + ADDFN(CHeadSpinner, CGameObject); + ADDFN(CIdleSummoner, CGameObject); + ADDFN(CLeaveSecClassState, CGameObject); + ADDFN(CLemonDispensor, CBackground); + ADDFN(CLight, CBackground); + ADDFN(CLightSwitch, CBackground); + ADDFN(CLittleLiftButton, CBackground); + ADDFN(CLongStickDispenser, CGameObject); + ADDFN(CMissiveOMat, CGameObject); + ADDFN(CMissiveOMatButton, CEditControl); + ADDFN(CMovieTester, CGameObject); + ADDFN(CMusicalInstrument, CBackground); + ADDFN(CMusicConsoleButton, CMusicPlayer); + ADDFN(CMusicRoomPhonograph, CRestaurantPhonograph); + ADDFN(CMusicRoomStopPhonographButton, CEjectPhonographButton); + ADDFN(CMusicSystemLock, CDropTarget); + ADDFN(CNavHelmet, CGameObject); + ADDFN(CNavHelmetOn, CGameObject); + ADDFN(CNavHelmetOff, CGameObject); + ADDFN(CNavigationComputer, CGameObject); + ADDFN(CNoNutBowl, CBackground); + ADDFN(CNoseHolder, CDropTarget); + ADDFN(CNullPortHole, CClickResponder); + ADDFN(CNutReplacer, CGameObject); + ADDFN(CPetDisabler, CGameObject); + ADDFN(CPhonograph, CMusicPlayer); + ADDFN(CPhonographLid, CGameObject); + ADDFN(CPlayMusicButton, CBackground); + ADDFN(CPlayOnAct, CBackground); + ADDFN(CPortHole, CGameObject); + ADDFN(CRecordPhonographButton, CBackground); + ADDFN(CReplacementEar, CBackground); + ADDFN(CReservedTable, CGameObject); + ADDFN(CRestaurantCylinderHolder, CDropTarget); + ADDFN(CRestaurantPhonograph, CPhonograph); + ADDFN(CSauceDispensor, CBackground); + ADDFN(CSearchPoint, CGameObject); + ADDFN(CSeasonBackground, CBackground); + ADDFN(CSeasonBarrel, CBackground); + ADDFN(CSeasonalAdjustment, CBackground); + ADDFN(CServiceElevatorWindow, CBackground); + ADDFN(CShipSetting, CBackground); + ADDFN(CShipSettingButton, CGameObject); + ADDFN(CShowCellpoints, CGameObject); + ADDFN(CSpeechDispensor, CBackground); + ADDFN(CSplashAnimation, CGameObject); + ADDFN(CStarlingPuret, CGameObject); + ADDFN(CStartAction, CBackground); + ADDFN(CStopPhonographButton, CBackground); + ADDFN(CSUBGlass, CGameObject); + ADDFN(CSUBWrapper, CGameObject); + ADDFN(CSweetBowl, CGameObject); + ADDFN(CTelevision, CBackground); + ADDFN(CThirdClassCanal, CBackground); + ADDFN(CThrowTVDownWell, CGameObject); + ADDFN(CTitaniaStillControl, CGameObject); + ADDFN(CTOWParrotNav, CGameObject); + ADDFN(CUpLighter, CDropTarget); + ADDFN(CUselessLever, CToggleButton); + ADDFN(CVolumeControl, CGameObject); + ADDFN(CWheelButton, CBackground); + ADDFN(CWheelHotSpot, CBackground); + ADDFN(CWheelSpin, CBackground); + ADDFN(CWheelSpinHorn, CWheelSpin); + ADDFN(CGondolierBase, CGameObject); + ADDFN(CGondolierChest, CGondolierBase); + ADDFN(CGondolierFace, CGondolierBase); + ADDFN(CGondolierMixer, CGondolierBase); + ADDFN(CGondolierSlider, CGondolierBase); + ADDFN(CMaitreDArmHolder, CDropTarget); + ADDFN(CMaitreDBody, CMaitreDProdReceptor); + ADDFN(CMaitreDLegs, CMaitreDProdReceptor); + ADDFN(CMaitreDProdReceptor, CGameObject); + ADDFN(CParrotLobbyController, CParrotLobbyObject); + ADDFN(CParrotLobbyLinkUpdater, CParrotLobbyObject); + ADDFN(CParrotLobbyObject, CGameObject); + ADDFN(CParrotLobbyViewObject, CParrotLobbyObject); + ADDFN(CParrotLoser, CGameObject); + ADDFN(CParrotNutBowlActor, CGameObject); + ADDFN(CParrotNutEater, CGameObject); + ADDFN(CParrotPerchHolder, CMultiDropTarget); + ADDFN(CParrotSuccUBus, CSuccUBus); + ADDFN(CParrotTrigger, CGameObject); + ADDFN(CPlayerMeetsParrot, CGameObject); + ADDFN(CPET, CGameObject); + ADDFN(CPETClass1, CGameObject); + ADDFN(CPETClass2, CGameObject); + ADDFN(CPETClass3, CGameObject); + ADDFN(CPETLift, CPETTransport); + ADDFN(CPETMonitor, CGameObject); + ADDFN(CPETPellerator, CPETTransport); + ADDFN(CPETPosition, CGameObject); + ADDFN(CPETSentinal, CGameObject); + ADDFN(CPETSounds, CGameObject); + ADDFN(CPETTransition, CGameObject); + ADDFN(CPETTransport, CGameObject); + ADDFN(CPickUp, CGameObject); + ADDFN(CPickUpBarGlass, CPickUp); + ADDFN(CPickUpHose, CPickUp); + ADDFN(CPickUpLemon, CPickUp); + ADDFN(CPickUpSpeechCentre, CPickUp); + ADDFN(CPickUpVisCentre, CPickUp); + ADDFN(CBarShelfVisCentre, CPlaceHolder); + ADDFN(CLemonOnBar, CPlaceHolder); + ADDFN(CPlaceHolder, CGameObject); + ADDFN(CTVOnBar, CPlaceHolder); + ADDFN(CArmchair, CSGTStateRoom); + ADDFN(CBasin, CSGTStateRoom); + ADDFN(CBedfoot, CSGTStateRoom); + ADDFN(CBedhead, CSGTStateRoom); + ADDFN(CChestOfDrawers, CSGTStateRoom); + ADDFN(CDesk, CSGTStateRoom); + ADDFN(CDeskchair, CSGTStateRoom); + ADDFN(CDrawer, CSGTStateRoom); + ADDFN(CSGTDoors, CGameObject); + ADDFN(SGTNav, CSGTStateRoom); + ADDFN(CSGTNavigation, CGameObject); + ADDFN(CSGTRestaurantDoors, CGameObject); + ADDFN(CSGTStateControl, CBackground); + ADDFN(CSGTStateRoom, CBackground); + ADDFN(CSGTTV, CSGTStateRoom); + ADDFN(CSGTUpperDoorsSound, CClickResponder); + ADDFN(CToilet, CSGTStateRoom); + ADDFN(CVase, CSGTStateRoom); + ADDFN(CWashstand, CSGTStateRoom); + + ADDFN(CGondolier, CTransport); + ADDFN(CLift, CTransport); + ADDFN(CLiftindicator, CLift); + ADDFN(CPellerator, CTransport); + ADDFN(CServiceElevator, CTransport); + ADDFN(CTransport, CMobile); + + ADDFN(CActButton, CSTButton); + ADDFN(CChangesSeasonButton, CSTButton); + ADDFN(CChevLeftOff, CToggleSwitch); + ADDFN(CChevLeftOn, CToggleSwitch); + ADDFN(CChevRightOff, CToggleSwitch); + ADDFN(CChevRightOn, CToggleSwitch); + ADDFN(CChevSendRecSwitch, CToggleSwitch); + ADDFN(CChevSwitch, CToggleSwitch); + ADDFN(CEditControl, CGameObject); + ADDFN(CElevatorButton, CSTButton); + ADDFN(CGetFromSucc, CToggleSwitch); + ADDFN(CHelmetOnOff, CToggleSwitch); + ADDFN(CHomePhoto, CToggleSwitch); + ADDFN(CIconNavAction, CToggleSwitch); + ADDFN(CIconNavButt, CPetGraphic); + ADDFN(CIconNavDown, CToggleSwitch); + ADDFN(CIconNavImage, CPetGraphic); + ADDFN(CIconNavLeft, CToggleSwitch); + ADDFN(CIconNavReceive, CPetGraphic); + ADDFN(CIconNavRight, CToggleSwitch); + ADDFN(CIconNavSend, CPetGraphic); + ADDFN(CIconNavUp, CToggleSwitch); + ADDFN(CKeybrdButt, CToggleSwitch); + ADDFN(CMoveObjectButton, CSTButton); + ADDFN(CMusicControl, CBackground); + ADDFN(CMusicSlider, CMusicControl); + ADDFN(CMusicSliderPitch, CMusicSlider); + ADDFN(CMusicSliderSpeed, CMusicSlider); + ADDFN(CMusicSwitch, CMusicControl); + ADDFN(CMusicSwitchInversion, CMusicSwitch); + ADDFN(CMusicSwitchReverse, CMusicSwitch); + ADDFN(CMusicVoiceMute, CMusicControl); + ADDFN(CPetControl, CGameObject); + ADDFN(CPetDragChev, CPetGraphic2); + ADDFN(CPetGraphic, CGameObject); + ADDFN(CPetGraphic2, CGameObject); + ADDFN(PETLeaf, CGameObject); + ADDFN(CPetModeOff, CToggleSwitch); + ADDFN(CPetModeOn, CToggleSwitch); + ADDFN(CPetModePanel, CToggleSwitch); + ADDFN(CPetPannel1, CPetGraphic); + ADDFN(CPetPannel2, CPetGraphic); + ADDFN(CPetPannel3, CPetGraphic); + ADDFN(CSendToSucc, CToggleSwitch); + ADDFN(CSGTSelector, CPetGraphic); + ADDFN(CSliderButton, CSTButton); + ADDFN(CSmallChevLeftOff, CToggleSwitch); + ADDFN(CSmallChevLeftOn, CToggleSwitch); + ADDFN(CSmallChevRightOff, CToggleSwitch); + ADDFN(CSmallChevRightOn, CToggleSwitch); + ADDFN(CStatusChangeButton, CSTButton); + ADDFN(CSTButton, CBackground); + ADDFN(CTextDown, CPetGraphic); + ADDFN(CTextSkrew, CPetGraphic); + ADDFN(CTextUp, CPetGraphic); + ADDFN(CToggleButton, CBackground); + ADDFN(CToggleSwitch, CGameObject); + + ADDFN(CActMsg, CMessage); + ADDFN(CActivationmsg, CMessage); + ADDFN(CAddHeadPieceMsg, CMessage); + ADDFN(CAnimateMaitreDMsg, CMessage); + ADDFN(CArboretumGateMsg, CMessage); + ADDFN(CArmPickedUpFromTableMsg, CMessage); + ADDFN(CAutoSoundEvent, CGameObject); + ADDFN(CBilgeAutoSoundEvent, CAutoSoundEvent); + ADDFN(CBilgeDispensorEvent, CAutoSoundEvent); + ADDFN(CBodyInBilgeRoomMsg, CMessage); + ADDFN(CBowlStateChangeMsg, CMessage); + ADDFN(CCarryObjectArrivedMsg, CMessage); + ADDFN(CChangeMusicMsg, CMessage); + ADDFN(CChangeSeasonMsg, CMessage); + ADDFN(CCheckAllPossibleCodes, CMessage); + ADDFN(CCheckChevCode, CMessage); + ADDFN(CChildDragEndMsg, CMessage); + ADDFN(CChildDragMoveMsg, CMessage); + ADDFN(CChildDragStartMsg, CMessage); + ADDFN(CClearChevPanelBits, CMessage); + ADDFN(CCorrectMusicPlayedMsg, CMessage); + ADDFN(CCreateMusicPlayerMsg, CMessage); + ADDFN(CCylinderHolderReadyMsg, CMessage); + ADDFN(CDeactivationMsg, CMessage); + ADDFN(CDeliverCCarryMsg, CMessage); + ADDFN(CDisableMaitreDProdReceptor, CMessage); + ADDFN(CDismissBotMsg, CMessage); + ADDFN(CDoffNavHelmet, CMessage); + ADDFN(CDonNavHelmet, CMessage); + ADDFN(CDoorAutoSoundEvent, CAutoSoundEvent); + ADDFN(CDoorbotNeededInElevatorMsg, CMessage); + ADDFN(CDoorbotNeededInHomeMsg, CMessage); + ADDFN(CDropObjectMsg, CMessage); + ADDFN(CDropZoneGotObjectMsg, CMessage); + ADDFN(CDropZoneLostObjectMsg, CMessage); + ADDFN(CEditControlMsg, CMessage); + ADDFN(CEnterNodeMsg, CMessage); + ADDFN(CEnterRoomMsg, CMessage); + ADDFN(CEnterViewMsg, CMessage); + ADDFN(CEjectCylinderMsg, CMessage); + ADDFN(CErasePhonographCylinderMsg, CMessage); + ADDFN(CFrameMsg, CMessage); + ADDFN(CFreshenCookieMsg, CMessage); + ADDFN(CGetChevClassBits, CMessage); + ADDFN(CGetChevClassNum, CMessage); + ADDFN(CGetChevCodeFromRoomNameMsg, CMessage); + ADDFN(CGetChevFloorBits, CMessage); + ADDFN(CGetChevFloorNum, CMessage); + ADDFN(CGetChevLiftBits, CMessage); + ADDFN(CGetChevLiftNum, CMessage); + ADDFN(CGetChevRoomBits, CMessage); + ADDFN(CGetChevRoomNum, CMessage); + ADDFN(CHoseConnectedMsg, CMessage); + ADDFN(CInitializeAnimMsg, CMessage); + ADDFN(CIsEarBowlPuzzleDone, CMessage); + ADDFN(CIsHookedOnMsg, CMessage); + ADDFN(CIsParrotPresentMsg, CMessage); + ADDFN(CKeyCharMsg, CMessage); + ADDFN(CLeaveNodeMsg, CMessage); + ADDFN(CLeaveRoomMsg, CMessage); + ADDFN(CLeaveViewMsg, CMessage); + ADDFN(CLemonFallsFromTreeMsg, CMessage); + ADDFN(CLightsMsg, CMessage); + ADDFN(CLoadSuccessMsg, CMessage); + ADDFN(CLockPhonographMsg, CMessage); + ADDFN(CMaitreDDefeatedMsg, CMessage); + ADDFN(CMaitreDHappyMsg, CMessage); + ADDFN(CMessage, CSaveableObject); + ADDFN(CMissiveOMatActionMsg, CMessage); + ADDFN(CMouseMsg, CMessage); + ADDFN(CMouseMoveMsg, CMouseMsg); + ADDFN(CMouseButtonMsg, CMouseMsg); + ADDFN(CMouseButtonDownMsg, CMouseButtonMsg); + ADDFN(CMouseButtonUpMsg, CMouseButtonMsg); + ADDFN(CMouseDoubleClickMsg, CMouseButtonMsg); + ADDFN(CMouseDragMsg, CMouseMsg); + ADDFN(CMouseDragStartMsg, CMouseDragMsg); + ADDFN(CMouseDragMoveMsg, CMouseDragMsg); + ADDFN(CMouseDragEndMsg, CMouseDragMsg); + ADDFN(CMoveToStartPosMsg, CMessage); + ADDFN(CMovieEndMsg, CMessage); + ADDFN(CMovieFrameMsg, CMessage); + ADDFN(CMusicHasStartedMsg, CMessage); + ADDFN(CMusicHasStoppedMsg, CMessage); + ADDFN(CMusicSettingChangedMsg, CMessage); + ADDFN(CNPCPlayAnimationMsg, CMessage); + ADDFN(CNPCPlayIdleAnimationMsg, CMessage); + ADDFN(CNPCPlayTalkingAnimationMsg, CMessage); + ADDFN(CNPCQueueIdleAnimMsg, CMessage); + ADDFN(CNutPuzzleMsg, CMessage); + ADDFN(COnSummonBotMsg, CMessage); + ADDFN(COpeningCreditsMsg, CMessage); + ADDFN(CPETDeliverMsg, CMessage); + ADDFN(CPETGainedObjectMsg, CMessage); + ADDFN(CPETHelmetOnOffMsg, CMessage); + ADDFN(CPETKeyboardOnOffMsg, CMessage); + ADDFN(CPETLostObjectMsg, CMessage); + ADDFN(CPETObjectSelectedMsg, CMessage); + ADDFN(CPETObjectStateMsg, CMessage); + ADDFN(CPETPhotoOnOffMsg, CMessage); + ADDFN(CPETPlaySoundMsg, CMessage); + ADDFN(CPETReceiveMsg, CMessage); + ADDFN(CPETSetStarDestinationMsg, CMessage); + ADDFN(CPETStarFieldLockMsg, CMessage); + ADDFN(CPETStereoFieldOnOffMsg, CMessage); + ADDFN(CPETTargetMsg, CMessage); + ADDFN(CPETUpMsg, CPETTargetMsg); + ADDFN(CPETDownMsg, CPETTargetMsg); + ADDFN(CPETLeftMsg, CPETTargetMsg); + ADDFN(CPETRightMsg, CPETTargetMsg); + ADDFN(CPETActivateMsg, CPETTargetMsg); + ADDFN(CPanningAwayFromParrotMsg, CMessage); + ADDFN(CParrotSpeakMsg, CMessage); + ADDFN(CParrotTriesChickenMsg, CMessage); + ADDFN(CPassOnDragStartMsg, CMessage); + ADDFN(CPhonographPlayMsg, CMessage); + ADDFN(CPhonographReadyToPlayMsg, CMessage); + ADDFN(CPhonographRecordMsg, CMessage); + ADDFN(CPhonographStopMsg, CMessage); + ADDFN(CPlayRangeMsg, CMessage); + ADDFN(CPlayerTriesRestaurantTableMsg, CMessage); + ADDFN(CEnterNodeMsg, CMessage); + ADDFN(CEnterRoomMsg, CMessage); + ADDFN(CEnterViewMsg, CMessage); + ADDFN(CPreSaveMsg, CMessage); + ADDFN(CProdMaitreDMsg, CMessage); + ADDFN(CPumpingMsg, CMessage); + ADDFN(CPutBotBackInHisBoxMsg, CMessage); + ADDFN(CPutParrotBackMsg, CMessage); + ADDFN(CPuzzleSolvedMsg, CMessage); + ADDFN(CQueryCylinderHolderMsg, CMessage); + ADDFN(CQueryCylinderMsg, CMessage); + ADDFN(CQueryCylinderNameMsg, CMessage); + ADDFN(CQueryCylinderTypeMsg, CMessage); + ADDFN(CQueryMusicControlSettingMsg, CMessage); + ADDFN(CQueryPhonographState, CMessage); + ADDFN(CRecordOntoCylinderMsg, CMessage); + ADDFN(CRemoveFromGameMsg, CMessage); + ADDFN(CReplaceBowlAndNutsMsg, CMessage); + ADDFN(CRestaurantMusicChanged, CMessage); + ADDFN(CSendCCarryMsg, CMessage); + ADDFN(CSenseWorkingMsg, CMessage); + ADDFN(CServiceElevatorDoor, CMessage); + ADDFN(CServiceElevatorFloorChangeMsg, CMessage); + ADDFN(CServiceElevatorFloorRequestMsg, CMessage); + ADDFN(CServiceElevatorMsg, CMessage); + ADDFN(CSetChevButtonImageMsg, CMessage); + ADDFN(CSetChevClassBits, CMessage); + ADDFN(CSetChevFloorBits, CMessage); + ADDFN(CSetChevLiftBits, CMessage); + ADDFN(CSetChevPanelBitMsg, CMessage); + ADDFN(CSetChevPanelButtonsMsg, CMessage); + ADDFN(CSetChevRoomBits, CMessage); + ADDFN(CSetFrameMsg, CMessage); + ADDFN(CSetMusicControlsMsg, CMessage); + ADDFN(CSetVarMsg, CMessage); + ADDFN(CSetVolumeMsg, CMessage); + ADDFN(CShipSettingMsg, CMessage); + ADDFN(CShowTextMsg, CMessage); + ADDFN(CSignalObject, CMessage); + ADDFN(CSpeechFallsFromTreeMsg, CMessage); + ADDFN(CStartMusicMsg, CMessage); + ADDFN(CStatusChangeMsg, CMessage); + ADDFN(CStopMusicMsg, CMessage); + ADDFN(CSubAcceptCCarryMsg, CMessage); + ADDFN(CSubDeliverCCarryMsg, CMessage); + ADDFN(CSubSendCCarryMsg, CMessage); + ADDFN(CSUBTransition, CMessage); + ADDFN(CSubTurnOffMsg, CMessage); + ADDFN(CSubTurnOnMsg, CMessage); + ADDFN(CSummonBotMsg, CMessage); + ADDFN(CSummonBotQueryMsg, CMessage); + ADDFN(CTakeHeadPieceMsg, CMessage); + ADDFN(CTextInputMsg, CMessage); + ADDFN(CTimeDilationMsg, CMessage); + ADDFN(CTimeMsg, CMessage); + ADDFN(CTimerMsg, CTimeMsg); + ADDFN(CTitleSequenceEndedMsg, CMessage); + ADDFN(CTransitMsg, CMessage); + ADDFN(CTranslateObjectMsg, CMessage); + ADDFN(CTransportMsg, CMessage); + ADDFN(CTriggerAutoMusicPlayerMsg, CMessage); + ADDFN(CTriggerNPCEvent, CMessage); + ADDFN(CTrueTalkGetAnimSetMsg, CMessage); + ADDFN(CTrueTalkGetAssetDetailsMsg, CMessage); + ADDFN(CTrueTalkGetStateValueMsg, CMessage); + ADDFN(CTrueTalkNotifySpeechEndedMsg, CMessage); + ADDFN(CTrueTalkNotifySpeechStartedMsg, CMessage); + ADDFN(CTrueTalkQueueUpAnimSetMsg, CMessage); + ADDFN(CTrueTalkSelfQueueAnimSetMsg, CMessage); + ADDFN(CTrueTalkTriggerActionMsg, CMessage); + ADDFN(CTurnOff, CMessage); + ADDFN(CTurnOn, CMessage); + ADDFN(CUse, CMessage); + ADDFN(CUseWithCharMsg, CMessage); + ADDFN(CUseWithOtherMsg, CMessage); + ADDFN(CVirtualKeyCharMsg, CMessage); + ADDFN(CVisibleMsg, CMessage); + + ADDFN(CEnterBombRoom, CMovePlayerTo); + ADDFN(CEnterBridge, CGameObject); + ADDFN(CEnterExitFirstClassState, CGameObject); + ADDFN(CEnterExitMiniLift, CSGTNavigation); + ADDFN(CEnterExitSecClassMiniLift, CGameObject); + ADDFN(CEnterExitView, CGameObject); + ADDFN(CEnterSecClassState, CGameObject); + ADDFN(CExitArboretum, CMovePlayerTo); + ADDFN(CExitBridge, CMovePlayerTo); + ADDFN(CExitLift, CGameObject); + ADDFN(CExitPellerator, CGameObject); + ADDFN(CExitStateRoom, CMovePlayerTo); + ADDFN(CExitTiania, CMovePlayerTo); + ADDFN(CMovePlayerInParrotRoom, CMovePlayerTo); + ADDFN(CMovePlayerTo, CGameObject); + ADDFN(CMovePlayerToFrom, CGameObject); + ADDFN(CMultiMove, CMovePlayerTo); + ADDFN(CPanFromPel, CMovePlayerTo); + ADDFN(CRestaurantPanHandler, CMovePlayerTo); + ADDFN(CScraliontisTable, CRestaurantPanHandler); + ADDFN(CRestrictedMove, CMovePlayerTo); + ADDFN(CTripDownCanal, CMovePlayerTo); + + ADDFN(CBarbot, CTrueTalkNPC); + ADDFN(CBellBot, CTrueTalkNPC); + ADDFN(CCallBot, CGameObject); + ADDFN(CCharacter, CGameObject); + ADDFN(CDeskbot, CTrueTalkNPC); + ADDFN(CDoorbot, CTrueTalkNPC); + ADDFN(CMaitreD, CTrueTalkNPC); + ADDFN(CLiftBot, CTrueTalkNPC); + ADDFN(CMobile, CCharacter); + ADDFN(CParrot, CTrueTalkNPC); + ADDFN(CRobotController, CGameObject); + ADDFN(CStarlings, CCharacter); + ADDFN(CSuccUBus, CTrueTalkNPC); + ADDFN(CSummonBots, CRobotController); + ADDFN(CTitania, CCharacter); + ADDFN(CTrueTalkNPC, CCharacter); + + ADDFN(CAutoMusicPlayer, CAutoMusicPlayerBase); + ADDFN(CAutoMusicPlayerBase, CGameObject); + ADDFN(CAutoSoundPlayer, CGameObject); + ADDFN(CAutoSoundPlayerADSR, CAutoSoundPlayer); + ADDFN(CBackgroundSoundMaker, CGameObject); + ADDFN(CBirdSong, CRoomAutoSoundPlayer); + ADDFN(CDomeFromTopOfWell, CViewAutoSoundPlayer); + ADDFN(CGondolierSong, CGameObject); + ADDFN(CEnterViewTogglesOtherMusic, CTriggerAutoMusicPlayer); + ADDFN(CGondolierSong, CRoomAutoSoundPlayer); + ADDFN(CMusicPlayer, CGameObject); + ADDFN(CNodeAutoSoundPlayer, CAutoSoundPlayer); + ADDFN(CRestrictedAutoMusicPlayer, CAutoMusicPlayer); + ADDFN(CRoomAutoSoundPlayer, CAutoSoundPlayer); + ADDFN(CRoomTriggerAutoMusicPlayer, CTriggerAutoMusicPlayer); + ADDFN(CSeasonNoises, CViewAutoSoundPlayer); + ADDFN(CSeasonalMusicPlayer, CAutoMusicPlayerBase); + ADDFN(CAutoMusicPlayer, CAutoMusicPlayerBase); + ADDFN(CAutoMusicPlayerBase, CAutoMusicPlayer); + ADDFN(CTitaniaSpeech, CGameObject); + ADDFN(CTriggerAutoMusicPlayer, CGameObject); + ADDFN(CViewAutoSoundPlayer, CAutoSoundPlayer); + ADDFN(CViewTogglesOtherMusic, CEnterViewTogglesOtherMusic); + ADDFN(CWaterLappingSounds, CRoomAutoSoundPlayer); + ADDFN(CStarControl, CGameObject); + ADDFN(CTimeEventInfo, ListItem); +} + +void CSaveableObject::freeClassList() { + Common::List<ClassDef *>::iterator i; + for (i = _classDefs->begin(); i != _classDefs->end(); ++i) + delete *i; + + delete _classDefs; + delete _classList; +} + +CSaveableObject *CSaveableObject::createInstance(const Common::String &name) { + return (*_classList)[name](); +} + +void CSaveableObject::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); +} + +void CSaveableObject::load(SimpleFile *file) { + file->readNumber(); +} + +void CSaveableObject::saveHeader(SimpleFile *file, int indent) { + file->writeClassStart(getType()->_className, indent); +} + +void CSaveableObject::saveFooter(SimpleFile *file, int indent) { + file->writeClassEnd(indent); +} + +bool CSaveableObject::isInstanceOf(const ClassDef *classDef) const { + for (ClassDef *def = getType(); def != nullptr; def = def->_parent) { + if (def == classDef) + return true; + } + + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/saveable_object.h b/engines/titanic/core/saveable_object.h new file mode 100644 index 0000000000..6d80ad121d --- /dev/null +++ b/engines/titanic/core/saveable_object.h @@ -0,0 +1,110 @@ +/* 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_SAVEABLE_OBJECT_H +#define TITANIC_SAVEABLE_OBJECT_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/hash-str.h" +#include "common/list.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +class CSaveableObject; + +class ClassDef { +public: + const char *_className; + ClassDef *_parent; +public: + ClassDef(const char *className, ClassDef *parent) : + _className(className), _parent(parent) {} + virtual ~ClassDef() {} + virtual CSaveableObject *create(); +}; + +template<typename T> +class TypeTemplate : public ClassDef { +public: + TypeTemplate(const char *className, ClassDef *parent) : + ClassDef(className, parent) {} + virtual CSaveableObject *create() { return new T(); } +}; + +#define CLASSDEF \ + static ClassDef *_type; \ + virtual ClassDef *getType() const { return _type; } + +class CSaveableObject { + typedef CSaveableObject *(*CreateFunction)(); +private: + static Common::List<ClassDef *> *_classDefs; + static Common::HashMap<Common::String, CreateFunction> *_classList; +public: + /** + * Sets up the list of saveable object classes + */ + static void initClassList(); + + /** + * Free the list of saveable object classes + */ + static void freeClassList(); + + /** + * Creates a new instance of a saveable object class + */ + static CSaveableObject *createInstance(const Common::String &name); +public: + CLASSDEF + virtual ~CSaveableObject() {} + + bool isInstanceOf(const ClassDef *classDef) const; + + /** + * 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); + + /** + * Write out a header definition for the class to file + * prior to saving the actual data for the class + */ + virtual void saveHeader(SimpleFile *file, int indent); + + /** + * Writes out a footer for the class after it's data has + * been written to file + */ + virtual void saveFooter(SimpleFile *file, int indent); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SAVEABLE_OBJECT_H */ diff --git a/engines/titanic/core/static_image.cpp b/engines/titanic/core/static_image.cpp new file mode 100644 index 0000000000..977009e750 --- /dev/null +++ b/engines/titanic/core/static_image.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/core/static_image.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CStaticImage, CGameObject); + +void CStaticImage::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CStaticImage::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/static_image.h b/engines/titanic/core/static_image.h new file mode 100644 index 0000000000..7a715a84fa --- /dev/null +++ b/engines/titanic/core/static_image.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_STATIC_IMAGE_H +#define TITANIC_STATIC_IMAGE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CStaticImage : 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_STATIC_IMAGE_H */ diff --git a/engines/titanic/core/tree_item.cpp b/engines/titanic/core/tree_item.cpp new file mode 100644 index 0000000000..86c34cab8b --- /dev/null +++ b/engines/titanic/core/tree_item.cpp @@ -0,0 +1,288 @@ +/* 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/core/tree_item.h" +#include "titanic/core/dont_save_file_item.h" +#include "titanic/core/file_item.h" +#include "titanic/core/game_object.h" +#include "titanic/core/game_object_desc_item.h" +#include "titanic/core/link_item.h" +#include "titanic/core/mail_man.h" +#include "titanic/core/named_item.h" +#include "titanic/core/node_item.h" +#include "titanic/core/project_item.h" +#include "titanic/core/view_item.h" +#include "titanic/core/room_item.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/game_manager.h" +#include "titanic/game/placeholder/place_holder.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CTreeItem, CMessageTarget); + +CTreeItem::CTreeItem() : _parent(nullptr), _firstChild(nullptr), + _nextSibling(nullptr), _priorSibling(nullptr), _field14(0) { +} + +void CTreeItem::dump(int indent) { + CString line = dumpItem(indent); + debug("%s", line.c_str()); + + CTreeItem *item = getFirstChild(); + while (item) { + item->dump(indent + 1); + + item = item->getNextSibling(); + } +} + +CString CTreeItem::dumpItem(int indent) const { + CString result; + for (int idx = 0; idx < indent; ++idx) + result += '\t'; + result += getType()->_className; + + return result; +} + +void CTreeItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + CMessageTarget::save(file, indent); +} + +void CTreeItem::load(SimpleFile *file) { + file->readNumber(); + CMessageTarget::load(file); +} + +bool CTreeItem::isFileItem() const { + return isInstanceOf(CFileItem::_type); +} + +bool CTreeItem::isRoomItem() const { + return isInstanceOf(CRoomItem::_type); +} + +bool CTreeItem::isNodeItem() const { + return isInstanceOf(CNodeItem::_type); +} + +bool CTreeItem::isViewItem() const { + return isInstanceOf(CViewItem::_type); +} + +bool CTreeItem::isLinkItem() const { + return isInstanceOf(CLinkItem::_type); +} + +bool CTreeItem::isPlaceHolderItem() const { + return isInstanceOf(CPlaceHolder::_type); +} + +bool CTreeItem::isNamedItem() const { + return isInstanceOf(CNamedItem::_type); +} + +bool CTreeItem::isGameObject() const { + return isInstanceOf(CGameObject::_type); +} + +bool CTreeItem::isGameObjectDescItem() const { + return isInstanceOf(CGameObjectDescItem::_type); +} + +CGameManager *CTreeItem::getGameManager() const { + return _parent ? _parent->getGameManager() : nullptr; +} + +CProjectItem *CTreeItem::getRoot() const { + CTreeItem *parent = getParent(); + + if (parent) { + do { + parent = parent->getParent(); + } while (parent->getParent()); + } + + return dynamic_cast<CProjectItem *>(parent); +} + +CTreeItem *CTreeItem::getLastSibling() { + CTreeItem *item = this; + while (item->getNextSibling()) + item = item->getNextSibling(); + + return item; +} + +CTreeItem *CTreeItem::getLastChild() const { + if (!_firstChild) + return nullptr; + return _firstChild->getLastSibling(); +} + +CTreeItem *CTreeItem::scan(CTreeItem *item) const { + if (_firstChild) + return _firstChild; + + const CTreeItem *treeItem = this; + while (treeItem != item) { + if (treeItem->_nextSibling) + return treeItem->_nextSibling; + + treeItem = treeItem->_parent; + if (!treeItem) + break; + } + + return nullptr; +} + +CTreeItem *CTreeItem::findChildInstanceOf(ClassDef *classDef) const { + for (CTreeItem *treeItem = _firstChild; treeItem; treeItem = treeItem->getNextSibling()) { + if (treeItem->isInstanceOf(classDef)) + return treeItem; + } + + return nullptr; +} + +CTreeItem *CTreeItem::findNextInstanceOf(ClassDef *classDef, CTreeItem *startItem) const { + CTreeItem *treeItem = startItem ? startItem->getNextSibling() : getFirstChild(); + + for (; treeItem; treeItem = treeItem->getNextSibling()) { + if (treeItem->isInstanceOf(classDef)) + return treeItem; + } + + return nullptr; +} + +void CTreeItem::addUnder(CTreeItem *newParent) { + if (newParent->_firstChild) + addSibling(newParent->_firstChild->getLastSibling()); + else + setParent(newParent); +} + +void CTreeItem::setParent(CTreeItem *newParent) { + _parent = newParent; + _priorSibling = nullptr; + _nextSibling = newParent->_firstChild; + + if (newParent->_firstChild) + newParent->_firstChild->_priorSibling = this; + newParent->_firstChild = this; +} + +void CTreeItem::addSibling(CTreeItem *item) { + _priorSibling = item; + _nextSibling = item->_nextSibling; + _parent = item->_parent; + + if (item->_nextSibling) + item->_nextSibling->_priorSibling = this; + item->_nextSibling = this; +} + +void CTreeItem::moveUnder(CTreeItem *newParent) { + if (newParent) { + detach(); + addUnder(newParent); + } +} + +void CTreeItem::destroyAll() { + destroyChildren(); + detach(); + delete this; +} + +int CTreeItem::destroyChildren() { + if (!_firstChild) + return 0; + + CTreeItem *item = _firstChild, *child, *nextSibling; + int total = 0; + + do { + child = item->_firstChild; + nextSibling = item->_nextSibling; + + if (child) + total += item->destroyChildren(); + item->detach(); + delete item; + ++total; + } while ((item = nextSibling) != nullptr); + + return total; +} + +void CTreeItem::detach() { + // Delink this item from any prior and/or next siblings + if (_priorSibling) + _priorSibling->_nextSibling = _nextSibling; + if (_nextSibling) + _nextSibling->_priorSibling = _priorSibling; + + if (_parent && _parent->_firstChild == this) + _parent->_firstChild = _nextSibling; + + _priorSibling = _nextSibling = _parent = nullptr; +} + +void CTreeItem::attach(CTreeItem *item) { + _nextSibling = item; + _priorSibling = item->_priorSibling; + _parent = item->_parent; + + if (item->_priorSibling) + item->_priorSibling->_nextSibling = this; + + item->_priorSibling = this; + if (item->_parent && !item->_parent->_firstChild) + item->_parent->_firstChild = this; +} + +CNamedItem *CTreeItem::findByName(const CString &name, bool subMatch) { + CString nameLower = name; + nameLower.toLowercase(); + + for (CTreeItem *treeItem = this; treeItem; treeItem = treeItem->scan(this)) { + CString itemName = treeItem->getName(); + itemName.toLowercase(); + + if (subMatch) { + if (itemName.left(name.size()).compareTo(nameLower)) + return dynamic_cast<CNamedItem *>(treeItem); + } else { + if (!itemName.compareTo(nameLower)) + return dynamic_cast<CNamedItem *>(treeItem); + } + } + + return nullptr; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/tree_item.h b/engines/titanic/core/tree_item.h new file mode 100644 index 0000000000..e92f5cda49 --- /dev/null +++ b/engines/titanic/core/tree_item.h @@ -0,0 +1,265 @@ +/* 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_TREE_ITEM_H +#define TITANIC_TREE_ITEM_H + +#include "titanic/core/message_target.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +class CGameManager; +class CMovieClipList; +class CNamedItem; +class CProjectItem; +class CScreenManager; +class CViewItem; + +class CTreeItem: public CMessageTarget { + friend class CMessage; + DECLARE_MESSAGE_MAP; +private: + CTreeItem *_parent; + CTreeItem *_nextSibling; + CTreeItem *_priorSibling; + CTreeItem *_firstChild; + int _field14; +public: + CLASSDEF; + CTreeItem(); + + + /** + * Dump the item and any of it's children + */ + void dump(int indent); + + /** + * Dump the item + */ + virtual CString dumpItem(int indent) const; + + /** + * 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); + + /** + * Get the game manager for the project + */ + virtual CGameManager *getGameManager() const; + + /** + * Returns true if the item is a file item + */ + virtual bool isFileItem() const; + + /** + * Returns true if the item is a room item + */ + virtual bool isRoomItem() const; + + /** + * Returns true if the item is a node item + */ + virtual bool isNodeItem() const; + + /** + * Returns true if the item is a view item + */ + virtual bool isViewItem() const; + + /** + * Returns true if the item is a link item + */ + virtual bool isLinkItem() const; + + /** + * Returns true if the item is a placeholder item + */ + virtual bool isPlaceHolderItem() const; + + /** + * Returns true if the item is a named item + */ + virtual bool isNamedItem() const; + + /** + * Returns true if the item is a game object + */ + virtual bool isGameObject() const; + + /** + * Returns true if the item is a game object desc item + */ + virtual bool isGameObjectDescItem() const; + + /** + * Gets the name of the item, if any + */ + virtual const CString getName() const { return CString(); } + + /** + * Returns true if the item's name matches a passed name + */ + virtual bool isEquals(const CString &name, int maxLen = 0) const { return false; } + + /** + * Compares the name of the item to a passed name + */ + virtual int compareTo(const CString &name, int maxLen = 0) const { return false; } + + /** + * Returns the clip list, if any, associated with the item + */ + virtual const CMovieClipList *getMovieClips() const { return nullptr; } + + /** + * Returns true if the given item connects to another specified view + */ + virtual bool connectsTo(CViewItem *destView) const { return false; } + + /** + * Allows the item to draw itself + */ + virtual void draw(CScreenManager *screenManager) {} + + /** + * Gets the bounds occupied by the item + */ + virtual Rect getBounds() const { return Rect(); } + + /** + * Called when the view changes + */ + virtual void viewChange() {} + + /** + * Get the parent for the given item + */ + CTreeItem *getParent() const { return _parent; } + + /** + * Jumps up through the parents to find the root item + */ + CProjectItem *getRoot() const; + + /** + * Get the next sibling + */ + CTreeItem *getNextSibling() const { return _nextSibling; } + + /** + * Get the prior sibling + */ + CTreeItem *getPriorSibling() const { return _priorSibling; } + + /** + * Get the last sibling of this sibling + */ + CTreeItem *getLastSibling(); + + /** + * Get the first child of the item, if any + */ + CTreeItem *getFirstChild() const { return _firstChild; } + + /** + * Get the last child of the item, if any + */ + CTreeItem *getLastChild() const; + + /** + * Given all the recursive children of the tree item, gives the next + * item in sequence to the passed starting item + */ + CTreeItem *scan(CTreeItem *item) const; + + /** + * Find the first child item that is of a given type + */ + CTreeItem *findChildInstanceOf(ClassDef *classDef) const; + + /** + * Find the next sibling item that is of the given type + */ + CTreeItem *findNextInstanceOf(ClassDef *classDef, CTreeItem *startItem) const; + + /** + * Adds the item under another tree item + */ + void addUnder(CTreeItem *newParent); + + /** + * Sets the parent for the item + */ + void setParent(CTreeItem *newParent); + + /** + * Adds the item as a sibling of another item + */ + void addSibling(CTreeItem *item); + + /** + * Moves the tree item to be under another parent + */ + void moveUnder(CTreeItem *newParent); + + /** + * Destroys both the item as well as any of it's children + */ + void destroyAll(); + + /** + * Destroys all child tree items under this one. + * @returns Total number of tree items recursively removed + */ + int destroyChildren(); + + /** + * Detach the tree item from any other associated tree items + */ + void detach(); + + /** + * Attaches a tree item to a new node + */ + void attach(CTreeItem *item); + + /** + * Finds a tree item by name + * @param name Name to find + * @param subMatch If false, does an exact name match. + * If false, matches any item that starts with the given name + */ + CNamedItem *findByName(const CString &name, bool subMatch = false); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TREE_ITEM_H */ diff --git a/engines/titanic/core/turn_on_object.cpp b/engines/titanic/core/turn_on_object.cpp new file mode 100644 index 0000000000..221602bb7b --- /dev/null +++ b/engines/titanic/core/turn_on_object.cpp @@ -0,0 +1,59 @@ +/* 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/core/turn_on_object.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CTurnOnObject, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +CTurnOnObject::CTurnOnObject() : CBackground(), _msgName("NULL") { +} + +void CTurnOnObject::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_msgName, indent); + + CBackground::save(file, indent); +} + +void CTurnOnObject::load(SimpleFile *file) { + file->readNumber(); + _msgName = file->readString(); + + CBackground::load(file); +} + +bool CTurnOnObject::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CTurnOnObject::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + CTurnOn turnOn; + turnOn.execute(_msgName); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/turn_on_object.h b/engines/titanic/core/turn_on_object.h new file mode 100644 index 0000000000..0f7cd76382 --- /dev/null +++ b/engines/titanic/core/turn_on_object.h @@ -0,0 +1,53 @@ +/* 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_TURN_ON_OBJECT_H +#define TITANIC_TURN_ON_OBJECT_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CTurnOnObject : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +protected: + CString _msgName; +public: + CLASSDEF; + CTurnOnObject(); + + /** + * 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_TURN_ON_OBJECT_H */ diff --git a/engines/titanic/core/turn_on_play_sound.cpp b/engines/titanic/core/turn_on_play_sound.cpp new file mode 100644 index 0000000000..2f9dba24a6 --- /dev/null +++ b/engines/titanic/core/turn_on_play_sound.cpp @@ -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. + * + */ + +#include "titanic/core/turn_on_play_sound.h" + +namespace Titanic { + +CTurnOnPlaySound::CTurnOnPlaySound() : CTurnOnObject(), + _string3("NULL"), _fieldF8(80), _fieldFC(0) { +} + +void CTurnOnPlaySound::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string3, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_fieldFC, indent); + + CTurnOnObject::save(file, indent); +} + +void CTurnOnPlaySound::load(SimpleFile *file) { + file->readNumber(); + _string3 = file->readString(); + _fieldF8 = file->readNumber(); + _fieldFC = file->readNumber(); + + CTurnOnObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/turn_on_play_sound.h b/engines/titanic/core/turn_on_play_sound.h new file mode 100644 index 0000000000..1164135071 --- /dev/null +++ b/engines/titanic/core/turn_on_play_sound.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_TURN_ON_PLAY_SOUND_H +#define TITANIC_TURN_ON_PLAY_SOUND_H + +#include "titanic/core/turn_on_object.h" + +namespace Titanic { + +class CTurnOnPlaySound : public CTurnOnObject { +private: + CString _string3; + int _fieldF8; + int _fieldFC; +public: + CLASSDEF; + CTurnOnPlaySound(); + + /** + * 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_TURN_ON_PLAY_SOUND_H */ diff --git a/engines/titanic/core/turn_on_turn_off.cpp b/engines/titanic/core/turn_on_turn_off.cpp new file mode 100644 index 0000000000..d43ddf7038 --- /dev/null +++ b/engines/titanic/core/turn_on_turn_off.cpp @@ -0,0 +1,53 @@ +/* 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/core/turn_on_turn_off.h" + +namespace Titanic { + +CTurnOnTurnOff::CTurnOnTurnOff() : CBackground(), _fieldE0(0), + _fieldE4(0), _fieldE8(0), _fieldEC(0), _fieldF0(0) { +} + +void CTurnOnTurnOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + + CBackground::save(file, indent); +} + +void CTurnOnTurnOff::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/turn_on_turn_off.h b/engines/titanic/core/turn_on_turn_off.h new file mode 100644 index 0000000000..adca6876ff --- /dev/null +++ b/engines/titanic/core/turn_on_turn_off.h @@ -0,0 +1,54 @@ +/* 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_TURN_ON_TURN_OFF_H +#define TITANIC_TURN_ON_TURN_OFF_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CTurnOnTurnOff : public CBackground { +private: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _fieldF0; +public: + CLASSDEF; + CTurnOnTurnOff(); + + /** + * 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_TURN_ON_TURN_OFF_H */ diff --git a/engines/titanic/core/view_item.cpp b/engines/titanic/core/view_item.cpp new file mode 100644 index 0000000000..03e2753839 --- /dev/null +++ b/engines/titanic/core/view_item.cpp @@ -0,0 +1,332 @@ +/* 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/game_manager.h" +#include "titanic/support/screen_manager.h" +#include "titanic/core/project_item.h" +#include "titanic/core/room_item.h" +#include "titanic/core/view_item.h" +#include "titanic/messages/messages.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CViewItem, CNamedItem) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(MouseDoubleClickMsg) + ON_MESSAGE(MouseMoveMsg) +END_MESSAGE_MAP() + +CViewItem::CViewItem() : CNamedItem() { + Common::fill(&_buttonUpTargets[0], &_buttonUpTargets[4], (CTreeItem *)nullptr); + _field24 = 0; + _angle = 0.0; + _viewNumber = 0; + setAngle(0.0); +} + +void CViewItem::setAngle(double angle) { + _angle = angle; + _viewPos.x = (int16)(cos(_angle) * 30.0); + _viewPos.y = (int16)(sin(_angle) * -30.0); +} + +void CViewItem::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + _resourceKey.save(file, indent); + file->writeQuotedLine("V", indent); + file->writeFloatLine(_angle, indent + 1); + file->writeNumberLine(_viewNumber, indent + 1); + + CNamedItem::save(file, indent); +} + +void CViewItem::load(SimpleFile *file) { + int val = file->readNumber(); + + switch (val) { + case 1: + _resourceKey.load(file); + // Deliberate fall-through + + default: + file->readBuffer(); + setAngle(file->readFloat()); + _viewNumber = file->readNumber(); + break; + } + + CNamedItem::load(file); +} + +bool CViewItem::getResourceKey(CResourceKey *key) { + *key = _resourceKey; + CString filename = key->exists(); + return !filename.empty(); +} + +void CViewItem::leaveView(CViewItem *newView) { + // Only do the processing if we've been passed a view, and it's not the same + if (newView && newView != this) { + CLeaveViewMsg viewMsg(this, newView); + viewMsg.execute(this, nullptr, MSGFLAG_SCAN); + + CNodeItem *oldNode = findNode(); + CNodeItem *newNode = newView->findNode(); + if (newNode != oldNode) { + CLeaveNodeMsg nodeMsg(oldNode, newNode); + nodeMsg.execute(oldNode, nullptr, MSGFLAG_SCAN); + + CRoomItem *oldRoom = oldNode->findRoom(); + CRoomItem *newRoom = newNode->findRoom(); + if (newRoom != oldRoom) { + CGameManager *gm = getGameManager(); + if (gm) + gm->viewChange(); + + CLeaveRoomMsg roomMsg(oldRoom, newRoom); + roomMsg.execute(oldRoom, nullptr, MSGFLAG_SCAN); + } + } + } +} + +void CViewItem::preEnterView(CViewItem *newView) { + // Only do the processing if we've been passed a view, and it's not the same + if (newView && newView != this) { + CPreEnterViewMsg viewMsg(this, newView); + viewMsg.execute(this, nullptr, MSGFLAG_SCAN); + + CNodeItem *oldNode = findNode(); + CNodeItem *newNode = newView->findNode(); + if (newNode != oldNode) { + CPreEnterNodeMsg nodeMsg(oldNode, newNode); + nodeMsg.execute(oldNode, nullptr, MSGFLAG_SCAN); + + CRoomItem *oldRoom = oldNode->findRoom(); + CRoomItem *newRoom = newNode->findRoom(); + if (newRoom != oldRoom) { + CPreEnterRoomMsg roomMsg(oldRoom, newRoom); + roomMsg.execute(oldRoom, nullptr, MSGFLAG_SCAN); + } + } + } +} + +void CViewItem::enterView(CViewItem *newView) { + // Only do the processing if we've been passed a view, and it's not the same + if (newView && newView != this) { + CEnterViewMsg viewMsg(this, newView); + viewMsg.execute(this, nullptr, MSGFLAG_SCAN); + + CNodeItem *oldNode = findNode(); + CNodeItem *newNode = newView->findNode(); + if (newNode != oldNode) { + CEnterNodeMsg nodeMsg(oldNode, newNode); + nodeMsg.execute(oldNode, nullptr, MSGFLAG_SCAN); + + CRoomItem *oldRoom = oldNode->findRoom(); + CRoomItem *newRoom = newNode->findRoom(); + + CPetControl *petControl = nullptr; + if (newRoom != nullptr) { + petControl = newRoom->getRoot()->getPetControl(); + if (petControl) + petControl->enterNode(newNode); + } + + if (newRoom != oldRoom) { + CEnterRoomMsg roomMsg(oldRoom, newRoom); + roomMsg.execute(oldRoom, nullptr, MSGFLAG_SCAN); + + if (petControl) + petControl->enterRoom(newRoom); + } + } + } +} + +CLinkItem *CViewItem::findLink(CViewItem *newView) { + for (CTreeItem *treeItem = getFirstChild(); treeItem; + treeItem = scan(treeItem)) { + CLinkItem *link = static_cast<CLinkItem *>(treeItem); + if (link && link->connectsTo(newView)) + return link; + } + + return nullptr; +} + +bool CViewItem::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (msg->_buttons & MB_LEFT) { + if (!handleMouseMsg(msg, true)) { + CGameManager *gm = getGameManager(); + if (gm->test54()) { + findNode()->findRoom(); + + CLinkItem *linkItem = dynamic_cast<CLinkItem *>( + findChildInstanceOf(CLinkItem::_type)); + while (linkItem) { + if (linkItem->_bounds.contains(msg->_mousePos)) { + gm->_gameState.triggerLink(linkItem); + return true; + } + + linkItem = dynamic_cast<CLinkItem *>( + findNextInstanceOf(CLinkItem::_type, linkItem)); + } + } + } + } + + return true; +} + +bool CViewItem::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (msg->_buttons & MB_LEFT) + handleMouseMsg(msg, false); + + return true; +} + +bool CViewItem::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + if (msg->_buttons & MB_LEFT) + handleMouseMsg(msg, false); + + return true; +} + +bool CViewItem::MouseMoveMsg(CMouseMoveMsg *msg) { + CScreenManager *screenManager = CScreenManager::_screenManagerPtr; + uint changeCount = screenManager->_mouseCursor->getChangeCount(); + + if (handleMouseMsg(msg, true)) { + // If the cursor hasn't been set in the call to handleMouseMsg, + // then reset it back to the default arrow cursor + if (screenManager->_mouseCursor->getChangeCount() == changeCount) + screenManager->_mouseCursor->setCursor(CURSOR_ARROW); + } else { + // Iterate through each link item, and if any is highlighted, + // change the mouse cursor to the designated cursor for the item + CTreeItem *treeItem = getFirstChild(); + while (treeItem) { + CLinkItem *linkItem = dynamic_cast<CLinkItem *>(treeItem); + if (linkItem && linkItem->_bounds.contains(msg->_mousePos)) { + screenManager->_mouseCursor->setCursor(linkItem->_cursorId); + return true; + } + + treeItem = treeItem->getNextSibling(); + } + + if (!handleMouseMsg(msg, false) || (screenManager->_mouseCursor->getChangeCount() == changeCount)) + screenManager->_mouseCursor->setCursor(CURSOR_ARROW); + } + + return true; +} + +bool CViewItem::handleMouseMsg(CMouseMsg *msg, bool flag) { + CMouseButtonUpMsg *upMsg = dynamic_cast<CMouseButtonUpMsg *>(msg); + if (upMsg) { + handleButtonUpMsg(upMsg); + return true; + } + + Common::Array<CGameObject *> gameObjects; + for (CTreeItem *treeItem = scan(this); treeItem; treeItem = treeItem->scan(this)) { + CGameObject *gameObject = dynamic_cast<CGameObject *>(treeItem); + if (gameObject) { + if (gameObject->checkPoint(msg->_mousePos, false, true) && + (!flag || !gameObject->_field60)) { + if (gameObjects.size() < 256) + gameObjects.push_back(gameObject); + } + } + } + + const CMouseMoveMsg *moveMsg = dynamic_cast<const CMouseMoveMsg *>(msg); + if (moveMsg) { + if (gameObjects.size() == 0) + return false; + + for (int idx = (int)gameObjects.size() - 1; idx >= 0; ++idx) { + if (gameObjects[idx]->_cursorId != CURSOR_IGNORE) { + CScreenManager::_screenManagerPtr->_mouseCursor->setCursor(gameObjects[idx]->_cursorId); + break; + } + } + } + if (gameObjects.size() == 0) + return false; + + bool result = false; + for (int idx = (int)gameObjects.size() - 1; idx >= 0; --idx) { + if (msg->execute(gameObjects[idx])) { + if (msg->isButtonDownMsg()) + _buttonUpTargets[msg->_buttons >> 1] = gameObjects[idx]; + return true; + } + + if (CMouseMsg::isSupportedBy(gameObjects[idx])) + result = true; + } + + return result; +} + +void CViewItem::handleButtonUpMsg(CMouseButtonUpMsg *msg) { + CTreeItem *&target = _buttonUpTargets[msg->_buttons >> 1]; + + if (target) { + msg->execute(target); + target = nullptr; + } +} + +void CViewItem::getPosition(double &xp, double &yp, double &zp) { + // Get the position of the owning node within the room + CNodeItem *node = findNode(); + node->getPosition(xp, yp, zp); + + // Adjust the position slightly to compensate for view's angle, + // ensuring different direction views don't all have the same position + xp += cos(_angle) * 0.5; + yp -= sin(_angle) * 0.5; +} + +CString CViewItem::getFullViewName() const { + CNodeItem *node = findNode(); + CRoomItem *room = node->findRoom(); + + return CString::format("%s.%s.%s", room->getName().c_str(), + node->getName().c_str(), getName().c_str()); +} + +CString CViewItem::getNodeViewName() const { + CNodeItem *node = findNode(); + + return CString::format("%s.%s", node->getName().c_str(), getName().c_str()); +} + +} // End of namespace Titanic diff --git a/engines/titanic/core/view_item.h b/engines/titanic/core/view_item.h new file mode 100644 index 0000000000..ceb8a020da --- /dev/null +++ b/engines/titanic/core/view_item.h @@ -0,0 +1,122 @@ +/* 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_VIEW_ITEM_H +#define TITANIC_VIEW_ITEM_H + +#include "titanic/core/link_item.h" +#include "titanic/core/named_item.h" +#include "titanic/core/resource_key.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CViewItem : public CNamedItem { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool MouseMoveMsg(CMouseMoveMsg *msg); + bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); +private: + CTreeItem *_buttonUpTargets[4]; +private: + /** + * Sets the angle of the view relative to the node it belongs to + */ + void setAngle(double angle); + + /** + * Called to handle mouse messagaes on the view + */ + bool handleMouseMsg(CMouseMsg *msg, bool flag); + + /** + * Handles mouse button up messages + */ + void handleButtonUpMsg(CMouseButtonUpMsg *msg); +protected: + int _field24; + CResourceKey _resourceKey; + Point _viewPos; +public: + int _viewNumber; + double _angle; +public: + CLASSDEF; + CViewItem(); + + /** + * 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); + + /** + * Get the resource key for the view + */ + bool getResourceKey(CResourceKey *key); + + /** + * Called when leaving the view + */ + void leaveView(CViewItem *newView); + + /** + * Called on an old view just left, and about to enter a new view + */ + void preEnterView(CViewItem *newView); + + /** + * Called when a new view is being entered + */ + void enterView(CViewItem *newView); + + /** + * Finds a link which connects to another designated view + */ + CLinkItem *findLink(CViewItem *newView); + + /** + * Return the full Id of the current view in a + * room.node.view tuplet form + */ + CString getFullViewName() const; + + /** + * Return the Id of the current view in a + * room.node.view tuplet form + */ + CString getNodeViewName() const; + + /** + * Gets the relative position of the view within the owning room + */ + void getPosition(double &xp, double &yp, double &zp); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_NAMED_ITEM_H */ diff --git a/engines/titanic/debugger.cpp b/engines/titanic/debugger.cpp new file mode 100644 index 0000000000..37fc546851 --- /dev/null +++ b/engines/titanic/debugger.cpp @@ -0,0 +1,263 @@ +/* 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/debugger.h" +#include "titanic/titanic.h" +#include "titanic/core/tree_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +Debugger::Debugger(TitanicEngine *vm) : GUI::Debugger(), _vm(vm) { + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("dump", WRAP_METHOD(Debugger, cmdDump)); + registerCmd("room", WRAP_METHOD(Debugger, cmdRoom)); + registerCmd("pet", WRAP_METHOD(Debugger, cmdPET)); + registerCmd("item", WRAP_METHOD(Debugger, cmdItem)); +} + +int Debugger::strToInt(const char *s) { + if (!*s) + // No string at all + return 0; + else if (toupper(s[strlen(s) - 1]) != 'H') + // Standard decimal string + return atoi(s); + + // Hexadecimal string + uint tmp = 0; + int read = sscanf(s, "%xh", &tmp); + if (read < 1) + error("strToInt failed on string \"%s\"", s); + return (int)tmp; +} + +CRoomItem *Debugger::findRoom(const char *name) { + CTreeItem *root = g_vm->_window->_gameManager->_project; + CRoomItem *roomItem = dynamic_cast<CRoomItem *>(root->findByName(name)); + if (roomItem) + return roomItem; + + int roomNumber = strToInt(name); + for (CTreeItem *treeItem = root; treeItem; treeItem = treeItem->scan(root)) { + roomItem = dynamic_cast<CRoomItem *>(treeItem); + if (roomItem && roomItem->_roomNumber == roomNumber) + return roomItem; + } + + return nullptr; +} + +CNodeItem *Debugger::findNode(CRoomItem *room, const char *name) { + CNodeItem *nodeItem = dynamic_cast<CNodeItem *>(room->findByName(name)); + if (nodeItem) + return nodeItem; + + int nodeNumber = strToInt(name); + nodeItem = dynamic_cast<CNodeItem *>(room->findChildInstanceOf(CNodeItem::_type)); + while (nodeItem) { + if (nodeItem->_nodeNumber == nodeNumber) + return nodeItem; + + nodeItem = dynamic_cast<CNodeItem *>(room->findNextInstanceOf(CNodeItem::_type, nodeItem)); + } + + return nullptr; +} + +CViewItem *Debugger::findView(CNodeItem *node, const char *name) { + CViewItem *viewItem = dynamic_cast<CViewItem *>(node->findByName(name)); + if (viewItem) + return viewItem; + + int viewNumber = strToInt(name); + viewItem = dynamic_cast<CViewItem *>(node->findChildInstanceOf(CViewItem::_type)); + while (viewItem) { + if (viewItem->_viewNumber == viewNumber) + return viewItem; + + viewItem = dynamic_cast<CViewItem *>(node->findNextInstanceOf(CViewItem::_type, viewItem)); + } + + return nullptr; +} + +void Debugger::listRooms() { + CGameManager &gm = *g_vm->_window->_gameManager; + CTreeItem *root = gm._project; + CViewItem *view = gm._gameState._gameLocation.getView(); + CNodeItem *node = gm._gameState._gameLocation.getNode(); + CRoomItem *room = gm._gameState._gameLocation.getRoom(); + debugPrintf("Current location: %s, %s, %s\n", room->getName().c_str(), + node->getName().c_str(), view->getName().c_str()); + + debugPrintf("Available rooms:\n"); + for (CTreeItem *treeItem = root; treeItem; treeItem = treeItem->scan(root)) { + CRoomItem *roomItem = dynamic_cast<CRoomItem *>(treeItem); + if (roomItem) + debugPrintf("%d - %s\n", roomItem->_roomNumber, roomItem->_name.c_str()); + } +} + +void Debugger::listRoom(CRoomItem *room) { + for (CTreeItem *treeItem = room; treeItem; treeItem = treeItem->scan(room)) { + CNodeItem *nodeItem = dynamic_cast<CNodeItem *>(treeItem); + if (nodeItem) + debugPrintf("%s\n", nodeItem->_name.c_str()); + } +} + +void Debugger::listNode(CNodeItem *node) { + for (CTreeItem *treeItem = node; treeItem; treeItem = treeItem->scan(node)) { + CViewItem *viewItem = dynamic_cast<CViewItem *>(treeItem); + if (viewItem) + debugPrintf("%s\n", viewItem->_name.c_str()); + } +} + +bool Debugger::cmdDump(int argc, const char **argv) { + // Get the starting node + CTreeItem *root = g_vm->_window->_gameManager->_project; + if (argc == 2) + root = root->findByName(argv[1]); + + if (root == nullptr) { + debugPrintf("Could not find item\n"); + } else { + root->dump(0); + debugPrintf("Item and it's content were dumped to stdout\n"); + } + + return true; +} + +bool Debugger::cmdRoom(int argc, const char **argv) { + if (argc == 1) { + listRooms(); + } else if (argc >= 2) { + CRoomItem *roomItem = findRoom(argv[1]); + + if (!roomItem) + debugPrintf("Could not find room - %s\n", argv[1]); + else if (argc == 2) + listRoom(roomItem); + else { + CNodeItem *nodeItem = findNode(roomItem, argv[2]); + + if (!nodeItem) + debugPrintf("Could not find node - %s\n", argv[2]); + else if (argc == 3) + listNode(nodeItem); + else { + CViewItem *viewItem = findView(nodeItem, argv[3]); + + if (!viewItem) { + debugPrintf("Could not find view - %s\n", argv[3]); + } else { + // Change to the specified view + g_vm->_window->_gameManager->_gameState.changeView(viewItem, nullptr); + return false; + } + } + } + } + + return true; +} + +bool Debugger::cmdPET(int argc, const char **argv) { + CGameManager &gameManager = *g_vm->_window->_gameManager; + CGameState &gameState = gameManager._gameState; + + if (argc == 2) { + CString s(argv[1]); + s.toLowercase(); + + if (s == "on") { + gameState._petActive = true; + gameManager.initBounds(); + debugPrintf("PET is now on\n"); + return true; + } else if (s == "off") { + gameState._petActive = false; + gameManager.update(); + debugPrintf("PET is now off\n"); + return true; + } + } + + debugPrintf("%s [on | off]\n", argv[0]); + return true; +} + +bool Debugger::cmdItem(int argc, const char **argv) { + CGameManager &gameManager = *g_vm->_window->_gameManager; + CGameState &gameState = gameManager._gameState; + + if (argc == 1) { + // No parameters, so list the available items + debugPrintf("item [<name> [ add ]]\n"); + for (int idx = 0; idx < 40; ++idx) + debugPrintf("%s\n", g_vm->_itemIds[idx].c_str()); + } else { + // Ensure the specified name is a valid inventory item + int itemIndex; + for (itemIndex = 0; itemIndex < 40; ++itemIndex) { + if (g_vm->_itemIds[itemIndex] == argv[1]) + break; + } + if (itemIndex == 40) { + debugPrintf("Could not find item with that name\n"); + return true; + } + + // Get the item + CCarry *item = static_cast<CCarry *>( + g_vm->_window->_project->findByName(argv[1])); + assert(item); + + if (argc == 2) { + // List it's details + CTreeItem *treeItem = item; + CString fullName; + while ((treeItem = treeItem->getParent()) != nullptr) { + if (!treeItem->getName().empty()) + fullName = treeItem->getName() + "." + fullName; + } + + debugPrintf("Current location: %s\n", fullName.c_str()); + } else if (CString(argv[2]) == "add") { + // Ensure the PET is active and add the item to the inventory + gameState._petActive = true; + gameManager.initBounds(); + item->petAddToInventory(); + + return false; + } else { + debugPrintf("Unknown command\n"); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/debugger.h b/engines/titanic/debugger.h new file mode 100644 index 0000000000..5edb7cb324 --- /dev/null +++ b/engines/titanic/debugger.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_DEBUGGER_H +#define TITANIC_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" +#include "titanic/core/room_item.h" +#include "titanic/core/node_item.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +class TitanicEngine; + +class Debugger : public GUI::Debugger { +private: + /** + * Converts a decimal or hexadecimal string into a number + */ + int strToInt(const char *s); + + /** + * Find a room by name or number + */ + CRoomItem *findRoom(const char *name); + + /** + * Find a node within a room by name or number + */ + CNodeItem *findNode(CRoomItem *room, const char *name); + + /** + * Find a view within a room node by name or number + */ + CViewItem *findView(CNodeItem *node, const char *name); + + /** + * List all the rooms in the game + */ + void listRooms(); + + /** + * List the nodes within a room + */ + void listRoom(CRoomItem *room); + + /** + * List the views within a room node + */ + void listNode(CNodeItem *node); + + /** + * Dump a portion of the game project + */ + bool cmdDump(int argc, const char **argv); + + /** + * List room details, or jump to a specific view + */ + bool cmdRoom(int argc, const char **argv); + + /** + * Turn the PET on or off + */ + bool cmdPET(int argc, const char **argv); + + /** + * Item handling + */ + bool cmdItem(int argc, const char **argv); +protected: + TitanicEngine *_vm; +public: + Debugger(TitanicEngine *vm); + virtual ~Debugger() {} +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DEBUGGER_H */ diff --git a/engines/titanic/detection.cpp b/engines/titanic/detection.cpp new file mode 100644 index 0000000000..86d26f2f27 --- /dev/null +++ b/engines/titanic/detection.cpp @@ -0,0 +1,189 @@ +/* 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/titanic.h" +#include "titanic/core/project_item.h" +#include "titanic/support/simple_file.h" + +#include "base/plugins.h" +#include "common/savefile.h" +#include "common/str-array.h" +#include "common/memstream.h" +#include "engines/advancedDetector.h" +#include "common/system.h" +#include "graphics/colormasks.h" +#include "graphics/surface.h" + +#define MAX_SAVES 99 + +namespace Titanic { + +struct TitanicGameDescription { + ADGameDescription desc; +}; + +uint32 TitanicEngine::getFeatures() const { + return _gameDescription->desc.flags; +} + +bool TitanicEngine::isDemo() const { + return (bool)(_gameDescription->desc.flags & ADGF_DEMO); +} + +Common::Language TitanicEngine::getLanguage() const { + return _gameDescription->desc.language; +} + +} // End of namespace Titanic + +static const PlainGameDescriptor TitanicGames[] = { + {"titanic", "Starship Titanic"}, + {0, 0} +}; + +#include "titanic/detection_tables.h" + +class TitanicMetaEngine : public AdvancedMetaEngine { +public: + TitanicMetaEngine() : AdvancedMetaEngine(Titanic::gameDescriptions, sizeof(Titanic::TitanicGameDescription), TitanicGames) { + _maxScanDepth = 3; + } + + virtual const char *getName() const { + return "Titanic Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "Titanic Engine (c)"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const; + virtual void removeSaveState(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; + +bool TitanicMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail); +} + +bool Titanic::TitanicEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + +bool TitanicMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const Titanic::TitanicGameDescription *gd = (const Titanic::TitanicGameDescription *)desc; + *engine = new Titanic::TitanicEngine(syst, gd); + + return gd != 0; +} + +SaveStateList TitanicMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.0##", target); + Titanic::TitanicSavegameHeader header; + + filenames = saveFileMan->listSavefiles(pattern); + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + const char *ext = strrchr(file->c_str(), '.'); + int slot = ext ? atoi(ext + 1) : -1; + + if (slot >= 0 && slot < MAX_SAVES) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + Titanic::CompressedFile cf; + cf.open(in); + + if (Titanic::CProjectItem::readSavegameHeader(&cf, header)) + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + cf.close(); + } + } + } + + // Sort saves based on slot number. + Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); + return saveList; +} + +int TitanicMetaEngine::getMaximumSaveSlot() const { + return MAX_SAVES; +} + +void TitanicMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); +} + +SaveStateDescriptor TitanicMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); + + if (f) { + Titanic::CompressedFile file; + file.open(f); + + Titanic::TitanicSavegameHeader header; + Titanic::CProjectItem::readSavegameHeader(&file, header); + + file.close(); + + // Create the return descriptor + SaveStateDescriptor desc(slot, header._saveName); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME); + + return desc; + } + + return SaveStateDescriptor(); +} + + +#if PLUGIN_ENABLED_DYNAMIC(TITANIC) + REGISTER_PLUGIN_DYNAMIC(TITANIC, PLUGIN_TYPE_ENGINE, TitanicMetaEngine); +#else + REGISTER_PLUGIN_STATIC(TITANIC, PLUGIN_TYPE_ENGINE, TitanicMetaEngine); +#endif diff --git a/engines/titanic/detection_tables.h b/engines/titanic/detection_tables.h new file mode 100644 index 0000000000..d4acebc3bf --- /dev/null +++ b/engines/titanic/detection_tables.h @@ -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. + * + */ + +namespace Titanic { + +static const TitanicGameDescription gameDescriptions[] = { + { + { + "titanic", + 0, + AD_ENTRY1s("newgame.st", "c276f2661f0d0a547445a65db78b2292", 87227), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, + +#if 0 + // German version currently disabled because it won't start up, + // even with the English generated titanic.dat file + { + { + "titanic", + 0, + AD_ENTRY1s("newgame.st", "db22924adfd6730f4b79f4e51b25e779", 87608), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, +#endif + + { AD_TABLE_END_MARKER } +}; + +} // End of namespace Titanic diff --git a/engines/titanic/events.cpp b/engines/titanic/events.cpp new file mode 100644 index 0000000000..318ddf5726 --- /dev/null +++ b/engines/titanic/events.cpp @@ -0,0 +1,150 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/system.h" +#include "engines/util.h" +#include "titanic/events.h" +#include "titanic/titanic.h" +#include "titanic/main_game_window.h" + +namespace Titanic { + +Events::Events(TitanicEngine *vm): _vm(vm), _frameCounter(1), + _priorFrameTime(0) { +} + +void Events::pollEvents() { + checkForNextFrameCounter(); + + Common::Event event; + if (!g_system->getEventManager()->pollEvent(event)) + return; + + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + _mousePos = event.mouse; + eventTarget()->mouseMove(_mousePos); + break; + case Common::EVENT_LBUTTONDOWN: + _mousePos = event.mouse; + eventTarget()->leftButtonDown(_mousePos); + break; + case Common::EVENT_LBUTTONUP: + _mousePos = event.mouse; + eventTarget()->leftButtonUp(_mousePos); + break; + case Common::EVENT_MBUTTONDOWN: + _mousePos = event.mouse; + eventTarget()->middleButtonDown(_mousePos); + break; + case Common::EVENT_MBUTTONUP: + _mousePos = event.mouse; + eventTarget()->middleButtonUp(_mousePos); + break; + case Common::EVENT_RBUTTONDOWN: + _mousePos = event.mouse; + eventTarget()->rightButtonDown(_mousePos); + break; + case Common::EVENT_RBUTTONUP: + _mousePos = event.mouse; + eventTarget()->rightButtonUp(_mousePos); + break; + case Common::EVENT_KEYDOWN: + eventTarget()->keyDown(event.kbd); + break; + case Common::EVENT_KEYUP: + eventTarget()->keyUp(event.kbd); + break; + default: + break; + } +} + +void Events::pollEventsAndWait() { + pollEvents(); + g_system->delayMillis(10); + + // Regularly update the sound mixer + CGameManager *gameManager = g_vm->_window->_gameManager; + if (gameManager) + gameManager->_sound.updateMixer(); +} + +bool Events::checkForNextFrameCounter() { + // Check for next game frame + uint32 milli = g_system->getMillis(); + if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) { + ++_frameCounter; + _priorFrameTime = milli; + + // Handle any idle updates + eventTarget()->onIdle(); + + // Give time to the debugger + _vm->_debugger->onFrame(); + + // Display the frame + _vm->_screen->update(); + + return true; + } + + return false; +} + +uint32 Events::getTicksCount() const { + return g_system->getMillis(); +} + +void Events::sleep(uint time) { + uint32 delayEnd = g_system->getMillis() + time; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) + pollEventsAndWait(); +} + +bool Events::waitForPress(uint expiry) { + uint32 delayEnd = g_system->getMillis() + expiry; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { + g_system->delayMillis(10); + checkForNextFrameCounter(); + + Common::Event event; + if (g_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_MBUTTONDOWN: + case Common::EVENT_KEYDOWN: + return true; + default: + break; + } + } + } + + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/events.h b/engines/titanic/events.h new file mode 100644 index 0000000000..68666c7c46 --- /dev/null +++ b/engines/titanic/events.h @@ -0,0 +1,145 @@ +/* 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_EVENTS_H +#define TITANIC_EVENTS_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/stack.h" +#include "support/rect.h" + +namespace Titanic { + +#define GAME_FRAME_RATE 30 +#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) +#define DOUBLE_CLICK_TIME 100 + +enum SpecialButtons { + MK_LBUTTON = 1, MK_RBUTTON = 2, MK_SHIFT = 4, MK_CONTROL = 8, + MK_MBUTTON = 0x10 +}; + +class TitanicEngine; + +/** + * A base class for windows that can receive event messages + */ +class CEventTarget { +public: + virtual ~CEventTarget() {} + + /** + * Called to handle any regular updates the game requires + */ + virtual void onIdle() {} + + /** + * Mouse/key event handlers + */ + virtual void mouseMove(const Point &mousePos) {} + virtual void leftButtonDown(const Point &mousePos) {} + virtual void leftButtonUp(const Point &mousePos) {} + virtual void leftButtonDoubleClick(const Point &mousePos) {} + virtual void middleButtonDown(const Point &mousePos) {} + virtual void middleButtonUp(const Point &mousePos) {} + virtual void middleButtonDoubleClick(const Point &mousePos) {} + virtual void rightButtonDown(const Point &mousePos) {} + virtual void rightButtonUp(const Point &mousePos) {} + virtual void keyDown(Common::KeyState keyState) {} + virtual void keyUp(Common::KeyState keyState) {} +}; + +class Events { +private: + TitanicEngine *_vm; + Common::Stack<CEventTarget *> _eventTargets; + uint32 _frameCounter; + uint32 _priorFrameTime; + Common::Point _mousePos; + + /** + * Check whether it's time to display the next screen frame + */ + bool checkForNextFrameCounter(); + + /** + * Return the currently active event target + */ + CEventTarget *eventTarget() const { + return _eventTargets.top(); + } +public: + Events(TitanicEngine *vm); + ~Events() {} + + /** + * Adds a new event target to the top of the list. It will get + * all events generated until such time as another is pushed on + * top of it, or the removeTarget method is called + */ + void addTarget(CEventTarget *target) { + _eventTargets.push(target); + } + + /** + * Removes the currently active event target + */ + void removeTarget() { + _eventTargets.pop(); + } + + /** + * Check for any pending events + */ + void pollEvents(); + + /** + * Poll for events and introduce a small delay, to allow the system to + * yield to other running programs + */ + void pollEventsAndWait(); + + /** + * Return the current game frame number + */ + uint32 getFrameCounter() const { return _frameCounter; } + + /** + * Get the elapsed playtime + */ + uint32 getTicksCount() const; + + /** + * Sleep for a specified period of time + */ + void sleep(uint time); + + /** + * Wait for a mouse or keypress + */ + bool waitForPress(uint expiry); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_EVENTS_H */ diff --git a/engines/titanic/game/announce.cpp b/engines/titanic/game/announce.cpp new file mode 100644 index 0000000000..74c126476f --- /dev/null +++ b/engines/titanic/game/announce.cpp @@ -0,0 +1,132 @@ +/* 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/game/announce.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAnnounce, CGameObject) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +CAnnounce::CAnnounce() : _nameIndex(0), _soundHandle(0), _leaveFlag(1), _enabled(false) { +} + +void CAnnounce::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_nameIndex, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_leaveFlag, indent); + file->writeNumberLine(_enabled, indent); + + CGameObject::save(file, indent); +} + +void CAnnounce::load(SimpleFile *file) { + file->readNumber(); + _nameIndex = file->readNumber(); + _soundHandle = file->readNumber(); + _leaveFlag = file->readNumber(); + _enabled = file->readNumber(); + + CGameObject::load(file); +} + +bool CAnnounce::TimerMsg(CTimerMsg *msg) { + if (!_enabled) + return false; + + if (msg->_timerCtr == 1) { + CString numStr = "0"; + CString waveNames1[20] = { + "z#181.wav", "z#211.wav", "z#203.wav", "z#202.wav", "z#201.wav", + "z#200.wav", "z#199.wav", "z#198.wav", "z#197.wav", "z#196.wav", + "z#210.wav", "z#209.wav", "z#208.wav", "z#207.wav", "z#206.wav", + "z#205.wav", "z#204.wav", "z#145.wav", "", "" + }; + CString waveNames2[37] = { + "z#154.wav", "z#153.wav", "z#152.wav", "z#151.wav", "z#150.wav", + "z#149.wav", "z#148.wav", "z#169.wav", "z#171.wav", "z#178.wav", + "z#176.wav", "z#177.wav", "z#165.wav", "z#170.wav", "z#180.wav", + "z#156.wav", "z#172.wav", "z#173.wav", "z#160.wav", "z#158.wav", + "z#161.wav", "z#179.wav", "z#163.wav", "z#164.wav", "z#162.wav", + "z#159.wav", "z#175.wav", "z#166.wav", "z#174.wav", "z#157.wav", + "", "", "", "", "", "", "" + }; + + int randVal = _nameIndex ? getRandomNumber(2) : 0; + switch (randVal) { + case 0: + case 1: + _soundHandle = playSound("z#189.wav"); + if (_nameIndex < 20) { + queueSound(waveNames1[_nameIndex], _soundHandle); + ++_nameIndex; + } else { + queueSound(waveNames1[1 + getRandomNumber(17)], _soundHandle); + } + break; + + case 2: + _soundHandle = playSound("z#189.wav"); + queueSound(waveNames2[1 + getRandomNumber(35)], _soundHandle); + break; + + default: + break; + } + + addTimer(1, 300000 + getRandomNumber(30000), 0); + if (getRandomNumber(3) == 0) + addTimer(2, 4000, 0); + + } else if (msg->_timerCtr == 2) { + CParrotSpeakMsg speakMsg; + speakMsg._target = "Announcements"; + speakMsg.execute("PerchedParrot"); + } + + return true; +} + +bool CAnnounce::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (_leaveFlag) { + addTimer(1, 1000, 0); + _leaveFlag = 0; + _enabled = true; + } + + return true; +} + +bool CAnnounce::ActMsg(CActMsg *msg) { + if (msg->_action == "Enable") + _enabled = true; + else if (msg->_action == "Disable") + _enabled = false; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/announce.h b/engines/titanic/game/announce.h new file mode 100644 index 0000000000..9bf060daae --- /dev/null +++ b/engines/titanic/game/announce.h @@ -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. + * + */ + +#ifndef TITANIC_ANNOUNCE_H +#define TITANIC_ANNOUNCE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CAnnounce : public CGameObject { + DECLARE_MESSAGE_MAP; + bool TimerMsg(CTimerMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool ActMsg(CActMsg *msg); +private: + int _nameIndex; + int _soundHandle; + bool _leaveFlag; + bool _enabled; +public: + CLASSDEF; + CAnnounce(); + + /** + * 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_ROOM_ITEM_H */ diff --git a/engines/titanic/game/annoy_barbot.cpp b/engines/titanic/game/annoy_barbot.cpp new file mode 100644 index 0000000000..8b22f9c13a --- /dev/null +++ b/engines/titanic/game/annoy_barbot.cpp @@ -0,0 +1,54 @@ +/* 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/game/annoy_barbot.h" + +namespace Titanic { + +int CAnnoyBarbot::_v1; + +BEGIN_MESSAGE_MAP(CAnnoyBarbot, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CAnnoyBarbot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + CGameObject::save(file, indent); +} + +void CAnnoyBarbot::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + CGameObject::load(file); +} + +bool CAnnoyBarbot::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if ((++_v1 % 3) == 1) { + CActMsg actMsg("GoRingBell"); + actMsg.execute("Barbot"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/annoy_barbot.h b/engines/titanic/game/annoy_barbot.h new file mode 100644 index 0000000000..0ccfe43794 --- /dev/null +++ b/engines/titanic/game/annoy_barbot.h @@ -0,0 +1,51 @@ +/* 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_ANNOY_BARBOT_H +#define TITANIC_ANNOY_BARBOT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CAnnoyBarbot : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + static int _v1; +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_ANNOY_BARBOT_H */ diff --git a/engines/titanic/game/arb_background.cpp b/engines/titanic/game/arb_background.cpp new file mode 100644 index 0000000000..f71bcf90d1 --- /dev/null +++ b/engines/titanic/game/arb_background.cpp @@ -0,0 +1,53 @@ +/* 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/game/arb_background.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CArbBackground, CBackground); + +CArbBackground::CArbBackground() : CBackground(), + _fieldE0(0), _fieldE4(61), _fieldE8(62), _fieldEC(118) { +} + +void CArbBackground::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + + CBackground::save(file, indent); +} + +void CArbBackground::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/arb_background.h b/engines/titanic/game/arb_background.h new file mode 100644 index 0000000000..88d4d1bec6 --- /dev/null +++ b/engines/titanic/game/arb_background.h @@ -0,0 +1,54 @@ +/* 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_ARB_BACKGROUND_H +#define TITANIC_ARB_BACKGROUND_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CArbBackground : public CBackground { + DECLARE_MESSAGE_MAP; +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; +public: + CLASSDEF; + CArbBackground(); + + /** + * 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_ARB_BACKGROUND_H */ diff --git a/engines/titanic/game/arboretum_gate.cpp b/engines/titanic/game/arboretum_gate.cpp new file mode 100644 index 0000000000..4c3ca03b7a --- /dev/null +++ b/engines/titanic/game/arboretum_gate.cpp @@ -0,0 +1,331 @@ +/* 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/game/arboretum_gate.h" +#include "titanic/game/seasonal_adjustment.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CArboretumGate, CBackground) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(TurnOff) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(TurnOn) +END_MESSAGE_MAP() + +int CArboretumGate::_v1; +int CArboretumGate::_initialFrame; +int CArboretumGate::_v3; + +CArboretumGate::CArboretumGate() : CBackground() { + _viewName1 = "NULL"; + _viewName2 = "NULL"; + _seasonNum = 0; + _fieldF0 = 0; + _winterOffStartFrame = 244; + _winterOffEndFrame = 304; + _springOffStartFrame = 122; + _springOffEndFrame = 182; + _summerOffStartFrame1 = 183; + _summerOffEndFrame1 = 243; + _summerOffStartFrame2 = 665; + _summerOffEndFrame2 = 724; + _autumnOffStartFrame1 = 61; + _autumnOffEndFrame1 = 121; + _autumnOffStartFrame2 = 0; + _autumnOffEndFrame2 = 60; + _winterOnStartFrame = 485; + _winterOnEndFrame = 544; + _springOnStartFrame = 425; + _springOnEndFrame = 484; + _summerOnStartFrame1 = 545; + _summerOnEndFrame1 = 604; + _summerOnStartFrame2 = 605; + _summerOnEndFrame2 = 664; + _autumnOnStartFrame1 = 305; + _autumnOnEndFrame1 = 364; + _autumnOnStartFrame2 = 365; + _autumnOnEndFrame2 = 424; +} + +void CArboretumGate::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_seasonNum, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_initialFrame, indent); + file->writeNumberLine(_v3, indent); + file->writeQuotedLine(_viewName1, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_winterOffStartFrame, indent); + file->writeNumberLine(_winterOffEndFrame, indent); + file->writeNumberLine(_springOffStartFrame, indent); + file->writeNumberLine(_springOffEndFrame, indent); + file->writeNumberLine(_summerOffStartFrame1, indent); + file->writeNumberLine(_summerOffEndFrame1, indent); + file->writeNumberLine(_summerOffStartFrame2, indent); + file->writeNumberLine(_summerOffEndFrame2, indent); + file->writeNumberLine(_autumnOffStartFrame1, indent); + file->writeNumberLine(_autumnOffEndFrame1, indent); + file->writeNumberLine(_autumnOffStartFrame2, indent); + file->writeNumberLine(_autumnOffEndFrame2, indent); + file->writeNumberLine(_winterOnStartFrame, indent); + file->writeNumberLine(_winterOnEndFrame, indent); + file->writeNumberLine(_springOnStartFrame, indent); + file->writeNumberLine(_springOnEndFrame, indent); + file->writeNumberLine(_summerOnStartFrame1, indent); + file->writeNumberLine(_summerOnEndFrame1, indent); + file->writeNumberLine(_summerOnStartFrame2, indent); + file->writeNumberLine(_summerOnEndFrame2, indent); + file->writeNumberLine(_autumnOnStartFrame1, indent); + file->writeNumberLine(_autumnOnEndFrame1, indent); + file->writeNumberLine(_autumnOnStartFrame2, indent); + file->writeNumberLine(_autumnOnEndFrame2, indent); + file->writeQuotedLine(_viewName2, indent); + + CBackground::save(file, indent); +} + +void CArboretumGate::load(SimpleFile *file) { + file->readNumber(); + _seasonNum = file->readNumber(); + _v1 = file->readNumber(); + _initialFrame = file->readNumber(); + _v3 = file->readNumber(); + _viewName1 = file->readString(); + _fieldF0 = file->readNumber(); + _winterOffStartFrame = file->readNumber(); + _winterOffEndFrame = file->readNumber(); + _springOffStartFrame = file->readNumber(); + _springOffEndFrame = file->readNumber(); + _summerOffStartFrame1 = file->readNumber(); + _summerOffEndFrame1 = file->readNumber(); + _summerOffStartFrame2 = file->readNumber(); + _summerOffEndFrame2 = file->readNumber(); + _autumnOffStartFrame1 = file->readNumber(); + _autumnOffEndFrame1 = file->readNumber(); + _autumnOffStartFrame2 = file->readNumber(); + _autumnOffEndFrame2 = file->readNumber(); + _winterOnStartFrame = file->readNumber(); + _winterOnEndFrame = file->readNumber(); + _springOnStartFrame = file->readNumber(); + _springOnEndFrame = file->readNumber(); + _summerOnStartFrame1 = file->readNumber(); + _summerOnEndFrame1 = file->readNumber(); + _summerOnStartFrame2 = file->readNumber(); + _summerOnEndFrame2 = file->readNumber(); + _autumnOnStartFrame1 = file->readNumber(); + _autumnOnEndFrame1 = file->readNumber(); + _autumnOnStartFrame2 = file->readNumber(); + _autumnOnEndFrame2 = file->readNumber(); + _viewName2 = file->readString(); + + CBackground::load(file); +} + +bool CArboretumGate::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + _seasonNum = (_seasonNum + 1) % 4; + return true; +} + +bool CArboretumGate::ActMsg(CActMsg *msg) { + if (msg->_action == "PlayerGetsSpeechCentre") { + _v1 = 1; + CVisibleMsg visibleMsg(true); + visibleMsg.execute("SpCtrOverlay"); + } else if (msg->_action == "ExitLFrozen") { + if (_v3) { + _viewName2 = "FrozenArboretum.Node 2.W"; + CTurnOn onMsg; + onMsg.execute(this); + } else { + changeView("FrozenArboretum.Node 2.W"); + } + } else if (msg->_action == "ExitRFrozen") { + if (_v3) { + _viewName2 = "FrozenArboretum.Node 2.E"; + CTurnOn onMsg; + onMsg.execute(this); + } else { + changeView("FrozenArboretum.Node 2.E"); + } + } else if (msg->_action == "ExitLNormal") { + if (_v3) { + _viewName2 = "Arboretum.Node 2.W"; + CTurnOn onMsg; + onMsg.execute(this); + } else { + changeView("Arboretum.Node 2.W"); + } + } else if (msg->_action == "ExitRNormal") { + if (_v3) { + _viewName2 = "Arboretum.Node 2.E"; + CTurnOn onMsg; + onMsg.execute(this); + } + else { + changeView("Arboretum.Node 2.E"); + } + } + + return true; +} + +bool CArboretumGate::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(!_v3); + + if (_viewName1 != "NULL") { + changeView(_viewName1); + } else if (_viewName2 != "NULL") { + changeView(_viewName2); + _viewName2 = "NULL"; + } + + return true; +} + +bool CArboretumGate::LeaveViewMsg(CLeaveViewMsg *msg) { + return false; +} + +bool CArboretumGate::TurnOff(CTurnOff *msg) { + if (!_v3) { + switch (_seasonNum) { + case SPRING: + playMovie(_springOffStartFrame, _springOffEndFrame, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + break; + + case SUMMER: + if (_v1) { + playMovie(_summerOffStartFrame2, _summerOffEndFrame2, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } else { + playMovie(_summerOffStartFrame1, _summerOffEndFrame1, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } + break; + + case AUTUMN: + if (_v1) { + playMovie(_autumnOffStartFrame2, _autumnOffEndFrame2, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } else { + playMovie(_autumnOffStartFrame1, _autumnOffEndFrame1, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } + break; + + case WINTER: + playMovie(_winterOffStartFrame, _winterOffEndFrame, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + break; + + default: + break; + } + + _v3 = 1; + CArboretumGateMsg gateMsg; + gateMsg.execute("Arboretum", nullptr, MSGFLAG_SCAN); + } + + return true; +} + +bool CArboretumGate::TurnOn(CTurnOn *msg) { + if (_v3) { + CArboretumGateMsg gateMsg(0); + gateMsg.execute("Arboretum"); + setVisible(true); + + switch (_seasonNum) { + case SPRING: + playMovie(_springOnStartFrame, _springOnEndFrame, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + break; + + case SUMMER: + if (_v1) { + playMovie(_summerOnStartFrame2, _summerOnEndFrame2, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } else { + playMovie(_summerOnStartFrame1, _summerOnEndFrame1, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } + break; + + case AUTUMN: + if (_v1) { + playMovie(_autumnOnStartFrame2, _autumnOnEndFrame2, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } else { + playMovie(_autumnOnStartFrame1, _autumnOnEndFrame1, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + } + break; + + case WINTER: + playMovie(_winterOnStartFrame, _winterOnEndFrame, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + break; + + default: + break; + } + + _v3 = 0; + } + + return true; +} + +bool CArboretumGate::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_v3) { + CTurnOff offMsg; + offMsg.execute(this); + } + + return true; +} + +bool CArboretumGate::EnterViewMsg(CEnterViewMsg *msg) { + if (!_v3) { + switch (_seasonNum) { + case SPRING: + _initialFrame = _springOffStartFrame; + break; + + case SUMMER: + _initialFrame = _v1 ? _summerOffStartFrame2 : _summerOffStartFrame1; + break; + + case AUTUMN: + _initialFrame = _v1 ? _autumnOffStartFrame1 : _autumnOffStartFrame2; + break; + + case WINTER: + _initialFrame = _winterOffStartFrame; + break; + + default: + break; + } + + loadFrame(_initialFrame); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/arboretum_gate.h b/engines/titanic/game/arboretum_gate.h new file mode 100644 index 0000000000..62c9200a64 --- /dev/null +++ b/engines/titanic/game/arboretum_gate.h @@ -0,0 +1,92 @@ +/* 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_ARBORETUM_GATE_H +#define TITANIC_ARBORETUM_GATE_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CArboretumGate : public CBackground { + DECLARE_MESSAGE_MAP; + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool TurnOff(CTurnOff *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool TurnOn(CTurnOn *msg); +private: + static int _v1; + static int _initialFrame; + static int _v3; +private: + int _seasonNum; + CString _viewName1; + int _fieldF0; + int _winterOffStartFrame; + int _winterOffEndFrame; + int _springOffStartFrame; + int _springOffEndFrame; + int _summerOffStartFrame2; + int _summerOffEndFrame2; + int _summerOffStartFrame1; + int _summerOffEndFrame1; + int _autumnOffStartFrame2; + int _autumnOffEndFrame2; + int _autumnOffStartFrame1; + int _autumnOffEndFrame1; + int _winterOnStartFrame; + int _winterOnEndFrame; + int _springOnStartFrame; + int _springOnEndFrame; + int _summerOnStartFrame1; + int _summerOnEndFrame1; + int _summerOnStartFrame2; + int _summerOnEndFrame2; + int _autumnOnStartFrame1; + int _autumnOnEndFrame1; + int _autumnOnStartFrame2; + int _autumnOnEndFrame2; + CString _viewName2; +public: + CLASSDEF; + CArboretumGate(); + + /** + * 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_ARBORETUM_GATE_H */ diff --git a/engines/titanic/game/auto_animate.cpp b/engines/titanic/game/auto_animate.cpp new file mode 100644 index 0000000000..16e6e56747 --- /dev/null +++ b/engines/titanic/game/auto_animate.cpp @@ -0,0 +1,68 @@ +/* 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/game/auto_animate.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAutoAnimate, CBackground) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(InitializeAnimMsg) +END_MESSAGE_MAP() + +void CAutoAnimate::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_enabled, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_repeat, indent); + CBackground::save(file, indent); +} + +void CAutoAnimate::load(SimpleFile *file) { + file->readNumber(); + _enabled = file->readNumber(); + _fieldE4 = file->readNumber(); + _repeat = file->readNumber(); + CBackground::load(file); +} + +bool CAutoAnimate::EnterViewMsg(CEnterViewMsg *msg) { + if (_enabled) { + uint flags = _repeat ? MOVIE_REPEAT : 0; + if (_startFrame != _endFrame) + playMovie(_startFrame, _endFrame, flags); + else + playMovie(flags); + + if (!_fieldE4) + _enabled = false; + } + + return true; +} + +bool CAutoAnimate::InitializeAnimMsg(CInitializeAnimMsg *msg) { + _enabled = true; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/auto_animate.h b/engines/titanic/game/auto_animate.h new file mode 100644 index 0000000000..735aba922e --- /dev/null +++ b/engines/titanic/game/auto_animate.h @@ -0,0 +1,56 @@ +/* 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_AUTO_ANIMATE_H +#define TITANIC_AUTO_ANIMATE_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CAutoAnimate : public CBackground { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool InitializeAnimMsg(CInitializeAnimMsg *msg); +private: + bool _enabled; + int _fieldE4; + bool _repeat; +public: + CLASSDEF; + CAutoAnimate() : CBackground(), _enabled(true), _fieldE4(1), _repeat(false) {} + + /** + * 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_AUTO_ANIMATE_H */ diff --git a/engines/titanic/game/bar_bell.cpp b/engines/titanic/game/bar_bell.cpp new file mode 100644 index 0000000000..207644a00e --- /dev/null +++ b/engines/titanic/game/bar_bell.cpp @@ -0,0 +1,131 @@ +/* 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/game/bar_bell.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBarBell, CGameObject) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +CBarBell::CBarBell() : CGameObject(), _fieldBC(0), + _volume(65), _soundVal3(0), _fieldC8(0), _fieldCC(0) { +} + +void CBarBell::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_volume, indent); + file->writeNumberLine(_soundVal3, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_fieldCC, indent); + + CGameObject::save(file, indent); +} + +void CBarBell::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _volume = file->readNumber(); + _soundVal3 = file->readNumber(); + _fieldC8 = file->readNumber(); + _fieldCC = file->readNumber(); + + CGameObject::load(file); +} + +bool CBarBell::EnterRoomMsg(CEnterRoomMsg *msg) { + _fieldBC = 0; + return true; +} + +bool CBarBell::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if ((_fieldC8 % 3) == 2) { + switch (_fieldBC) { + case 0: + case 1: + case 5: + playSound("c#54.wav", _volume, _soundVal3); + break; + + case 2: + playSound("c#52.wav", _volume, _soundVal3); + break; + + case 3: + playSound("c#53.wav", _volume, _soundVal3); + break; + + case 4: + playSound("c#55.wav", _volume, _soundVal3); + break; + + default: + playSound("c#51.wav", _volume, _soundVal3); + break; + } + } else if (_fieldBC >= 5) { + if (_fieldBC == 6) { + CActMsg actMsg("BellRing3"); + actMsg.execute("Barbot"); + } + + playSound("c#51.wav", _volume, _soundVal3); + } else { + if (_fieldBC == 3) { + CActMsg actMsg("BellRing1"); + actMsg.execute("Barbot"); + } else if (_fieldBC == 4) { + CActMsg actMsg("BellRing2"); + actMsg.execute("Barbot"); + } + + playSound("c#54.wav", _volume, _soundVal3); + } + + return true; +} + +bool CBarBell::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (!_fieldBC) { + CTurnOn onMsg; + onMsg.execute("Barbot"); + } + + ++_fieldBC; + return 2; +} + +bool CBarBell::ActMsg(CActMsg *msg) { + if (msg->_action == "ResetCount") { + _fieldBC = 0; + ++_fieldC8; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bar_bell.h b/engines/titanic/game/bar_bell.h new file mode 100644 index 0000000000..b50fe505ba --- /dev/null +++ b/engines/titanic/game/bar_bell.h @@ -0,0 +1,60 @@ +/* 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_BAR_BELL_H +#define TITANIC_BAR_BELL_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CBarBell : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool ActMsg(CActMsg *msg); +public: + int _fieldBC; + int _volume; + int _soundVal3; + int _fieldC8; + int _fieldCC; +public: + CLASSDEF; + CBarBell(); + + /** + * 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_BAR_BELL_H */ diff --git a/engines/titanic/game/bar_menu.cpp b/engines/titanic/game/bar_menu.cpp new file mode 100644 index 0000000000..3812a8dab6 --- /dev/null +++ b/engines/titanic/game/bar_menu.cpp @@ -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. + * + */ + +#include "titanic/game/bar_menu.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBarMenu, CGameObject) + ON_MESSAGE(PETActivateMsg) + ON_MESSAGE(PETDownMsg) + ON_MESSAGE(PETUpMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +CBarMenu::CBarMenu() : CGameObject(), _barFrameNumber(0), _visibleFlag(false), _numFrames(6) { +} + +void CBarMenu::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_barFrameNumber, indent); + file->writeNumberLine(_visibleFlag, indent); + file->writeNumberLine(_numFrames, indent); + + CGameObject::save(file, indent); +} + +void CBarMenu::load(SimpleFile *file) { + file->readNumber(); + _barFrameNumber = file->readNumber(); + _visibleFlag = file->readNumber(); + _numFrames = file->readNumber(); + + CGameObject::load(file); +} + +bool CBarMenu::PETActivateMsg(CPETActivateMsg *msg) { + if (msg->_name == "Television") { + _visibleFlag = !_visibleFlag; + setVisible(_visibleFlag); + loadFrame(_barFrameNumber); + } + + return true; +} + +bool CBarMenu::PETDownMsg(CPETDownMsg *msg) { + if (_visibleFlag) { + if (--_barFrameNumber < 0) + _barFrameNumber = _numFrames - 1; + + loadFrame(_barFrameNumber); + } + + return true; +} + +bool CBarMenu::PETUpMsg(CPETUpMsg *msg) { + if (_visibleFlag) { + _barFrameNumber = (_barFrameNumber + 1) % _numFrames; + loadFrame(_barFrameNumber); + } + + return true; +} + +bool CBarMenu::EnterViewMsg(CEnterViewMsg *msg) { + petSetArea(PET_REMOTE); + petHighlightGlyph(2); + petSetRemoteTarget(); + setVisible(_visibleFlag); + loadFrame(_barFrameNumber); + + return true; +} + +bool CBarMenu::LeaveViewMsg(CLeaveViewMsg *msg) { + petClear(); + _visibleFlag = false; + setVisible(false); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bar_menu.h b/engines/titanic/game/bar_menu.h new file mode 100644 index 0000000000..f16f7b035d --- /dev/null +++ b/engines/titanic/game/bar_menu.h @@ -0,0 +1,59 @@ +/* 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_BAR_MENU_H +#define TITANIC_BAR_MENU_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CBarMenu : public CGameObject { + DECLARE_MESSAGE_MAP; + bool PETActivateMsg(CPETActivateMsg *msg); + bool PETDownMsg(CPETDownMsg *msg); + bool PETUpMsg(CPETUpMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +public: + int _barFrameNumber; + bool _visibleFlag; + int _numFrames; +public: + CLASSDEF; + CBarMenu(); + + /** + * 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_BAR_MENU_H */ diff --git a/engines/titanic/game/bar_menu_button.cpp b/engines/titanic/game/bar_menu_button.cpp new file mode 100644 index 0000000000..874584db30 --- /dev/null +++ b/engines/titanic/game/bar_menu_button.cpp @@ -0,0 +1,61 @@ +/* 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/game/bar_menu_button.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBarMenuButton, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +void CBarMenuButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CBarMenuButton::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +bool CBarMenuButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CBarMenuButton::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (_value) { + CPETUpMsg upMsg("", -1); + upMsg.execute("BarTelevision"); + } else { + CPETDownMsg downMsg("", -1); + downMsg.execute("BarTelevision"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bar_menu_button.h b/engines/titanic/game/bar_menu_button.h new file mode 100644 index 0000000000..300435c209 --- /dev/null +++ b/engines/titanic/game/bar_menu_button.h @@ -0,0 +1,53 @@ +/* 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_BAR_MENU_BUTTON_H +#define TITANIC_BAR_MENU_BUTTON_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBarMenuButton : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +public: + int _value; +public: + CLASSDEF; + CBarMenuButton() : CGameObject(), _value(1) {} + + /** + * 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_BAR_MENU_BUTTON_H */ diff --git a/engines/titanic/game/belbot_get_light.cpp b/engines/titanic/game/belbot_get_light.cpp new file mode 100644 index 0000000000..2cc4c3ae19 --- /dev/null +++ b/engines/titanic/game/belbot_get_light.cpp @@ -0,0 +1,78 @@ +/* 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/game/belbot_get_light.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBelbotGetLight, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MovieFrameMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CBelbotGetLight::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_value, indent); + CGameObject::save(file, indent); +} + +void CBelbotGetLight::load(SimpleFile *file) { + file->readNumber(); + _value = file->readString(); + CGameObject::load(file); +} + +bool CBelbotGetLight::ActMsg(CActMsg *msg) { + if (msg->_action == "BellbotGetLight") { + _value = getFullViewName(); + lockMouse(); + changeView("1stClassState.Node 11.N", ""); + } + + return true; +} + +bool CBelbotGetLight::MovieEndMsg(CMovieEndMsg *msg) { + sleep(1000); + changeView(_value, ""); + unlockMouse(); + return true; +} + +bool CBelbotGetLight::MovieFrameMsg(CMovieFrameMsg *msg) { + if (getMovieFrame() == 37) { + CActMsg actMsg("BellbotGetLight"); + actMsg.execute("Eye1"); + } + + return true; +} + +bool CBelbotGetLight::EnterViewMsg(CEnterViewMsg *msg) { + playMovie(MOVIE_NOTIFY_OBJECT); + movieEvent(37); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/belbot_get_light.h b/engines/titanic/game/belbot_get_light.h new file mode 100644 index 0000000000..1707ad4793 --- /dev/null +++ b/engines/titanic/game/belbot_get_light.h @@ -0,0 +1,54 @@ +/* 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_BELBOT_GET_LIGHT_H +#define TITANIC_BELBOT_GET_LIGHT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBelbotGetLight : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + CString _value; +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_LIGHT_H */ diff --git a/engines/titanic/game/bomb.cpp b/engines/titanic/game/bomb.cpp new file mode 100644 index 0000000000..f3f1129e22 --- /dev/null +++ b/engines/titanic/game/bomb.cpp @@ -0,0 +1,363 @@ +/* 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/game/bomb.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBomb, CBackground) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(TrueTalkGetStateValueMsg) + ON_MESSAGE(SetFrameMsg) +END_MESSAGE_MAP() + +static const char *const WAVE_NAMES1[] = { + "z#353.wav", "z#339.wav", "z#325.wav", "z#311.wav", "z#297.wav", + "z#283.wav", "z#269.wav", "z#255.wav", "z#241.wav" +}; + +static const char *const WAVE_NAMES2[] = { + "", "z#352.wav", "z#338.wav", "z#324.wav", "z#310.wav", "z#296.wav", + "z#281.wav", "z#268.wav", "z#254.wav", "z#240.wav", "", "z#351.wav", + "z#337.wav", "z#323.wav", "z#309.wav", "z#295.wav", "z#282.wav", + "z#267.wav", "z#253.wav", "z#239.wav" +}; + +static const char *const WAVE_NAMES3[100] = { + "bombcountdown_c0.wav", "z#355.wav", "z#341.wav", "z#327.wav", "z#313.wav", + "z#299.wav", "z#285.wav", "z#271.wav", "z#257.wav", "z#243.wav", + "z#354.wav", "z#350.wav", "z#349.wav", "z#348.wav", "z#347.wav", + "z#346.wav", "z#345.wav", "z#344.wav", "z#343.wav", "z#342.wav", + "z#340.wav", "z#336.wav", "z#335.wav", "z#334.wav", "z#333.wav", + "z#332.wav", "z#331.wav", "z#330.wav", "z#329.wav", "z#328.wav", + "z#326.wav", "z#322.wav", "z#321.wav", "z#320.wav", "z#319.wav", + "z#318.wav", "z#317.wav", "z#316.wav", "z#315.wav", "z#314.wav", + "z#312.wav", "z#308.wav", "z#307.wav", "z#306.wav", "z#305.wav", + "z#304.wav", "z#303.wav", "z#302.wav", "z#301.wav", "z#300.wav", + "z#298.wav", "z#294.wav", "z#293.wav", "z#292.wav", "z#291.wav", + "z#290.wav", "z#289.wav", "z#288.wav", "z#287.wav", "z#286.wav", + "z#284.wav", "z#280.wav", "z#279.wav", "z#278.wav", "z#277.wav", + "z#276.wav", "z#275.wav", "z#274.wav", "z#273.wav", "z#272.wav", + "z#270.wav", "z#266.wav", "z#265.wav", "z#264.wav", "z#263.wav", + "z#262.wav", "z#261.wav", "z#260.wav", "z#259.wav", "z#258.wav", + "z#256.wav", "z#252.wav", "z#251.wav", "z#250.wav", "z#249.wav", + "z#248.wav", "z#247.wav", "z#246.wav", "z#245.wav", "z#244.wav", + "z#242.wav", "z#238.wav", "z#237.wav", "z#236.wav", "z#235.wav", + "z#234.wav", "z#233.wav", "z#232.wav", "z#231.wav", "z#230.wav", +}; + +CBomb::CBomb() : CBackground() { + _fieldE0 = 0; + _fieldE4 = 0; + _fieldE8 = 17; + _fieldEC = 9; + _fieldF0 = 0; + _countdown = 999; + _soundHandle = 0; + _fieldFC = 0; + _startingTicks = 0; + _volume = 60; +} + +void CBomb::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_countdown, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_fieldFC, indent); + file->writeNumberLine(_startingTicks, indent); + file->writeNumberLine(_volume, indent); + + CBackground::save(file, indent); +} + +void CBomb::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + _countdown = file->readNumber(); + _soundHandle = file->readNumber(); + _fieldFC = file->readNumber(); + _startingTicks = file->readNumber(); + _volume = file->readNumber(); + + CBackground::load(file); +} + +bool CBomb::StatusChangeMsg(CStatusChangeMsg *msg) { + _fieldE4 += msg->_newStatus; + + if (_fieldE4 == 23) { + startAnimTimer("Disarmed", 2000); + lockMouse(); + } + + _fieldF0 %= 1000; + if (!(_fieldF0 % 20) && _countdown < 995) { + int val = getRandomNumber(5) + 25; + if (_fieldF0 < 20 || _fieldF0 > 80) + val = 28; + + CString name; + switch (val - 25) { + case 0: + name = "z#372.wav"; + break; + case 1: + name = "z#371.wav"; + break; + case 2: + name = "z#370.wav"; + break; + case 3: + name = "z#369.wav"; + break; + case 4: + name = "z#368.wav"; + break; + default: + name = "z#366.wav"; + break; + } + + _soundHandle = queueSound(name, _soundHandle, _volume); + } + + return true; +} + +bool CBomb::EnterViewMsg(CEnterViewMsg *msg) { + _fieldE4 = 2; + return true; +} + +bool CBomb::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + playSound("z#62.wav"); + + if (_fieldE0) { + stopSound(_soundHandle); + if (_fieldE4 < 23) { + _fieldE8 = MIN(_fieldE8 + 1, 23); + + CString name; + switch (_fieldE8) { + case 18: + name = "z#380.wav"; + break; + case 19: + name = "z#379.wav"; + break; + case 20: + name = "z#377.wav"; + break; + case 21: + name = "z#376.wav"; + break; + case 22: + name = "z#375.wav"; + break; + default: + name = "z#374.wav"; + break; + } + + _soundHandle = queueSound(name, _soundHandle, _volume); + _countdown = 999; + } + } else { + _soundHandle = playSound("z#389.wav", _volume); + _fieldE0 = true; + CActMsg actMsg("Arm Bomb"); + actMsg.execute("EndExplodeShip"); + } + + return true; +} + +bool CBomb::EnterRoomMsg(CEnterRoomMsg *msg) { + _fieldE8 = 17; + _fieldEC = 9; + _fieldF0 = 0; + _startingTicks = getTicksCount(); + return true; +} + +bool CBomb::ActMsg(CActMsg *msg) { + if (msg->_action == "Hit") { + playSound("z#63.wav"); + stopSound(_soundHandle); + + if (_fieldEC < 17) + ++_fieldEC; + + CString name; + switch (_fieldEC) { + case 10: + name = "z#388.wav"; + break; + case 11: + name = "z#387.wav"; + break; + case 12: + name = "z#386.wav"; + break; + case 13: + name = "z#385.wav"; + break; + case 14: + name = "z#384.wav"; + break; + case 15: + name = "z#383.wav"; + break; + case 16: + name = "z#382.wav"; + break; + default: + name = "z#381.wav"; + break; + } + + _soundHandle = queueSound(name, _soundHandle, _volume); + _countdown = 999; + } + + return true; +} + +bool CBomb::TurnOn(CTurnOn *msg) { + if (!_fieldE0) { + _soundHandle = playSound("z#389.wav", _volume); + _fieldE0 = true; + + CActMsg actMsg("Arm Bomb"); + actMsg.execute("EndExplodeShip"); + addTimer(0); + } + + changeView("Titania.Node 8.W", ""); + CActMsg actMsg("Titania.Node 8.N"); + actMsg.execute("BombNav"); + actMsg.execute("EnterBombRoom"); + + return true; +} + +bool CBomb::TimerMsg(CTimerMsg *msg) { + if (msg->_action == "Disarmed") { + stopSound(_soundHandle); + playSound("z#364.wav", _volume); + + CActMsg actMsg1("Disarm Bomb"); + actMsg1.execute("EndExplodeShip"); + _fieldE0 = false; + CActMsg actMsg2("Titania.Node 5.N"); + actMsg2.execute("BombNav"); + actMsg2.execute("EnterBombNav"); + + changeView("Titania.Node 8.W", ""); + changeView("Titania.Node 13.N", ""); + unlockMouse(); + } + + if (compareRoomNameTo("Titania")) { + if (msg->_actionVal == 1 && getRandomNumber(9) == 0) { + if (!_fieldE0) + return true; + + CParrotSpeakMsg speakMsg("Bomb", "BombCountdown"); + speakMsg.execute("PerchedParrot"); + } + + if (_fieldE0) { + if (isSoundActive(_soundHandle)) { + if (msg->_actionVal == 0) { + addTimer(1, 1000, 0); + } else { + _soundHandle = 0; + int section = _countdown / 100; + int index = _countdown % 100; + + if (_countdown >= 100) { + CString name1 = index ? WAVE_NAMES2[section] : + WAVE_NAMES1[section]; + playSound(name1, _volume); + } + + CString name2 = WAVE_NAMES3[index]; + if (_countdown == 10) { + name2 = "z#229.wav"; + _countdown = 998; + } + + if (_soundHandle > 0) { + _soundHandle = queueSound(name2, _soundHandle, _volume); + } else { + _soundHandle = playSound(name2, _volume); + } + + --_countdown; + addTimer(0, 1000, 0); + } + } else { + addTimer(0, 100, 0); + } + } + } else { + if (_fieldE0) { + --_countdown; + addTimer(6000); + + if (_countdown < 11) + _countdown = getRandomNumber(900) + 50; + } + } + + return true; +} + +bool CBomb::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) { + if (msg->_stateNum == 10) + msg->_stateVal = _fieldE0; + + return true; +} + +bool CBomb::SetFrameMsg(CSetFrameMsg *msg) { + _volume = msg->_frameNumber; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bomb.h b/engines/titanic/game/bomb.h new file mode 100644 index 0000000000..f78c42cff0 --- /dev/null +++ b/engines/titanic/game/bomb.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_BOMB_H +#define TITANIC_BOMB_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CBomb : public CBackground { + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool ActMsg(CActMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TimerMsg(CTimerMsg *msg); + bool TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg); + bool SetFrameMsg(CSetFrameMsg *msg); + DECLARE_MESSAGE_MAP; +private: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _fieldF0; + int _countdown; + int _soundHandle; + int _fieldFC; + int _startingTicks; + int _volume; +public: + CLASSDEF; + CBomb(); + + /** + * 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_BOMB_H */ diff --git a/engines/titanic/game/bottom_of_well_monitor.cpp b/engines/titanic/game/bottom_of_well_monitor.cpp new file mode 100644 index 0000000000..38211040d8 --- /dev/null +++ b/engines/titanic/game/bottom_of_well_monitor.cpp @@ -0,0 +1,114 @@ +/* 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/game/bottom_of_well_monitor.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBottomOfWellMonitor, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +int CBottomOfWellMonitor::_v1; +int CBottomOfWellMonitor::_v2; + +void CBottomOfWellMonitor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_flag, indent); + CGameObject::save(file, indent); +} + +void CBottomOfWellMonitor::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + _flag = file->readNumber(); + CGameObject::load(file); +} + +bool CBottomOfWellMonitor::ActMsg(CActMsg *msg) { + if (msg->_action == "TelevisionTaken") { + _v1 = 0; + _cursorId = CURSOR_ARROW; + CVisibleMsg visibleMsg; + visibleMsg.execute("CrushedTV2NE"); + visibleMsg.execute("CrushedTV4SW"); + _cursorId = CURSOR_ARROW; + } else if (msg->_action == "LiftbotHeadTaken") { + _v2 = 0; + _cursorId = CURSOR_ARROW; + CVisibleMsg visibleMsg; + visibleMsg.execute("LiftbotHead2NE"); + visibleMsg.execute("LiftbotHead4SW"); + _cursorId = CURSOR_ARROW; + } else if (msg->_action == "LiftbotHeadTaken") { + _v2 = 1; + CVisibleMsg visibleMsg; + visibleMsg.execute("CrushedTV2NE"); + visibleMsg.execute("CrushedTV4SW"); + _cursorId = CURSOR_MOVE_DOWN1; + } + + return true; +} + +bool CBottomOfWellMonitor::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (isEquals("BOWTelevisionMonitor")) { + if (_v1) + changeView("BottomOfWell.Node 7.N", ""); + } else { + if (_v2) + changeView("BottomOfWell.Node 8.N", ""); + } + + return true; +} + +bool CBottomOfWellMonitor::EnterViewMsg(CEnterViewMsg *msg) { + if (_flag) { + if (isEquals("BOWTelevisionMonitor")) { + if (_v1) { + changeView("BottomOfWell.Node 7.N", ""); + _flag = false; + } + } else { + if (_v2) { + changeView("BottomOfWell.Node 8.N", ""); + _flag = false; + } + } + } + + return true; +} + +bool CBottomOfWellMonitor::LeaveViewMsg(CLeaveViewMsg *msg) { + _flag = true; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bottom_of_well_monitor.h b/engines/titanic/game/bottom_of_well_monitor.h new file mode 100644 index 0000000000..be9ae2c093 --- /dev/null +++ b/engines/titanic/game/bottom_of_well_monitor.h @@ -0,0 +1,56 @@ +/* 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_BOTTOM_OF_WELL_MONITOR_H +#define TITANIC_BOTTOM_OF_WELL_MONITOR_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBottomOfWellMonitor : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +public: + static int _v1, _v2; + bool _flag; +public: + CLASSDEF; + CBottomOfWellMonitor() : _flag(true) {} + + /** + * 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_BOTTOM_OF_WELL_MONITOR_H */ diff --git a/engines/titanic/game/bowl_unlocker.cpp b/engines/titanic/game/bowl_unlocker.cpp new file mode 100644 index 0000000000..c4adac34f2 --- /dev/null +++ b/engines/titanic/game/bowl_unlocker.cpp @@ -0,0 +1,78 @@ +/* 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/game/bowl_unlocker.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBowlUnlocker, CGameObject) + ON_MESSAGE(NutPuzzleMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CBowlUnlocker::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_bowlUnlocked, indent); + CGameObject::save(file, indent); +} + +void CBowlUnlocker::load(SimpleFile *file) { + file->readNumber(); + _bowlUnlocked = file->readNumber(); + CGameObject::load(file); +} + +bool CBowlUnlocker::NutPuzzleMsg(CNutPuzzleMsg *msg) { + if (msg->_value == "UnlockBowl") { + setVisible(true); + playMovie(MOVIE_NOTIFY_OBJECT); + } + + return true; +} + +bool CBowlUnlocker::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(false); + _bowlUnlocked = true; + + CNutPuzzleMsg puzzleMsg("BowlUnlocked"); + puzzleMsg.execute(getRoom(), nullptr, MSGFLAG_SCAN); + + playSound("z#47.wav"); + return true; +} + +bool CBowlUnlocker::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_bowlUnlocked) + msg->execute("Ear1"); + return true; +} + +bool CBowlUnlocker::LeaveViewMsg(CLeaveViewMsg *msg) { + _bowlUnlocked = false; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bowl_unlocker.h b/engines/titanic/game/bowl_unlocker.h new file mode 100644 index 0000000000..b940661904 --- /dev/null +++ b/engines/titanic/game/bowl_unlocker.h @@ -0,0 +1,55 @@ +/* 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_BOWL_UNLOCKER_H +#define TITANIC_BOWL_UNLOCKER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBowlUnlocker : public CGameObject { + DECLARE_MESSAGE_MAP; + bool NutPuzzleMsg(CNutPuzzleMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +public: + bool _bowlUnlocked; +public: + CLASSDEF; + CBowlUnlocker() : CGameObject(), _bowlUnlocked(false) {} + + /** + * 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_BOWL_UNLOCKER_H */ diff --git a/engines/titanic/game/brain_slot.cpp b/engines/titanic/game/brain_slot.cpp new file mode 100644 index 0000000000..1518d9b0b3 --- /dev/null +++ b/engines/titanic/game/brain_slot.cpp @@ -0,0 +1,149 @@ +/* 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/game/brain_slot.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBrainSlot, CGameObject) + ON_MESSAGE(SetFrameMsg) + ON_MESSAGE(AddHeadPieceMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +int CBrainSlot::_added; +bool CBrainSlot::_woken; + +void CBrainSlot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeQuotedLine(_target, indent); + file->writeNumberLine(_added, indent); + file->writeNumberLine(_woken, indent); + + CGameObject::save(file, indent); +} + +void CBrainSlot::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _target = file->readString(); + _added = file->readNumber(); + _woken = file->readNumber(); + + CGameObject::load(file); +} + +bool CBrainSlot::SetFrameMsg(CSetFrameMsg *msg) { + loadFrame(msg->_frameNumber); + _value1 = 1; + return true; +} + +bool CBrainSlot::AddHeadPieceMsg(CAddHeadPieceMsg *msg) { + _added = 1; + _cursorId = CURSOR_HAND; + CAddHeadPieceMsg addMsg("NULL"); + + if (isEquals("AuditoryCentreSlot")) { + if (msg->_value == "AuditoryCentre") + addMsg._value = "AuditoryCentre"; + } else if (isEquals("SpeechCentreSlot")) { + if (msg->_value == "SpeechCentre") + addMsg._value = "SpeechCentre"; + } else if (isEquals("OlfactoryCentreSlot")) { + if (msg->_value == "OlfactoryCentre") + addMsg._value = "OlfactoryCentre"; + } else if (isEquals("VisionCentreSlot")) { + if (msg->_value == "VisionCentre") + addMsg._value = "VisionCentre"; + } else if (isEquals("CentralCoreSlot")) { + if (msg->_value == "CentralCore") + addMsg._value = "CentralCore"; + } + + if (addMsg._value != "NULL") + addMsg.execute("TitaniaControl"); + + if (addMsg._value == "OlfactoryCentre") + loadFrame(2); + else if (addMsg._value == "AuditoryCentre") + loadFrame(1); + else if (addMsg._value == "SpeechCentre") + loadFrame(3); + else if (addMsg._value == "VisionCentre") + loadFrame(4); + else if (addMsg._value == "CentralCore") { + CActMsg actMsg("Insert Central Core"); + actMsg.execute("CentralCoreSlot"); + } + + _target = msg->_value; + _value1 = 1; + return true; +} + +bool CBrainSlot::EnterViewMsg(CEnterViewMsg *msg) { + if (getName() == "CentralCoreSlot") + loadFrame(21); + if (_woken) + _cursorId = CURSOR_ARROW; + + return true; +} + +bool CBrainSlot::ActMsg(CActMsg *msg) { + if (msg->_action == "Insert Central Core") + playMovie(0, 21, 0); + else if (msg->_action == "Woken") + _woken = true; + + return true; +} + +bool CBrainSlot::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!_value1 || _woken || !checkPoint(msg->_mousePos, false, true)) + return false; + + _cursorId = CURSOR_ARROW; + CVisibleMsg visibleMsg(true); + visibleMsg.execute(_target); + CTakeHeadPieceMsg takeMsg(_target); + takeMsg.execute("TitaniaControl"); + + loadFrame(isEquals("CentralCoreSlot") ? 21 : 0); + _value1 = 0; + + CPassOnDragStartMsg passMsg; + passMsg._mousePos = msg->_mousePos; + passMsg.execute(_target); + + msg->_dragItem = getRoot()->findByName(_target); + _added = 0; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/brain_slot.h b/engines/titanic/game/brain_slot.h new file mode 100644 index 0000000000..4d500cc59a --- /dev/null +++ b/engines/titanic/game/brain_slot.h @@ -0,0 +1,60 @@ +/* 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_BRAIN_SLOT_H +#define TITANIC_BRAIN_SLOT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBrainSlot : public CGameObject { + DECLARE_MESSAGE_MAP; + bool SetFrameMsg(CSetFrameMsg *msg); + bool AddHeadPieceMsg(CAddHeadPieceMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool ActMsg(CActMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +public: + static int _added; + static bool _woken; +public: + int _value1; + CString _target; +public: + CLASSDEF; + CBrainSlot() : CGameObject(), _value1(0) {} + + /** + * 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_BRAIN_SLOT_H */ diff --git a/engines/titanic/game/bridge_door.cpp b/engines/titanic/game/bridge_door.cpp new file mode 100644 index 0000000000..bfa30fd650 --- /dev/null +++ b/engines/titanic/game/bridge_door.cpp @@ -0,0 +1,62 @@ +/* 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/game/bridge_door.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBridgeDoor, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CBridgeDoor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CBridgeDoor::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CBridgeDoor::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + setVisible(true); + playMovie(0, 6, 0); + changeView("Titania.Node 12.N"); + + return true; +} + +bool CBridgeDoor::StatusChangeMsg(CStatusChangeMsg *msg) { + setVisible(true); + playMovie(7, 0, MOVIE_NOTIFY_OBJECT); + return true; +} + +bool CBridgeDoor::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bridge_door.h b/engines/titanic/game/bridge_door.h new file mode 100644 index 0000000000..010a8b8bc0 --- /dev/null +++ b/engines/titanic/game/bridge_door.h @@ -0,0 +1,51 @@ +/* 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_BRIDGE_DOOR_H +#define TITANIC_BRIDGE_DOOR_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBridgeDoor : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MovieEndMsg(CMovieEndMsg *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_BRIDGE_DOOR_H */ diff --git a/engines/titanic/game/bridge_view.cpp b/engines/titanic/game/bridge_view.cpp new file mode 100644 index 0000000000..466480a64c --- /dev/null +++ b/engines/titanic/game/bridge_view.cpp @@ -0,0 +1,115 @@ +/* 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/game/bridge_view.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBridgeView, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CBridgeView::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_mode, indent); + CBackground::save(file, indent); +} + +void CBridgeView::load(SimpleFile *file) { + file->readNumber(); + _mode = file->readNumber(); + CBackground::load(file); +} + +bool CBridgeView::ActMsg(CActMsg *msg) { + CTurnOn onMsg; + CSetVolumeMsg volumeMsg; + volumeMsg._secondsTransition = 1; + + if (msg->_action == "End") { + _mode = 4; + petLockInput(); + petHide(); + setVisible(true); + playMovie(MOVIE_NOTIFY_OBJECT); + } else if (msg->_action == "Go") { + _mode = 1; + setVisible(true); + volumeMsg._volume = 100; + volumeMsg.execute("EngineSounds"); + onMsg.execute("EngineSounds"); + playMovie(MOVIE_NOTIFY_OBJECT); + } else { + volumeMsg._volume = 50; + volumeMsg.execute("EngineSounds"); + onMsg.execute("EngineSounds"); + + if (msg->_action == "Cruise") { + _mode = 2; + setVisible(true); + playMovie(MOVIE_NOTIFY_OBJECT); + } else if (msg->_action == "GoENd") { + _mode = 3; + setVisible(true); + CChangeMusicMsg musicMsg; + musicMsg._flags = 1; + musicMsg.execute("BridgeAutoMusicPlayer"); + playSound("a#42.wav"); + playMovie(MOVIE_NOTIFY_OBJECT); + } + } + + return true; +} + +bool CBridgeView::MovieEndMsg(CMovieEndMsg *msg) { + CTurnOff offMsg; + offMsg.execute("EngineSounds"); + + switch (_mode) { + case 0: + case 1: + setVisible(false); + dec54(); + break; + + case 2: { + setVisible(false); + CActMsg actMsg("End"); + actMsg.execute("HomeSequence"); + break; + } + + case 3: + setVisible(false); + changeView("TheEnd.Node 3.N"); + break; + + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/bridge_view.h b/engines/titanic/game/bridge_view.h new file mode 100644 index 0000000000..45cfa3f4c8 --- /dev/null +++ b/engines/titanic/game/bridge_view.h @@ -0,0 +1,53 @@ +/* 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_BRIDGE_VIEW_H +#define TITANIC_BRIDGE_VIEW_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CBridgeView : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +public: + int _mode; +public: + CLASSDEF; + CBridgeView() : CBackground(), _mode(0) {} + + /** + * 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_BRIDGE_VIEW_H */ diff --git a/engines/titanic/game/broken_pell_base.cpp b/engines/titanic/game/broken_pell_base.cpp new file mode 100644 index 0000000000..02c2d873ac --- /dev/null +++ b/engines/titanic/game/broken_pell_base.cpp @@ -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. + * + */ + +#include "titanic/game/broken_pell_base.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CBrokenPellBase, CBackground); + +bool CBrokenPellBase::_v1; +int CBrokenPellBase::_v2; + +void CBrokenPellBase::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_fieldE0, indent); + CBackground::save(file, indent); +} + +void CBrokenPellBase::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + _fieldE0 = file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/broken_pell_base.h b/engines/titanic/game/broken_pell_base.h new file mode 100644 index 0000000000..4ca7eddd20 --- /dev/null +++ b/engines/titanic/game/broken_pell_base.h @@ -0,0 +1,54 @@ +/* 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_BROKEN_PELL_BASE_H +#define TITANIC_BROKEN_PELL_BASE_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CBrokenPellBase : public CBackground { + DECLARE_MESSAGE_MAP; +protected: + static bool _v1; + static int _v2; + + int _fieldE0; +public: + CLASSDEF; + CBrokenPellBase() : CBackground(), _fieldE0(0) {} + + /** + * 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_BROKEN_PELL_BASE_H */ diff --git a/engines/titanic/game/broken_pellerator.cpp b/engines/titanic/game/broken_pellerator.cpp new file mode 100644 index 0000000000..8fb7244b7e --- /dev/null +++ b/engines/titanic/game/broken_pellerator.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/game/broken_pellerator.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBrokenPellerator, CBrokenPellBase) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CBrokenPellerator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string2, indent); + file->writeQuotedLine(_string3, indent); + file->writeQuotedLine(_string4, indent); + file->writeQuotedLine(_string5, indent); + + CBrokenPellBase::save(file, indent); +} + +void CBrokenPellerator::load(SimpleFile *file) { + file->readNumber(); + _string2 = file->readString(); + _string3 = file->readString(); + _string4 = file->readString(); + _string5 = file->readString(); + + CBrokenPellBase::load(file); +} + +bool CBrokenPellerator::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_v1) { + changeView(_v2 ? _string5 : _string4); + } else { + if (_v2) { + playMovie(28, 43, 0); + } else { + playMovie(0, 14, MOVIE_NOTIFY_OBJECT); + } + + _v1 = true; + } + + return true; +} + +bool CBrokenPellerator::LeaveViewMsg(CLeaveViewMsg *msg) { + CString name = msg->_newView->getNodeViewName(); + if (name == "Node 3.S" || name == "Node 3.N") { + _v1 = false; + loadFrame(0); + } + + return true; +} + +bool CBrokenPellerator::ActMsg(CActMsg *msg) { + if (msg->_action == "PlayerGetsHose") { + _v2 = 1; + loadFrame(43); + + CStatusChangeMsg statusMsg; + statusMsg.execute("PickupHose"); + } else { + _fieldE0 = 0; + bool closeFlag = msg->_action == "Close"; + if (msg->_action == "CloseLeft") { + closeFlag = true; + _fieldE0 = 1; + } + if (msg->_action == "CloseRight") { + closeFlag = true; + _fieldE0 = 2; + } + + if (closeFlag) { + if (_v1) { + _v1 = false; + if (_v2) + playMovie(43, 57, MOVIE_NOTIFY_OBJECT); + else + playMovie(14, 28, MOVIE_NOTIFY_OBJECT); + } else { + switch (_fieldE0) { + case 1: + changeView(_string2); + break; + case 2: + changeView(_string3); + break; + default: + break; + } + + _fieldE0 = 0; + } + } + } + + return true; +} + +bool CBrokenPellerator::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == 14) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("PickUpHose"); + } + + if (msg->_endFrame == 28) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PickUpHose"); + } + + switch (_fieldE0) { + case 1: + changeView(_string2); + break; + case 2: + changeView(_string3); + break; + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/broken_pellerator.h b/engines/titanic/game/broken_pellerator.h new file mode 100644 index 0000000000..3b8c3ba587 --- /dev/null +++ b/engines/titanic/game/broken_pellerator.h @@ -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. + * + */ + +#ifndef TITANIC_BROKEN_PELLERATOR_H +#define TITANIC_BROKEN_PELLERATOR_H + +#include "titanic/game/broken_pell_base.h" + +namespace Titanic { + +class CBrokenPellerator : public CBrokenPellBase { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + CString _string2; + CString _string3; + CString _string4; + CString _string5; +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_BROKEN_PELLERATOR_H */ diff --git a/engines/titanic/game/broken_pellerator_froz.cpp b/engines/titanic/game/broken_pellerator_froz.cpp new file mode 100644 index 0000000000..690ab76820 --- /dev/null +++ b/engines/titanic/game/broken_pellerator_froz.cpp @@ -0,0 +1,150 @@ +/* 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/game/broken_pellerator_froz.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBrokenPelleratorFroz, CBrokenPellBase) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CBrokenPelleratorFroz::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string2, indent); + file->writeQuotedLine(_string3, indent); + file->writeQuotedLine(_string4, indent); + file->writeQuotedLine(_string5, indent); + + CBrokenPellBase::save(file, indent); +} + +void CBrokenPelleratorFroz::load(SimpleFile *file) { + file->readNumber(); + _string2 = file->readString(); + _string3 = file->readString(); + _string4 = file->readString(); + _string5 = file->readString(); + + CBrokenPellBase::load(file); +} + +bool CBrokenPelleratorFroz::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_v1) { + changeView(_v2 ? _string5 : _string4); + } else { + _v1 = true; + if (_v2) { + playMovie(0, 13, 0); + } else { + playMovie(43, 55, MOVIE_NOTIFY_OBJECT); + } + } + + return true; +} + +bool CBrokenPelleratorFroz::LeaveViewMsg(CLeaveViewMsg *msg) { + CString name = msg->_newView->getNodeViewName(); + + if (name == "Node 3.S" || name == "Node 3.E") { + _v1 = false; + loadFrame(0); + } + + return true; +} + +bool CBrokenPelleratorFroz::ActMsg(CActMsg *msg) { + if (msg->_action == "PlayerGetsHose") { + _v2 = 1; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("FPickUpHose"); + } else { + _fieldE0 = 0; + bool closeFlag = msg->_action == "Close"; + if (msg->_action == "CloseLeft") { + closeFlag = true; + _fieldE0 = 1; + } + if (msg->_action == "CloseRight") { + closeFlag = true; + _fieldE0 = 2; + } + + if (closeFlag) { + if (_v1) { + _v1 = false; + if (_v2) + playMovie(29, 42, MOVIE_NOTIFY_OBJECT); + else + playMovie(72, 84, MOVIE_NOTIFY_OBJECT); + } else { + switch (_fieldE0) { + case 1: + changeView(_string2); + break; + case 2: + changeView(_string3); + break; + default: + break; + } + + _fieldE0 = 0; + } + } + } + + return true; +} + +bool CBrokenPelleratorFroz::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == 55) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("FPickUpHose"); + } + + if (msg->_endFrame == 84) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("FPickUpHose"); + } + + if (_fieldE0 == 1) { + changeView(_string2); + _fieldE0 = 0; + } else if (_fieldE0 == 2) { + changeView(_string3); + _fieldE0 = 0; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/broken_pellerator_froz.h b/engines/titanic/game/broken_pellerator_froz.h new file mode 100644 index 0000000000..ccdae6ffa8 --- /dev/null +++ b/engines/titanic/game/broken_pellerator_froz.h @@ -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. + * + */ + +#ifndef TITANIC_BROKEN_PELLERATOR_FROZ_H +#define TITANIC_BROKEN_PELLERATOR_FROZ_H + +#include "titanic/game/broken_pell_base.h" + +namespace Titanic { + +class CBrokenPelleratorFroz : public CBrokenPellBase { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + CString _string2; + CString _string3; + CString _string4; + CString _string5; +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_BROKEN_PELLERATOR_FROZ_H */ diff --git a/engines/titanic/game/cage.cpp b/engines/titanic/game/cage.cpp new file mode 100644 index 0000000000..bbac384cea --- /dev/null +++ b/engines/titanic/game/cage.cpp @@ -0,0 +1,110 @@ +/* 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/game/cage.h" +#include "titanic/npcs/parrot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCage, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(PreEnterViewMsg) + ON_MESSAGE(MouseMoveMsg) +END_MESSAGE_MAP() + +int CCage::_v1; +bool CCage::_open; + +void CCage::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_open, indent); + + CBackground::save(file, indent); +} + +void CCage::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _open = file->readNumber(); + + CBackground::load(file); +} + +bool CCage::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (CParrot::_v4 && !CParrot::_v5) { + CActMsg actMsg(_open ? "Open" : "Shut"); + actMsg.execute(this); + } + + return true; +} + +bool CCage::ActMsg(CActMsg *msg) { + if (msg->_action == "Shut") { + if (!_open) { + playClip("Shut", MOVIE_STOP_PREVIOUS | MOVIE_NOTIFY_OBJECT); + disableMouse(); + } + } else if (msg->_action == "Open") { + if (_open) { + playClip("Open", MOVIE_STOP_PREVIOUS | MOVIE_NOTIFY_OBJECT); + disableMouse(); + } + } else if (msg->_action == "CoreReplaced") { + CActMsg actMsg("Shut"); + actMsg.execute(this); + } else if (msg->_action == "OpenNow") { + loadFrame(0); + _open = false; + } + + return true; +} + +bool CCage::MovieEndMsg(CMovieEndMsg *msg) { + enableMouse(); + _open = clipExistsByEnd("Shut", msg->_endFrame); + + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _open ? 1 : (CParrot::_v4 == 0 ? 1 : 0); + statusMsg.execute("PerchCoreHolder"); + + return true; +} + +bool CCage::PreEnterViewMsg(CPreEnterViewMsg *msg) { + loadSurface(); + _open = CParrot::_v4 != 0; + loadFrame(_open ? 8 : 0); + + return true; +} + +bool CCage::MouseMoveMsg(CMouseMoveMsg *msg) { + _cursorId = CParrot::_v4 && !CParrot::_v5 ? CURSOR_ACTIVATE : CURSOR_ARROW; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/cage.h b/engines/titanic/game/cage.h new file mode 100644 index 0000000000..48b1b46ab7 --- /dev/null +++ b/engines/titanic/game/cage.h @@ -0,0 +1,56 @@ +/* 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_CAGE_H +#define TITANIC_CAGE_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CCage : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool PreEnterViewMsg(CPreEnterViewMsg *msg); + bool MouseMoveMsg(CMouseMoveMsg *msg); +public: + static int _v1; + static bool _open; +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_CAGE_H */ diff --git a/engines/titanic/game/captains_wheel.cpp b/engines/titanic/game/captains_wheel.cpp new file mode 100644 index 0000000000..79908b561d --- /dev/null +++ b/engines/titanic/game/captains_wheel.cpp @@ -0,0 +1,209 @@ +/* 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/game/captains_wheel.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCaptainsWheel, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(TurnOff) + ON_MESSAGE(TurnOn) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +CCaptainsWheel::CCaptainsWheel() : CBackground(), + _fieldE0(0), _fieldE4(0), _fieldE8(0), _fieldEC(0), + _fieldF0(0), _fieldF4(0) { +} + +void CCaptainsWheel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_fieldF4, indent); + + CBackground::save(file, indent); +} + +void CCaptainsWheel::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + _fieldF4 = file->readNumber(); + + CBackground::load(file); +} + +bool CCaptainsWheel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_fieldE0) { + _fieldE0 = false; + CTurnOff offMsg; + offMsg.execute(this); + playMovie(162, 168, 0); + } else { + playMovie(0, 8, MOVIE_NOTIFY_OBJECT); + } + + return true; +} + +bool CCaptainsWheel::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_fieldE0) { + _fieldE0 = false; + CTurnOff offMsg; + offMsg.execute(this); + playMovie(162, 168, MOVIE_GAMESTATE); + } + + return true; +} + +bool CCaptainsWheel::ActMsg(CActMsg *msg) { + if (msg->_action == "Spin") { + if (_fieldE0) { + CTurnOn onMsg; + onMsg.execute("RatchetySound"); + playMovie(8, 142, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } else if (msg->_action == "Honk") { + if (_fieldE0) { + playMovie(150, 160, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } else if (msg->_action == "Go") { + if (!_fieldE0) { + inc54(); + _fieldE0 = false; + _fieldE4 = 1; + + CTurnOff offMsg; + offMsg.execute(this); + playMovie(162, 168, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } else if (msg->_action == "Cruise") { + if (_fieldE0) { + inc54(); + _fieldE0 = false; + _fieldE4 = 2; + + CTurnOff offMsg; + offMsg.execute(this); + playMovie(162, 168, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } else if (msg->_action == "SetDestin") { + playSound("a#44.wav"); + CSetVolumeMsg volumeMsg; + volumeMsg._volume = 25; + volumeMsg.execute("EngineSounds"); + CTurnOn onMsg; + onMsg.execute("EngineSounds"); + _fieldF0 = 1; + } else if (msg->_action == "ClearDestin") { + _fieldF0 = 0; + } + + return true; +} + +bool CCaptainsWheel::TurnOff(CTurnOff *msg) { + CSignalObject signalMsg; + signalMsg._numValue = 0; + + static const char *const NAMES[8] = { + "WheelSpin", "SeagullHorn", "WheelStopButt", "StopHotSpot", + "WheelCruiseButt", "CruiseHotSpot", "WheelGoButt","GoHotSpot" + }; + for (int idx = 0; idx < 8; ++idx) + signalMsg.execute(NAMES[idx]); + + return true; +} + +bool CCaptainsWheel::TurnOn(CTurnOn *msg) { + CSignalObject signalMsg; + signalMsg._numValue = 1; + signalMsg.execute("WheelSpin"); + signalMsg.execute("SeagullHorn"); + + if (_fieldE0) { + signalMsg.execute("WheelStopButt"); + signalMsg.execute("StopHotSpot"); + } + + if (_fieldEC) { + signalMsg.execute("WheelCruiseButt"); + signalMsg.execute("CruiseHotSpot"); + } + + if (_fieldF0) { + signalMsg.execute("WheelGoButt"); + signalMsg.execute("GoHotSpot"); + } + + return true; +} + +bool CCaptainsWheel::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == 8) { + _fieldE0 = true; + CTurnOn onMsg; + onMsg.execute(this); + } + + if (msg->_endFrame == 142) { + CTurnOff offMsg; + offMsg.execute("RatchetySound"); + } + + if (msg->_endFrame == 168) { + switch (_fieldE4) { + case 1: { + CActMsg actMsg(starFn2() ? "GoEnd" : "Go"); + actMsg.execute("GoSequence"); + break; + } + + case 2: { + CActMsg actMsg("Cruise"); + actMsg.execute("CruiseSequence"); + break; + } + + default: + break; + } + + _fieldE4 = 0; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/captains_wheel.h b/engines/titanic/game/captains_wheel.h new file mode 100644 index 0000000000..3aca45c21f --- /dev/null +++ b/engines/titanic/game/captains_wheel.h @@ -0,0 +1,62 @@ +/* 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_CAPTAINS_WHEEL_H +#define TITANIC_CAPTAINS_WHEEL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CCaptainsWheel : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool ActMsg(CActMsg *msg); + bool TurnOff(CTurnOff *msg); + bool TurnOn(CTurnOn *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _fieldF0; + int _fieldF4; +public: + CLASSDEF; + CCaptainsWheel(); + + /** + * 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_CAPTAINS_WHEEL_H */ diff --git a/engines/titanic/game/cdrom.cpp b/engines/titanic/game/cdrom.cpp new file mode 100644 index 0000000000..cd913d05f7 --- /dev/null +++ b/engines/titanic/game/cdrom.cpp @@ -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. + * + */ + +#include "titanic/game/cdrom.h" +#include "titanic/core/room_item.h" +#include "titanic/game/cdrom_tray.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCDROM, CGameObject) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(MouseDragMoveMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +CCDROM::CCDROM() : CGameObject() { +} + +void CCDROM::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_tempPos, indent); + CGameObject::save(file, indent); +} + +void CCDROM::load(SimpleFile *file) { + file->readNumber(); + _tempPos = file->readPoint(); + CGameObject::load(file); +} + +bool CCDROM::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkStartDragging(msg)) { + _tempPos = msg->_mousePos - _bounds; + setPosition(msg->_mousePos - _tempPos); + return true; + } else { + return false; + } +} + +bool CCDROM::MouseDragEndMsg(CMouseDragEndMsg *msg) { + if (msg->_dropTarget && msg->_dropTarget->getName() == "newComputer") { + CCDROMTray *newTray = dynamic_cast<CCDROMTray *>(getRoom()->findByName("newTray")); + + if (newTray->_isOpened && newTray->_insertedCD == "None") { + CActMsg actMsg(getName()); + actMsg.execute(newTray); + setVisible(false); + } + } + + resetPosition(); + return true; +} + +bool CCDROM::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + setPosition(msg->_mousePos - _tempPos); + return true; +} + +bool CCDROM::ActMsg(CActMsg *msg) { + if (msg->_action == "Ejected") + setVisible(true); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/cdrom.h b/engines/titanic/game/cdrom.h new file mode 100644 index 0000000000..017914830c --- /dev/null +++ b/engines/titanic/game/cdrom.h @@ -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. + * + */ + +#ifndef TITANIC_CDROM_H +#define TITANIC_CDROM_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CCDROM : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + bool ActMsg(CActMsg *msg); +private: + Point _tempPos; +public: + CLASSDEF; + CCDROM(); + + /** + * 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_CDROM_H */ diff --git a/engines/titanic/game/cdrom_computer.cpp b/engines/titanic/game/cdrom_computer.cpp new file mode 100644 index 0000000000..ceb0595188 --- /dev/null +++ b/engines/titanic/game/cdrom_computer.cpp @@ -0,0 +1,78 @@ +/* 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/game/cdrom_computer.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCDROMComputer, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CCDROMComputer::CCDROMComputer() : CGameObject(), + _clickRect(0, 3, 55, 32) { +} + +void CCDROMComputer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_clickRect.left, indent); + file->writeNumberLine(_clickRect.top, indent); + file->writeNumberLine(_clickRect.right, indent); + file->writeNumberLine(_clickRect.bottom, indent); + + CGameObject::save(file, indent); +} + +void CCDROMComputer::load(SimpleFile *file) { + file->readNumber(); + _clickRect.left = file->readNumber(); + _clickRect.top = file->readNumber(); + _clickRect.right = file->readNumber(); + _clickRect.bottom = file->readNumber(); + + CGameObject::load(file); +} + +bool CCDROMComputer::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CTreeItem *tray = getRoom()->findByName("newTray"); + if (tray) { + CStatusChangeMsg statusMsg; + statusMsg.execute(tray); + + if (!statusMsg._success) { + // Check if the mouse is within the clickable area + Rect tempRect = _clickRect; + tempRect.translate(_bounds.left, _bounds.top); + + if (!tempRect.contains(msg->_mousePos)) + return true; + } + + CActMsg actMsg("ClickedOn"); + actMsg.execute(tray); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/cdrom_computer.h b/engines/titanic/game/cdrom_computer.h new file mode 100644 index 0000000000..39fa9b9498 --- /dev/null +++ b/engines/titanic/game/cdrom_computer.h @@ -0,0 +1,53 @@ +/* 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_CDROM_COMPUTER_H +#define TITANIC_CDROM_COMPUTER_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CCDROMComputer : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + Rect _clickRect; +public: + CLASSDEF; + CCDROMComputer(); + + /** + * 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_CDROM_COMPUTER_H */ diff --git a/engines/titanic/game/cdrom_tray.cpp b/engines/titanic/game/cdrom_tray.cpp new file mode 100644 index 0000000000..1e5b135d35 --- /dev/null +++ b/engines/titanic/game/cdrom_tray.cpp @@ -0,0 +1,127 @@ +/* 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/core/room_item.h" +#include "titanic/game/cdrom_tray.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCDROMTray, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + + +CCDROMTray::CCDROMTray() : CGameObject(), _isOpened(false) { +} + +void CCDROMTray::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_isOpened, indent); + file->writeQuotedLine(_insertedCD, indent); + + CGameObject::save(file, indent); +} + +void CCDROMTray::load(SimpleFile *file) { + file->readNumber(); + _isOpened = file->readNumber(); + _insertedCD = file->readString(); + + CGameObject::load(file); +} + +bool CCDROMTray::ActMsg(CActMsg *msg) { + if (msg->_action == "ClickedOn") { + if (_isOpened) { + // Closing the tray + if (_insertedCD == "None") { + // No CD in tray + playMovie(55, 65, 0); + playSound("a#35.wav", 50, 0, 0); + _isOpened = false; + } else { + // Ejecting tray with CD + CTreeItem *cdrom = getRoom()->findByName(_insertedCD); + if (cdrom) { + CActMsg actMsg("Ejected"); + actMsg.execute(cdrom); + } + + _insertedCD = "None"; + loadFrame(52); + } + } else if (_insertedCD == "None") { + // Opening tray with no CD + playMovie(44, 54, 0); + playSound("a#34.wav", 50, 0, 0); + _isOpened = true; + } else if (_insertedCD == "newCD1" || _insertedCD == "newCD2") { + // Opening tray with standard CD + playMovie(22, 32, 0); + playSound("a#34.wav", 50, 0, 0); + _isOpened = true; + } else if (_insertedCD == "newSTCD") { + // Opening tray with Starship Titanic CD + playMovie(0, 10, 0); + playSound("a#34.wav", 50, 0, 0); + _isOpened = true; + } + } else if (_isOpened) { + if (msg->_action == "newCD1" || msg->_action == "newCD2") { + // Standard CD dropped on CDROM Tray + playMovie(33, 43, MOVIE_NOTIFY_OBJECT); + playSound("a#35.wav", 50, 0, 0); + } else if (msg->_action == "newSTCD") { + // Starship Titanic CD dropped on CDROM Tray + playMovie(11, 21, MOVIE_NOTIFY_OBJECT); + playSound("a#35.wav", 50, 0, 0); + } else { + return true; + } + + _insertedCD = msg->_action; + _isOpened = false; + } + + return true; +} + +bool CCDROMTray::MovieEndMsg(CMovieEndMsg *msg) { + CTreeItem *screen = getRoom()->findByName("newScreen"); + + if (screen) { + CActMsg actMsg(_insertedCD); + actMsg.execute(screen); + } + + return true; +} + +bool CCDROMTray::StatusChangeMsg(CStatusChangeMsg *msg) { + msg->_success = _isOpened; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/cdrom_tray.h b/engines/titanic/game/cdrom_tray.h new file mode 100644 index 0000000000..10fc1e145e --- /dev/null +++ b/engines/titanic/game/cdrom_tray.h @@ -0,0 +1,56 @@ +/* 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_CDROM_TRAY_H +#define TITANIC_CDROM_TRAY_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CCDROMTray : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +public: + bool _isOpened; + CString _insertedCD; +public: + CLASSDEF; + CCDROMTray(); + + /** + * 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_CDROM_TRAY_H */ diff --git a/engines/titanic/game/cell_point_button.cpp b/engines/titanic/game/cell_point_button.cpp new file mode 100644 index 0000000000..207dd73543 --- /dev/null +++ b/engines/titanic/game/cell_point_button.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 "titanic/game/cell_point_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCellPointButton, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CCellPointButton::CCellPointButton() : CBackground() { + _fieldE0 = 0; + _fieldE4 = 0; + _fieldE8 = 0; + _fieldEC = 0; + _regionNum = 0; + _fieldF4 = 0; + _fieldF8 = 0; + _fieldFC = 0; + _field100 = 0; + _field104 = 0; + _field108 = 1; +} + +void CCellPointButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_regionNum, indent); + file->writeNumberLine(_fieldF4, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_fieldFC, indent); + file->writeNumberLine(_field100, indent); + file->writeNumberLine(_field104, indent); + file->writeNumberLine(_field108, indent); + file->writeQuotedLine(_string3, indent); + file->writeNumberLine(_dialNum, indent); + + CBackground::save(file, indent); +} + +void CCellPointButton::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _regionNum = file->readNumber(); + _fieldF4 = file->readNumber(); + _fieldF8 = file->readNumber(); + _fieldFC = file->readNumber(); + _field100 = file->readNumber(); + _field104 = file->readNumber(); + _field108 = file->readNumber(); + _string3 = file->readString(); + _dialNum = file->readNumber(); + + CBackground::load(file); +} + +bool CCellPointButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (getRandomNumber(2) == 0) { + CParrotSpeakMsg speakMsg("Cellpoints", _string3); + speakMsg.execute("PerchedParrot"); + } + + playMovie(0); + _regionNum = _regionNum ? 0 : 1; + playSound("z#425.wav"); + talkSetDialRegion(_string3, _dialNum, _regionNum); + + return true; +} + +bool CCellPointButton::EnterViewMsg(CEnterViewMsg *msg) { + _regionNum = talkGetDialRegion(_string3, _dialNum); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/cell_point_button.h b/engines/titanic/game/cell_point_button.h new file mode 100644 index 0000000000..33f58cbb83 --- /dev/null +++ b/engines/titanic/game/cell_point_button.h @@ -0,0 +1,65 @@ +/* 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_CELL_POINT_BUTTON_H +#define TITANIC_CELL_POINT_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CCellPointButton : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _regionNum; + int _fieldF4; + int _fieldF8; + int _fieldFC; + int _field100; + int _field104; + int _field108; + CString _string3; + int _dialNum; +public: + CLASSDEF; + CCellPointButton(); + + /** + * 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_CELL_POINT_BUTTON_H */ diff --git a/engines/titanic/game/chev_code.cpp b/engines/titanic/game/chev_code.cpp new file mode 100644 index 0000000000..0acdf575f4 --- /dev/null +++ b/engines/titanic/game/chev_code.cpp @@ -0,0 +1,285 @@ +/* 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/game/chev_code.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChevCode, CGameObject) + ON_MESSAGE(SetChevLiftBits) + ON_MESSAGE(SetChevClassBits) + ON_MESSAGE(SetChevFloorBits) + ON_MESSAGE(SetChevRoomBits) + ON_MESSAGE(GetChevLiftNum) + ON_MESSAGE(GetChevClassNum) + ON_MESSAGE(GetChevFloorNum) + ON_MESSAGE(GetChevRoomNum) + ON_MESSAGE(CheckChevCode) + ON_MESSAGE(GetChevCodeFromRoomNameMsg) +END_MESSAGE_MAP() + +void CChevCode::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_chevCode, indent); + CGameObject::save(file, indent); +} + +void CChevCode::load(SimpleFile *file) { + file->readNumber(); + _chevCode = file->readNumber(); + CGameObject::load(file); +} + +bool CChevCode::SetChevLiftBits(CSetChevLiftBits *msg) { + _chevCode &= ~0xC0000; + if (msg->_liftNum > 0 && msg->_liftNum < 5) + _chevCode = ((msg->_liftNum - 1) << 18) | _chevCode; + + return true; +} + +bool CChevCode::SetChevClassBits(CSetChevClassBits *msg) { + _chevCode &= ~0x30000; + if (msg->_classNum > 0 && msg->_classNum < 4) + _chevCode = (msg->_classNum << 16) | msg->_classNum; + + return true; +} + +bool CChevCode::SetChevFloorBits(CSetChevFloorBits *msg) { + int section = (msg->_floorNum + 4) / 10; + int index = (msg->_floorNum + 4) % 10; + _chevCode &= ~0xFF00; + + int val = 0; + switch (section) { + case 0: + val = 144; + break; + case 1: + val = 208; + break; + case 2: + val = 224; + break; + case 3: + val = 240; + break; + default: + break; + } + + _chevCode |= ((index + val) << 8); + return true; +} + +bool CChevCode::SetChevRoomBits(CSetChevRoomBits *msg) { + _chevCode &= ~0xff; + if (msg->_roomNum > 0 && msg->_roomNum < 128) + _chevCode |= msg->_roomNum * 2; + + return true; +} + +bool CChevCode::GetChevLiftNum(CGetChevLiftNum *msg) { + msg->_liftNum = ((_chevCode >> 18) & 3) + 1; + return true; +} + +bool CChevCode::GetChevClassNum(CGetChevClassNum *msg) { + msg->_classNum = (_chevCode >> 16) & 3; + return true; +} + +bool CChevCode::GetChevFloorNum(CGetChevFloorNum *msg) { + int val1 = (_chevCode >> 8) & 0xF; + int val2 = ((_chevCode >> 12) & 0xF) - 9; + + switch (val2) { + case 0: + val2 = 0; + break; + case 4: + val2 = 1; + break; + case 5: + val2 = 2; + break; + case 6: + val2 = 3; + break; + default: + val2 = 4; + break; + } + + msg->_floorNum = (val1 >= 10) ? 0 : val1 * 10; + return true; +} + +bool CChevCode::GetChevRoomNum(CGetChevRoomNum *msg) { + msg->_roomNum = (_chevCode >> 1) & 0x7F; + return true; +} + +bool CChevCode::CheckChevCode(CCheckChevCode *msg) { + CGetChevClassNum getClassMsg; + CGetChevLiftNum getLiftMsg; + CGetChevFloorNum getFloorMsg; + CGetChevRoomNum getRoomMsg; + CString roomName; + int classNum = 0; + uint bits = 0; + + if (_chevCode & 1) { + switch (_chevCode) { + case 0x1D0D9: + roomName = "ParrLobby"; + classNum = 4; + break; + case 0x196D9: + roomName = "FCRestrnt"; + classNum = 4; + break; + case 0x39FCB: + roomName = "Bridge"; + classNum = 4; + break; + case 0x2F86D: + roomName = "CrtrsCham"; + classNum = 4; + break; + case 0x465FB: + roomName = "SculpCham"; + classNum = 4; + break; + case 0x3D94B: + roomName = "BilgeRoom"; + classNum = 4; + break; + case 0x59FAD: + roomName = "BoWell"; + classNum = 4; + break; + case 0x4D6AF: + roomName = "Arboretum"; + classNum = 4; + break; + case 0x8A397: + roomName = "TitRoom"; + classNum = 4; + break; + case 0x79C45: + roomName = "PromDeck"; + classNum = 4; + break; + case 0xB3D97: + roomName = "Bar"; + classNum = 4; + break; + case 0xCC971: + roomName = "EmbLobby"; + classNum = 4; + break; + case 0xF34DB: + roomName = "MusicRoom"; + classNum = 4; + break; + default: + roomName = "BadRoom"; + classNum = 5; + break; + } + + bits = classNum == 5 ? 0x3D94B : _chevCode; + } else { + getFloorMsg.execute(this); + getRoomMsg.execute(this); + getClassMsg.execute(this); + getLiftMsg.execute(this); + if (getFloorMsg._floorNum > 37 || getRoomMsg._roomNum > 18) + classNum = 5; + + if (classNum == 5) { + bits = 0x3D94B; + } else { + switch (getClassMsg._classNum) { + case 1: + if (getFloorMsg._floorNum >= 2 && getFloorMsg._floorNum <= 18 + && getRoomMsg._roomNum >= 1 && getRoomMsg._roomNum <= 3 + && getLiftMsg._liftNum >= 1 && getLiftMsg._liftNum <= 4) + classNum = 1; + else + classNum = 5; + break; + + case 2: + if (getFloorMsg._floorNum >= 19 && getFloorMsg._floorNum <= 26 + && getRoomMsg._roomNum >= 1 && getRoomMsg._roomNum <= 5 + && getLiftMsg._liftNum >= 1 && getLiftMsg._liftNum <= 4) + classNum = 2; + else + classNum = 5; + break; + + case 3: + if (getFloorMsg._floorNum >= 27 && getFloorMsg._floorNum <= 37 + && getRoomMsg._roomNum >= 1 && getRoomMsg._roomNum <= 18 + && (getLiftMsg._liftNum & 1) == 1 + && getLiftMsg._liftNum >= 1 && getLiftMsg._liftNum <= 4) + classNum = 3; + else + classNum = 5; + break; + } + } + } + + msg->_classNum = classNum; + msg->_chevCode = bits; + + // WORKAROUND: Skipped code from original that was for debugging purposes only + return true; +} + +bool CChevCode::GetChevCodeFromRoomNameMsg(CGetChevCodeFromRoomNameMsg *msg) { + static const char *const ROOM_NAMES[13] = { + "ParrotLobby", "sculptureChamber", "Bar", "EmbLobby", "MusicRoom", + "Titania", "BottomOfWell", "Arboretum", "PromenadeDeck", + "FCRestrnt", "CrtrsCham", "BilgeRoom", "Bridge" + }; + static const uint CHEV_CODES[13] = { + 0x1D0D9, 0x465FB, 0xB3D97, 0xCC971, 0xF34DB, 0x8A397, 0x59FAD, + 0x4D6AF, 0x79C45, 0x196D9, 0x2F86D, 0x3D94B, 0x39FCB + }; + + for (int idx = 0; idx < 13; ++idx) { + if (msg->_roomName == ROOM_NAMES[idx]) { + msg->_chevCode = CHEV_CODES[idx]; + break; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/chev_code.h b/engines/titanic/game/chev_code.h new file mode 100644 index 0000000000..4a71b13f9e --- /dev/null +++ b/engines/titanic/game/chev_code.h @@ -0,0 +1,61 @@ +/* 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_CHEV_CODE_H +#define TITANIC_CHEV_CODE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CChevCode : public CGameObject { + DECLARE_MESSAGE_MAP; + bool SetChevLiftBits(CSetChevLiftBits *msg); + bool SetChevClassBits(CSetChevClassBits *msg); + bool SetChevFloorBits(CSetChevFloorBits *msg); + bool SetChevRoomBits(CSetChevRoomBits *msg); + bool GetChevLiftNum(CGetChevLiftNum *msg); + bool GetChevClassNum(CGetChevClassNum *msg); + bool GetChevFloorNum(CGetChevFloorNum *msg); + bool GetChevRoomNum(CGetChevRoomNum *msg); + bool CheckChevCode(CCheckChevCode *msg); + bool GetChevCodeFromRoomNameMsg(CGetChevCodeFromRoomNameMsg *msg); +public: + int _chevCode; +public: + CLASSDEF; + CChevCode() : CGameObject(), _chevCode(0) {} + + /** + * 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_CHEV_CODE_H */ diff --git a/engines/titanic/game/chev_panel.cpp b/engines/titanic/game/chev_panel.cpp new file mode 100644 index 0000000000..ed730c9d61 --- /dev/null +++ b/engines/titanic/game/chev_panel.cpp @@ -0,0 +1,121 @@ +/* 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/game/chev_panel.h" +#include "titanic/game/chev_code.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChevPanel, CGameObject) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseDragMoveMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(SetChevPanelBitMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(ClearChevPanelBits) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(SetChevPanelButtonsMsg) +END_MESSAGE_MAP() + +void CChevPanel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_startPos.x, indent); + file->writeNumberLine(_startPos.y, indent); + file->writeNumberLine(_chevCode, indent); + + CGameObject::save(file, indent); +} + +void CChevPanel::load(SimpleFile *file) { + file->readNumber(); + _startPos.x = file->readNumber(); + _startPos.y = file->readNumber(); + _chevCode = file->readNumber(); + + CGameObject::load(file); +} + +bool CChevPanel::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkStartDragging(msg)) { + _startPos = Point(msg->_mousePos.x - _bounds.left, + msg->_mousePos.y - _bounds.top); + CChildDragStartMsg dragMsg(_startPos); + dragMsg.execute(this, nullptr, MSGFLAG_SCAN); + } + + return true; +} + +bool CChevPanel::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + CChildDragMoveMsg dragMsg(_startPos); + dragMsg.execute(this, nullptr, MSGFLAG_SCAN); + + setPosition(msg->_mousePos - _startPos); + return true; +} + +bool CChevPanel::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + CChevCode chevCode; + chevCode._chevCode = _chevCode; + CCheckChevCode checkCode; + checkCode.execute(this); + CClearChevPanelBits panelBits; + panelBits.execute(this, nullptr, MSGFLAG_SCAN); + CSetChevPanelButtonsMsg setMsg; + setMsg._chevCode = checkCode._chevCode; + setMsg.execute(this); + + return true; +} + +bool CChevPanel::SetChevPanelBitMsg(CSetChevPanelBitMsg *msg) { + _chevCode = (_chevCode & ~(1 << msg->_value1)) | (msg->_value2 << msg->_value1); + return true; +} + +bool CChevPanel::MouseDragEndMsg(CMouseDragEndMsg *msg) { + setPosition(msg->_mousePos - _startPos); + return true; +} + +bool CChevPanel::ClearChevPanelBits(CClearChevPanelBits *msg) { + CSetChevPanelButtonsMsg setMsg; + setMsg._chevCode = 0; + setMsg.execute(this); + + return true; +} + +bool CChevPanel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CChevPanel::SetChevPanelButtonsMsg(CSetChevPanelButtonsMsg *msg) { + _chevCode = msg->_chevCode; + CSetChevButtonImageMsg setMsg; + setMsg._value2 = 1; + setMsg.execute(this, nullptr, MSGFLAG_SCAN); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/chev_panel.h b/engines/titanic/game/chev_panel.h new file mode 100644 index 0000000000..bcfb920221 --- /dev/null +++ b/engines/titanic/game/chev_panel.h @@ -0,0 +1,60 @@ +/* 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_CHEV_PANEL_H +#define TITANIC_CHEV_PANEL_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CChevPanel : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool SetChevPanelBitMsg(CSetChevPanelBitMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool ClearChevPanelBits(CClearChevPanelBits *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool SetChevPanelButtonsMsg(CSetChevPanelButtonsMsg *msg); +public: + Point _startPos; + int _chevCode; +public: + CLASSDEF; + CChevPanel() : _chevCode(0) {} + + /** + * 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_CHEV_PANEL_H */ diff --git a/engines/titanic/game/chicken_cooler.cpp b/engines/titanic/game/chicken_cooler.cpp new file mode 100644 index 0000000000..d10405de38 --- /dev/null +++ b/engines/titanic/game/chicken_cooler.cpp @@ -0,0 +1,79 @@ +/* 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/game/chicken_cooler.h" +#include "titanic/carry/chicken.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChickenCooler, CGameObject) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CChickenCooler::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + + CGameObject::save(file, indent); +} + +void CChickenCooler::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + + CGameObject::load(file); +} + +bool CChickenCooler::EnterRoomMsg(CEnterRoomMsg *msg) { + if (_fieldC0) { + CGameObject *obj = getMailManFirstObject(); + if (obj) { + // WORKAROUND: Redundant loop for chicken in originalhere + } else { + getNextMail(nullptr); + if (CChicken::_v1 > _fieldBC) + CChicken::_v1 = _fieldBC; + } + } + + return true; +} + +bool CChickenCooler::EnterViewMsg(CEnterViewMsg *msg) { + if (!_fieldC0) { + for (CGameObject *obj = getMailManFirstObject(); obj; + obj = getNextMail(obj)) { + if (obj->isEquals("Chicken")) + return true; + } + + if (CChicken::_v1 > _fieldBC) + CChicken::_v1 = _fieldBC; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/chicken_cooler.h b/engines/titanic/game/chicken_cooler.h new file mode 100644 index 0000000000..54dba90686 --- /dev/null +++ b/engines/titanic/game/chicken_cooler.h @@ -0,0 +1,55 @@ +/* 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_CHICKEN_COOLER_H +#define TITANIC_CHICKEN_COOLER_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CChickenCooler : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + int _fieldBC; + int _fieldC0; +public: + CLASSDEF; + CChickenCooler() : CGameObject(), _fieldBC(0), _fieldC0(0) {} + + /** + * 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_CHICKEN_COOLER_H */ diff --git a/engines/titanic/game/chicken_dispensor.cpp b/engines/titanic/game/chicken_dispensor.cpp new file mode 100644 index 0000000000..7fb8fefcda --- /dev/null +++ b/engines/titanic/game/chicken_dispensor.cpp @@ -0,0 +1,189 @@ +/* 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/game/chicken_dispensor.h" +#include "titanic/core/project_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChickenDispensor, CBackground) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +CChickenDispensor::CChickenDispensor() : CBackground(), + _fieldE0(0), _fieldE4(0), _fieldE8(0) { +} + +void CChickenDispensor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + CBackground::save(file, indent); +} + +void CChickenDispensor::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + + CBackground::load(file); +} + +bool CChickenDispensor::StatusChangeMsg(CStatusChangeMsg *msg) { + msg->execute("SGTRestLeverAnimation"); + int v1 = _fieldE8 ? 0 : _fieldE4; + CPetControl *pet = getPetControl(); + CGameObject *obj; + + for (obj = pet->getFirstObject(); obj; obj = pet->getNextObject(obj)) { + if (obj->isEquals("Chicken")) { + petDisplayMessage(1, "Chickens are allocated on a one-per-customer basis."); + return true; + } + } + + for (obj = getMailManFirstObject(); obj; obj = getNextMail(obj)) { + if (obj->isEquals("Chicken")) { + petDisplayMessage(1, "Chickens are allocated on a one-per-customer basis."); + return true; + } + } + + if (v1 == 1 || v1 == 2) + _fieldE8 = 1; + + switch (v1) { + case 0: + petDisplayMessage(1, "Only one piece of chicken per passenger. Thank you."); + break; + case 1: + setVisible(true); + if (_fieldE0) { + playMovie(0, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("z#400.wav"); + _fieldE4 = 0; + } else { + playMovie(12, 16, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _fieldE8 = 1; + _fieldE4 = 0; + } + break; + + case 2: + setVisible(true); + if (_fieldE0) { + playMovie(0, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("z#400.wav"); + } else { + playMovie(12, 16, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _fieldE8 = 1; + } + break; + + default: + break; + } + + return true; +} + +bool CChickenDispensor::MovieEndMsg(CMovieEndMsg *msg) { + if (getMovieFrame() == 16) { + playSound("b#50.wav", 50); + CActMsg actMsg("Dispense Chicken"); + actMsg.execute("Chicken"); + } else if (_fieldE8) { + _cursorId = CURSOR_ARROW; + loadFrame(0); + setVisible(false); + if (_fieldE4 == 2) + _fieldE8 = 0; + } else { + loadFrame(0); + setVisible(false); + changeView("SgtLobby.Node 1.N"); + } + + return true; +} + +bool CChickenDispensor::ActMsg(CActMsg *msg) { + if (msg->_action == "EnableObject") + _fieldE0 = 0; + else if (msg->_action == "DisableObject") + _fieldE0 = 1; + else if (msg->_action == "IncreaseQuantity") + _fieldE4 = 2; + else if (msg->_action == "DecreaseQuantity") + _fieldE4 = 1; + + return true; +} + +bool CChickenDispensor::LeaveViewMsg(CLeaveViewMsg *msg) { + return true; +} + +bool CChickenDispensor::EnterViewMsg(CEnterViewMsg *msg) { + playSound("b#51.wav"); + _fieldE8 = 0; + _cursorId = CURSOR_ARROW; + return true; +} + +bool CChickenDispensor::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (getMovieFrame() == 16) { + setVisible(false); + loadFrame(0); + _cursorId = CURSOR_ARROW; + _fieldE8 = 1; + + CVisibleMsg visibleMsg; + visibleMsg.execute("Chicken"); + CPassOnDragStartMsg passMsg(msg->_mousePos, 1); + passMsg.execute("Chicken"); + + msg->_dragItem = getRoot()->findByName("Chicken"); + } + + return true; +} + +bool CChickenDispensor::TurnOff(CTurnOff *msg) { + if (getMovieFrame() == 16) + setVisible(false); + playMovie(16, 12, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _fieldE8 = 0; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/chicken_dispensor.h b/engines/titanic/game/chicken_dispensor.h new file mode 100644 index 0000000000..5e3ba47ee8 --- /dev/null +++ b/engines/titanic/game/chicken_dispensor.h @@ -0,0 +1,60 @@ +/* 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_CHICKEN_DISPENSOR_H +#define TITANIC_CHICKEN_DISPENSOR_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CChickenDispensor : public CBackground { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool ActMsg(CActMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool TurnOff(CTurnOff *msg); +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; +public: + CLASSDEF; + CChickenDispensor(); + + /** + * 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_CHICKEN_DISPENSOR_H */ diff --git a/engines/titanic/game/close_broken_pel.cpp b/engines/titanic/game/close_broken_pel.cpp new file mode 100644 index 0000000000..c234590849 --- /dev/null +++ b/engines/titanic/game/close_broken_pel.cpp @@ -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. + * + */ + +#include "titanic/game/close_broken_pel.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCloseBrokenPel, CBackground) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CCloseBrokenPel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_target, indent); + CBackground::save(file, indent); +} + +void CCloseBrokenPel::load(SimpleFile *file) { + file->readNumber(); + _target = file->readString(); + CBackground::load(file); +} + +bool CCloseBrokenPel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CActMsg actMsg("Close"); + actMsg.execute(_target); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/close_broken_pel.h b/engines/titanic/game/close_broken_pel.h new file mode 100644 index 0000000000..4bd66255df --- /dev/null +++ b/engines/titanic/game/close_broken_pel.h @@ -0,0 +1,51 @@ +/* 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_CLOSE_BROKEN_PEL_H +#define TITANIC_CLOSE_BROKEN_PEL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CCloseBrokenPel : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + CString _target; +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_CLOSE_BROKEN_PEL_H */ diff --git a/engines/titanic/game/code_wheel.cpp b/engines/titanic/game/code_wheel.cpp new file mode 100644 index 0000000000..94ee25435a --- /dev/null +++ b/engines/titanic/game/code_wheel.cpp @@ -0,0 +1,108 @@ +/* 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/game/code_wheel.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CodeWheel, CBomb) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +CodeWheel::CodeWheel() : CBomb(), _field108(0), _state(4), _field110(0) { +} + +void CodeWheel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field108, indent); + file->writeNumberLine(_state, indent); + file->writeNumberLine(_field110, indent); + + CBomb::save(file, indent); +} + +void CodeWheel::load(SimpleFile *file) { + file->readNumber(); + _field108 = file->readNumber(); + _state = file->readNumber(); + _field110 = file->readNumber(); + + CBomb::load(file); +} + +bool CodeWheel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + static const int START_FRAMES[15] = { + 0, 5, 10, 15, 19, 24, 28, 33, 38, 42, 47, 52, 57, 61, 66 + }; + static const int END_FRAMES[15] = { + 5, 10, 15, 19, 24, 28, 33, 38, 42, 47, 52, 57, 61, 66, 70 + }; + + int yp = _bounds.top + _bounds.height() / 2; + if (msg->_mousePos.y > yp) { + if (_state == _field108) + _field110 = true; + + _state = (_state + 1) % 15; + playMovie(START_FRAMES[_state], END_FRAMES[_state], + MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT); + } else { + if (_state == _field108) + _field110 = true; + + playMovie(START_FRAMES[14 - _state] + 68, END_FRAMES[14 - _state] + 68, + MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT); + + _state = (_state <= 0) ? 14 : _state - 1; + } + + playSound("z#59.wav"); + return true; +} + +bool CodeWheel::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(24); + _state = 4; + return true; +} + +bool CodeWheel::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return true; +} + +bool CodeWheel::MovieEndMsg(CMovieEndMsg *msg) { + sleep(200); + CStatusChangeMsg changeMsg; + changeMsg._newStatus = 0; + if (_field110) + changeMsg._newStatus = -1; + if (_field108 == _state) + changeMsg._newStatus = 1; + changeMsg.execute("Bomb"); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/code_wheel.h b/engines/titanic/game/code_wheel.h new file mode 100644 index 0000000000..e38a45b631 --- /dev/null +++ b/engines/titanic/game/code_wheel.h @@ -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. + * + */ + +#ifndef TITANIC_CODE_WHEEL_H +#define TITANIC_CODE_WHEEL_H + +#include "titanic/game/bomb.h" + +namespace Titanic { + +class CodeWheel : public CBomb { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + int _field108; + int _state; + int _field110; +public: + CLASSDEF; + CodeWheel(); + + /** + * 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_CODE_WHEEL_H */ diff --git a/engines/titanic/game/computer.cpp b/engines/titanic/game/computer.cpp new file mode 100644 index 0000000000..90574997b1 --- /dev/null +++ b/engines/titanic/game/computer.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 "titanic/game/computer.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CComputer, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CComputer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_currentCD, indent); + file->writeNumberLine(_state, indent); + CBackground::save(file, indent); +} + +void CComputer::load(SimpleFile *file) { + file->readNumber(); + _currentCD = file->readString(); + _state = file->readNumber(); + CBackground::load(file); +} + +bool CComputer::ActMsg(CActMsg *msg) { + if (_state) { + playSound("a#35.wav", 100, 0, 0); + playMovie(32, 42, 0); + + if (msg->_action == "CD1") + playMovie(43, 49, 0); + else if (msg->_action == "CD2") + playMovie(50, 79, 0); + else if (msg->_action == "STCD") + playMovie(80, 90, 4); + + _currentCD = msg->_action; + _state = 0; + } + + return true; +} + +bool CComputer::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_currentCD == "None") { + if (_state) { + playSound("a#35.wav", 100, 0, 0); + playMovie(11, 21, 0); + _state = 0; + } else { + playSound("a#34.wav", 100, 0, 0); + playMovie(0, 10, 0); + _state = 1; + } + } else { + if (_state) { + loadFrame(11); + CActMsg actMsg("EjectCD"); + actMsg.execute(_currentCD); + _currentCD = "None"; + } else { + playSound("a#34.wav", 100, 0, 0); + playMovie(21, 31, 0); + _state = 1; + } + } + + return true; +} + +bool CComputer::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == 90) { + playSound("a#32.wav", 100, 0, 0); + playSound("a#33.wav", 100, 0, 0); + playSound("a#31.wav", 100, 0, 0); + playSound("a#0.wav", 100, 0, 0); + + gotoView("Home.Node 4.E", "_TRACK,3,e-cu,4,E"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/computer.h b/engines/titanic/game/computer.h new file mode 100644 index 0000000000..6acdba27ea --- /dev/null +++ b/engines/titanic/game/computer.h @@ -0,0 +1,55 @@ +/* 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_COMPUTER_H +#define TITANIC_COMPUTER_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CComputer : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +public: + CString _currentCD; + int _state; +public: + CLASSDEF; + CComputer() : CBackground(), _currentCD("None"), _state(0) {} + + /** + * 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_COMPUTER_H */ diff --git a/engines/titanic/game/computer_screen.cpp b/engines/titanic/game/computer_screen.cpp new file mode 100644 index 0000000000..3e5172219d --- /dev/null +++ b/engines/titanic/game/computer_screen.cpp @@ -0,0 +1,140 @@ +/* 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/game/computer_screen.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CComputerScreen, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CComputerScreen::CComputerScreen() : CGameObject() { +} + +void CComputerScreen::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CComputerScreen::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CComputerScreen::ActMsg(CActMsg *msg) { + if (msg->_action == "newCD1" || msg->_action == "newCD2") { + playMovie(27, 53, MOVIE_GAMESTATE); + playMovie(19, 26, MOVIE_GAMESTATE); + } else if (msg->_action == "newSTCD") { + playMovie(0, 18, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT); + } + + return true; +} + +bool CComputerScreen::MovieEndMsg(CMovieEndMsg *msg) { + playSound("z#47.wav", 100, 0, 0); + addTimer(0, 3000, 0); + + for (int idx = 0; idx < 10; ++idx) + playMovie(0, 18, 0); + return true; +} + +bool CComputerScreen::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(26); + return true; +} + +bool CComputerScreen::TimerMsg(CTimerMsg *msg) { + int handle; + + switch (msg->_actionVal) { + case 0: + loadSound("a#32.wav"); + loadSound("a#31.wav"); + loadSound("a#33.wav"); + loadSound("a#30.wav"); + loadSound("a#29.wav"); + playSound("a#25.wav"); + addTimer(1, 2000, 0); + break; + + case 1: + playSound("a#32.wav"); + playSound("a#31.wav"); + addTimer(2, 2000, 0); + break; + + case 2: { + CChangeMusicMsg musicMsg(CString(), 1); + musicMsg.execute("HomeMusicPlayer"); + playSound("a#33.wav"); + playSound("a#31.wav"); + changeView("Home.Node 4.E", ""); + playClip(51, 150); + playSound("a#31.wav"); + playClip(151, 200); + + handle = playSound("a#27.wav"); + playClip(200, 306); + playSound("a#30.wav"); + stopSound(handle, 0); + + playClip(306, 338); + handle = playSound("a#28.wav"); + playClip(338, 392); + playSound("a#29.wav"); + stopSound(handle); + + playSound("y#662.wav"); + setSoundVolume(handle, 10, 2); + playClip(392, 450); + startTalking("Doorbot", 0x3611A); + sleep(8000); + + playClip(450, 492); + startTalking("Doorbot", 0x36121); + playClip(492, 522); + setSoundVolume(handle, 30, 2); + + playClip(523, 540); + setSoundVolume(handle, 0, 1); + + playClip(541, 551); + stopSound(handle); + break; + } + + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/computer_screen.h b/engines/titanic/game/computer_screen.h new file mode 100644 index 0000000000..8fb1dcd4dc --- /dev/null +++ b/engines/titanic/game/computer_screen.h @@ -0,0 +1,53 @@ +/* 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_COMPUTER_SCREEN_H +#define TITANIC_COMPUTER_SCREEN_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CComputerScreen : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool TimerMsg(CTimerMsg *msg); +public: + CLASSDEF; + CComputerScreen(); + + /** + * 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_COMPUTER_SCREEN_H */ diff --git a/engines/titanic/game/cookie.cpp b/engines/titanic/game/cookie.cpp new file mode 100644 index 0000000000..96edca4058 --- /dev/null +++ b/engines/titanic/game/cookie.cpp @@ -0,0 +1,60 @@ +/* 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/game/cookie.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCookie, CGameObject) + ON_MESSAGE(LeaveNodeMsg) + ON_MESSAGE(FreshenCookieMsg) +END_MESSAGE_MAP() + +void CCookie::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CCookie::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _value2 = file->readNumber(); + + CGameObject::load(file); +} + +bool CCookie::LeaveNodeMsg(CLeaveNodeMsg *msg) { + if (_value2) + _value1 = 1; + return true; +} + +bool CCookie::FreshenCookieMsg(CFreshenCookieMsg *msg) { + _value1 = msg->_value2; + _value2 = msg->_value1; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/cookie.h b/engines/titanic/game/cookie.h new file mode 100644 index 0000000000..2018deeb3e --- /dev/null +++ b/engines/titanic/game/cookie.h @@ -0,0 +1,54 @@ +/* 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_COOKIE_H +#define TITANIC_COOKIE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CCookie : public CGameObject { + DECLARE_MESSAGE_MAP; + bool LeaveNodeMsg(CLeaveNodeMsg *msg); + bool FreshenCookieMsg(CFreshenCookieMsg *msg); +public: + int _value1; + int _value2; +public: + CLASSDEF; + CCookie() : CGameObject(), _value1(0), _value2(0) {} + + /** + * 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_COOKIE_H */ diff --git a/engines/titanic/game/credits.cpp b/engines/titanic/game/credits.cpp new file mode 100644 index 0000000000..d9149f6dd2 --- /dev/null +++ b/engines/titanic/game/credits.cpp @@ -0,0 +1,81 @@ +/* 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/game/credits.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCredits, CGameObject) + ON_MESSAGE(SignalObject) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CCredits::CCredits() : CGameObject(), _fieldBC(-1), _fieldC0(1) { +} + +void CCredits::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + + CGameObject::save(file, indent); +} + +void CCredits::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + + CGameObject::load(file); +} + +bool CCredits::SignalObject(CSignalObject *msg) { + petHide(); + disableMouse(); + addTimer(50); + return true; +} + +bool CCredits::TimerMsg(CTimerMsg *msg) { + stopGlobalSound(true, -1); + setVisible(true); + loadSound("a#16.wav"); + loadSound("a#24.wav"); + + playCutscene(0, 18); + playGlobalSound("a#16.wav", -1, false, false, 0); + playCutscene(19, 642); + playSound("a#24.wav"); + playCutscene(643, 750); + + COpeningCreditsMsg creditsMsg; + creditsMsg.execute("Service Elevator Entity"); + changeView("EmbLobby.Node 6.S"); + + setVisible(false); + petShow(); + enableMouse(); + stopGlobalSound(true, -1); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/credits.h b/engines/titanic/game/credits.h new file mode 100644 index 0000000000..23fd25584d --- /dev/null +++ b/engines/titanic/game/credits.h @@ -0,0 +1,53 @@ +/* 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_CREDITS_H +#define TITANIC_CREDITS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CCredits : public CGameObject { + DECLARE_MESSAGE_MAP; + bool SignalObject(CSignalObject *msg); + bool TimerMsg(CTimerMsg *msg); +public: + int _fieldBC, _fieldC0; +public: + CLASSDEF; + CCredits(); + + /** + * 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_CREDITS_H */ diff --git a/engines/titanic/game/credits_button.cpp b/engines/titanic/game/credits_button.cpp new file mode 100644 index 0000000000..ee8f7bb329 --- /dev/null +++ b/engines/titanic/game/credits_button.cpp @@ -0,0 +1,62 @@ +/* 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/game/credits_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCreditsButton, CBackground) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CCreditsButton::CCreditsButton() : CBackground(), _fieldE0(1) { +} + +void CCreditsButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + CBackground::save(file, indent); +} + +void CCreditsButton::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + CBackground::load(file); +} + +bool CCreditsButton::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return true; +} + +bool CCreditsButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_fieldE0) { + playSound("a#20.wav"); + CSignalObject signalMsg; + signalMsg._numValue = 1; + signalMsg.execute("CreditsPlayer"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/credits_button.h b/engines/titanic/game/credits_button.h new file mode 100644 index 0000000000..4a53083195 --- /dev/null +++ b/engines/titanic/game/credits_button.h @@ -0,0 +1,53 @@ +/* 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_CREDITS_BUTTON_H +#define TITANIC_CREDITS_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CCreditsButton : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + int _fieldE0; +public: + CLASSDEF; + CCreditsButton(); + + /** + * 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_CREDITS_BUTTON_H */ diff --git a/engines/titanic/game/dead_area.cpp b/engines/titanic/game/dead_area.cpp new file mode 100644 index 0000000000..3c41ab34ba --- /dev/null +++ b/engines/titanic/game/dead_area.cpp @@ -0,0 +1,45 @@ +/* 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/game/dead_area.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDeadArea, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +CDeadArea::CDeadArea() : CGameObject() { +} + +void CDeadArea::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CDeadArea::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/dead_area.h b/engines/titanic/game/dead_area.h new file mode 100644 index 0000000000..fdb44ef5df --- /dev/null +++ b/engines/titanic/game/dead_area.h @@ -0,0 +1,55 @@ +/* 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_DEAD_AREA_H +#define TITANIC_DEAD_AREA_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +/** + * Implements a non-responsive screen area + */ +class CDeadArea : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg) { return true; } + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg) { return true; } +public: + CLASSDEF; + CDeadArea(); + + /** + * 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_DEAD_AREA_H */ diff --git a/engines/titanic/game/desk_click_responder.cpp b/engines/titanic/game/desk_click_responder.cpp new file mode 100644 index 0000000000..0650b3a1f5 --- /dev/null +++ b/engines/titanic/game/desk_click_responder.cpp @@ -0,0 +1,67 @@ +/* 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/game/desk_click_responder.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDeskClickResponder, CClickResponder) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +void CDeskClickResponder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldD4, indent); + file->writeNumberLine(_ticks, indent); + + CClickResponder::save(file, indent); +} + +void CDeskClickResponder::load(SimpleFile *file) { + file->readNumber(); + _fieldD4 = file->readNumber(); + _ticks = file->readNumber(); + + CClickResponder::load(file); +} + +bool CDeskClickResponder::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + _fieldD4 = (_fieldD4 + 1) % 3; + if (_fieldD4) + return CClickResponder::MouseButtonDownMsg(msg); + + uint ticks = getTicksCount(); + if (!_ticks || ticks > (_ticks + 4000)) { + playSound("a#22.wav"); + _ticks = ticks; + } + + return true; +} + +bool CDeskClickResponder::LoadSuccessMsg(CLoadSuccessMsg *msg) { + _ticks = 0; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/desk_click_responder.h b/engines/titanic/game/desk_click_responder.h new file mode 100644 index 0000000000..13cf7f4b87 --- /dev/null +++ b/engines/titanic/game/desk_click_responder.h @@ -0,0 +1,53 @@ +/* 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_DESK_CLICK_RESPONDER_H +#define TITANIC_DESK_CLICK_RESPONDER_H + +#include "titanic/core/click_responder.h" + +namespace Titanic { + +class CDeskClickResponder : public CClickResponder { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +protected: + int _fieldD4; + uint _ticks; +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_DESK_CLICK_RESPONDER_H */ diff --git a/engines/titanic/game/doorbot_elevator_handler.cpp b/engines/titanic/game/doorbot_elevator_handler.cpp new file mode 100644 index 0000000000..39978e9ed7 --- /dev/null +++ b/engines/titanic/game/doorbot_elevator_handler.cpp @@ -0,0 +1,56 @@ +/* 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/game/doorbot_elevator_handler.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDoorbotElevatorHandler, CGameObject) + ON_MESSAGE(EnterNodeMsg) +END_MESSAGE_MAP() + +void CDoorbotElevatorHandler::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + file->writeNumberLine(_called, indent); + CGameObject::save(file, indent); +} + +void CDoorbotElevatorHandler::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + _called = file->readNumber(); + CGameObject::load(file); +} + +bool CDoorbotElevatorHandler::EnterNodeMsg(CEnterNodeMsg *msg) { + if (!_called) { + CDoorbotNeededInElevatorMsg elevatorMsg; + elevatorMsg._value = 0; + elevatorMsg.execute("Doorbot"); + _called = true; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/doorbot_elevator_handler.h b/engines/titanic/game/doorbot_elevator_handler.h new file mode 100644 index 0000000000..f846273f14 --- /dev/null +++ b/engines/titanic/game/doorbot_elevator_handler.h @@ -0,0 +1,53 @@ +/* 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_DOORBOT_ELEVATOR_HANDLER_H +#define TITANIC_DOORBOT_ELEVATOR_HANDLER_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CDoorbotElevatorHandler : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterNodeMsg(CEnterNodeMsg *msg); +private: + bool _called; + int _value; +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_DOORBOT_ELEVATOR_HANDLER_H */ diff --git a/engines/titanic/game/doorbot_home_handler.cpp b/engines/titanic/game/doorbot_home_handler.cpp new file mode 100644 index 0000000000..92898ca626 --- /dev/null +++ b/engines/titanic/game/doorbot_home_handler.cpp @@ -0,0 +1,50 @@ +/* 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/game/doorbot_home_handler.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDoorbotHomeHandler, CGameObject) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CDoorbotHomeHandler::CDoorbotHomeHandler() { +} + +void CDoorbotHomeHandler::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CDoorbotHomeHandler::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CDoorbotHomeHandler::EnterViewMsg(CEnterViewMsg *msg) { + CDoorbotNeededInHomeMsg neededMsg; + neededMsg.execute("Doorbot"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/doorbot_home_handler.h b/engines/titanic/game/doorbot_home_handler.h new file mode 100644 index 0000000000..10552f2b87 --- /dev/null +++ b/engines/titanic/game/doorbot_home_handler.h @@ -0,0 +1,50 @@ +/* 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_DOORBOT_HOME_HANDLER_H +#define TITANIC_DOORBOT_HOME_HANDLER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CDoorbotHomeHandler : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); +public: + CLASSDEF; + CDoorbotHomeHandler(); + + /** + * 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_DOORBOT_HOME_HANDLER_H */ diff --git a/engines/titanic/game/ear_sweet_bowl.cpp b/engines/titanic/game/ear_sweet_bowl.cpp new file mode 100644 index 0000000000..646b95f0b4 --- /dev/null +++ b/engines/titanic/game/ear_sweet_bowl.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/game/ear_sweet_bowl.h" +#include "titanic/core/room_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEarSweetBowl, CSweetBowl) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(ReplaceBowlAndNutsMsg) +END_MESSAGE_MAP() + +void CEarSweetBowl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSweetBowl::save(file, indent); +} + +void CEarSweetBowl::load(SimpleFile *file) { + file->readNumber(); + CSweetBowl::load(file); +} + +bool CEarSweetBowl::MovieEndMsg(CMovieEndMsg *msg) { + CIsEarBowlPuzzleDone doneMsg; + doneMsg.execute(findRoom()); + + if (!doneMsg._value) { + CPetControl *pet = getPetControl(); + if (pet) + pet->hasRoomFlags(); + + CIsParrotPresentMsg parrotMsg; + parrotMsg.execute(findRoom()); + + if (parrotMsg._value) { + CNutPuzzleMsg nutMsg("Jiggle"); + nutMsg.execute("NutsParrotPlayer"); + } + } + + return true; +} + +bool CEarSweetBowl::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/ear_sweet_bowl.h b/engines/titanic/game/ear_sweet_bowl.h new file mode 100644 index 0000000000..1324ed224a --- /dev/null +++ b/engines/titanic/game/ear_sweet_bowl.h @@ -0,0 +1,50 @@ +/* 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_EAR_SWEET_BOWL_H +#define TITANIC_EAR_SWEET_BOWL_H + +#include "titanic/game/sweet_bowl.h" + +namespace Titanic { + +class CEarSweetBowl : public CSweetBowl { + DECLARE_MESSAGE_MAP; + bool MovieEndMsg(CMovieEndMsg *msg); + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *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_EAR_SWEET_BOWL_H */ diff --git a/engines/titanic/game/eject_phonograph_button.cpp b/engines/titanic/game/eject_phonograph_button.cpp new file mode 100644 index 0000000000..b2ff441ef8 --- /dev/null +++ b/engines/titanic/game/eject_phonograph_button.cpp @@ -0,0 +1,80 @@ +/* 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/game/eject_phonograph_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEjectPhonographButton, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(CylinderHolderReadyMsg) +END_MESSAGE_MAP() + +void CEjectPhonographButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_ejected, indent); + file->writeNumberLine(_readyFlag, indent); + file->writeQuotedLine(_soundName, indent); + file->writeQuotedLine(_readySoundName, indent); + + CBackground::save(file, indent); +} + +void CEjectPhonographButton::load(SimpleFile *file) { + file->readNumber(); + _ejected = file->readNumber(); + _readyFlag = file->readNumber(); + _soundName = file->readString(); + _readySoundName = file->readString(); + + CBackground::load(file); +} + +bool CEjectPhonographButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CQueryPhonographState queryMsg; + queryMsg.execute(getParent(), nullptr, MSGFLAG_SCAN); + + if (!_ejected && !queryMsg._value) { + loadFrame(1); + playSound(_soundName); + _readyFlag = true; + + CEjectCylinderMsg ejectMsg; + ejectMsg.execute(getParent(), nullptr, MSGFLAG_SCAN); + _ejected = true; + } + + return true; +} + +bool CEjectPhonographButton::CylinderHolderReadyMsg(CCylinderHolderReadyMsg *msg) { + if (_readyFlag) { + loadFrame(0); + playSound(_readySoundName); + _readyFlag = 0; + } + + _ejected = false; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/eject_phonograph_button.h b/engines/titanic/game/eject_phonograph_button.h new file mode 100644 index 0000000000..df8e602468 --- /dev/null +++ b/engines/titanic/game/eject_phonograph_button.h @@ -0,0 +1,56 @@ +/* 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_EJECT_PHONOGRAPH_BUTTON_H +#define TITANIC_EJECT_PHONOGRAPH_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CEjectPhonographButton : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool CylinderHolderReadyMsg(CCylinderHolderReadyMsg *msg); +public: + bool _ejected; + bool _readyFlag; + CString _soundName; + CString _readySoundName; +public: + CLASSDEF; + CEjectPhonographButton() : CBackground(), _ejected(false), _readyFlag(false) {} + + /** + * 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_EJECT_PHONOGRAPH_BUTTON_H */ diff --git a/engines/titanic/game/elevator_action_area.cpp b/engines/titanic/game/elevator_action_area.cpp new file mode 100644 index 0000000000..d59c9b9e7a --- /dev/null +++ b/engines/titanic/game/elevator_action_area.cpp @@ -0,0 +1,50 @@ +/* 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/game/elevator_action_area.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CElevatorActionArea, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CElevatorActionArea::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CElevatorActionArea::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +bool CElevatorActionArea::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CServiceElevatorMsg elevMsg(_value); + elevMsg.execute(findRoom()->findByName("Service Elevator Entity")); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/elevator_action_area.h b/engines/titanic/game/elevator_action_area.h new file mode 100644 index 0000000000..75d3a06d29 --- /dev/null +++ b/engines/titanic/game/elevator_action_area.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_ELEVATOR_ACTION_AREA_H +#define TITANIC_ELEVATOR_ACTION_AREA_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CElevatorActionArea : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + int _value; +public: + CLASSDEF; + CElevatorActionArea() : CGameObject(), _value(4) {} + + /** + * 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_ELEVATOR_ACTION_AREA_H */ diff --git a/engines/titanic/game/emma_control.cpp b/engines/titanic/game/emma_control.cpp new file mode 100644 index 0000000000..e3ba7cc42c --- /dev/null +++ b/engines/titanic/game/emma_control.cpp @@ -0,0 +1,66 @@ +/* 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/game/emma_control.h" +#include "titanic/core/room_item.h" +#include "titanic/sound/auto_music_player.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEmmaControl, CBackground) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +void CEmmaControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + file->writeQuotedLine(_hiddenSoundName, indent); + file->writeQuotedLine(_visibleSoundName, indent); + + CBackground::save(file, indent); +} + +void CEmmaControl::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + _hiddenSoundName = file->readString(); + _visibleSoundName = file->readString(); + + CBackground::load(file); +} + +bool CEmmaControl::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(_flag); + return true; +} + +bool CEmmaControl::StatusChangeMsg(CStatusChangeMsg *msg) { + _flag = !_flag; + setVisible(_flag); + CChangeMusicMsg changeMsg(_flag ? _visibleSoundName : _hiddenSoundName, 0); + changeMsg.execute(findRoom(), CAutoMusicPlayer::_type, + MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_CLASS_DEF); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/emma_control.h b/engines/titanic/game/emma_control.h new file mode 100644 index 0000000000..e4032ca1a5 --- /dev/null +++ b/engines/titanic/game/emma_control.h @@ -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. + * + */ + +#ifndef TITANIC_EMMA_CONTROL_H +#define TITANIC_EMMA_CONTROL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CEmmaControl : public CBackground { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +private: + bool _flag; + + CString _hiddenSoundName; + CString _visibleSoundName; +public: + CLASSDEF; + CEmmaControl() : CBackground(), _flag(false), + _hiddenSoundName("b#39.wav"), _visibleSoundName("b#38.wav") {} + + /** + * 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_EMMA_CONTROL_H */ diff --git a/engines/titanic/game/empty_nut_bowl.cpp b/engines/titanic/game/empty_nut_bowl.cpp new file mode 100644 index 0000000000..adee2589f6 --- /dev/null +++ b/engines/titanic/game/empty_nut_bowl.cpp @@ -0,0 +1,78 @@ +/* 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/game/empty_nut_bowl.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEmptyNutBowl, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ReplaceBowlAndNutsMsg) + ON_MESSAGE(NutPuzzleMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CEmptyNutBowl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CGameObject::save(file, indent); +} + +void CEmptyNutBowl::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CGameObject::load(file); +} + +bool CEmptyNutBowl::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_flag) { + CNutPuzzleMsg nutMsg("UnlockBowl"); + nutMsg.execute(getRoom(), nullptr, MSGFLAG_SCAN); + _flag = false; + } + + return true; +} + +bool CEmptyNutBowl::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + setVisible(false); + _flag = true; + return true; +} + +bool CEmptyNutBowl::NutPuzzleMsg(CNutPuzzleMsg *msg) { + if (msg->_value == "NutsGone") + setVisible(true); + return true; +} + +bool CEmptyNutBowl::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!_flag) { + msg->execute("Ear1"); + setVisible(false); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/empty_nut_bowl.h b/engines/titanic/game/empty_nut_bowl.h new file mode 100644 index 0000000000..d67e75b0aa --- /dev/null +++ b/engines/titanic/game/empty_nut_bowl.h @@ -0,0 +1,55 @@ +/* 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_EMPTY_NUT_BOWL_H +#define TITANIC_EMPTY_NUT_BOWL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CEmptyNutBowl : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg); + bool NutPuzzleMsg(CNutPuzzleMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +public: + bool _flag; +public: + CLASSDEF; + CEmptyNutBowl() : CGameObject(), _flag(true) {} + + /** + * 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_EMPTY_NUT_BOWL_H */ diff --git a/engines/titanic/game/end_credit_text.cpp b/engines/titanic/game/end_credit_text.cpp new file mode 100644 index 0000000000..4eee13d3fb --- /dev/null +++ b/engines/titanic/game/end_credit_text.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/game/end_credit_text.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEndCreditText, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +void CEndCreditText::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CGameObject::save(file, indent); +} + +void CEndCreditText::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CGameObject::load(file); +} + +bool CEndCreditText::ActMsg(CActMsg *msg) { + playGlobalSound("z#41.wav", -1, false, false, 0); + createCredits(); + _flag = true; + return true; +} + +bool CEndCreditText::FrameMsg(CFrameMsg *msg) { + if (_flag) { + if (_credits) { + makeDirty(); + } else { + addTimer(5000); + _flag = false; + } + } + + return true; +} + +bool CEndCreditText::TimerMsg(CTimerMsg *msg) { + setGlobalSoundVolume(-4, 2, -1); + sleep(1000); + quitGame(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/end_credit_text.h b/engines/titanic/game/end_credit_text.h new file mode 100644 index 0000000000..a0e0078837 --- /dev/null +++ b/engines/titanic/game/end_credit_text.h @@ -0,0 +1,54 @@ +/* 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_END_CREDIT_TEXT_H +#define TITANIC_END_CREDIT_TEXT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEndCreditText : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool TimerMsg(CTimerMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CEndCreditText() : CGameObject(), _flag(false) {} + + /** + * 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_END_CREDIT_TEXT_H */ diff --git a/engines/titanic/game/end_credits.cpp b/engines/titanic/game/end_credits.cpp new file mode 100644 index 0000000000..f613e5a008 --- /dev/null +++ b/engines/titanic/game/end_credits.cpp @@ -0,0 +1,64 @@ +/* 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/game/end_credits.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEndCredits, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +void CEndCredits::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CGameObject::save(file, indent); +} + +void CEndCredits::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CGameObject::load(file); +} + +bool CEndCredits::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_flag) { + deinit(); + stopGlobalSound(true, -1); + _flag = false; + } else { + loadSound("z#41.wav"); + playGlobalSound("z#41.wav", -1, false, false, 0); + _flag = true; + } + + return true; +} + +bool CEndCredits::FrameMsg(CFrameMsg *msg) { + if (_flag) + makeDirty(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/end_credits.h b/engines/titanic/game/end_credits.h new file mode 100644 index 0000000000..257c5b64a7 --- /dev/null +++ b/engines/titanic/game/end_credits.h @@ -0,0 +1,53 @@ +/* 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_END_CREDITS_H +#define TITANIC_END_CREDITS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEndCredits : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool FrameMsg(CFrameMsg *msg); +public: + bool _flag; +public: + CLASSDEF; + CEndCredits() : CGameObject(), _flag(false) {} + + /** + * 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_END_CREDITS_H */ diff --git a/engines/titanic/game/end_explode_ship.cpp b/engines/titanic/game/end_explode_ship.cpp new file mode 100644 index 0000000000..10c80f5863 --- /dev/null +++ b/engines/titanic/game/end_explode_ship.cpp @@ -0,0 +1,107 @@ +/* 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/game/end_explode_ship.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEndExplodeShip, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MovieFrameMsg) +END_MESSAGE_MAP() + +void CEndExplodeShip::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CEndExplodeShip::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _value2 = file->readNumber(); + + CGameObject::load(file); +} + +bool CEndExplodeShip::ActMsg(CActMsg *msg) { + if (msg->_action == "Arm Bomb") { + _value1 = 1; + } else if (msg->_action == "Disarm Bomb") { + _value1 = 0; + } else if (msg->_action == "TakeOff") { + loadSound("a#31.wav"); + loadSound("a#14.wav"); + playGlobalSound("a#13.wav", -1, true, true, 0); + addTimer(1, 10212, 0); + } + + return true; +} + +bool CEndExplodeShip::TimerMsg(CTimerMsg *msg) { + if (msg->_actionVal == 1) { + setVisible(true); + playMovie(0, 449, 0); + movieEvent(58); + playMovie(516, _value1 ? 550 : 551, MOVIE_NOTIFY_OBJECT); + } + + if (msg->_actionVal == 3) { + setGlobalSoundVolume(-4, 2, -1); + CActMsg actMsg(_value1 ? "ExplodeCredits" : "Credits"); + actMsg.execute("EndGameCredits"); + } + + if (msg->_action == "Room") { + playMovie(550, 583, MOVIE_NOTIFY_OBJECT); + movieEvent(551); + } + + return true; +} + +bool CEndExplodeShip::MovieEndMsg(CMovieEndMsg *msg) { + if (getMovieFrame() == 550) { + playSound("z#399.wav"); + startAnimTimer("Boom", 4200, 0); + } else { + addTimer(3, 8000, 0); + } + + return true; +} + +bool CEndExplodeShip::MovieFrameMsg(CMovieFrameMsg *msg) { + if (getMovieFrame() == 58) + playSound("a#31.wav", 70); + else if (getMovieFrame() == 551) + playSound("a#14.wav"); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/end_explode_ship.h b/engines/titanic/game/end_explode_ship.h new file mode 100644 index 0000000000..c48f822af8 --- /dev/null +++ b/engines/titanic/game/end_explode_ship.h @@ -0,0 +1,55 @@ +/* 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_END_EXPLODE_SHIP_H +#define TITANIC_END_EXPLODE_SHIP_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEndExplodeShip : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); +public: + int _value1, _value2; +public: + CLASSDEF; + CEndExplodeShip() : CGameObject(), _value1(0), _value2(0) {} + + /** + * 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_END_EXPLODE_SHIP_H */ diff --git a/engines/titanic/game/end_game_credits.cpp b/engines/titanic/game/end_game_credits.cpp new file mode 100644 index 0000000000..4edcef0a17 --- /dev/null +++ b/engines/titanic/game/end_game_credits.cpp @@ -0,0 +1,87 @@ +/* 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/game/end_game_credits.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEndGameCredits, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CEndGameCredits::CEndGameCredits() : CGameObject(), _flag(0), + _frameRange(0, 28) { +} + +void CEndGameCredits::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + file->writePoint(_frameRange, indent); + + CGameObject::save(file, indent); +} + +void CEndGameCredits::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + _frameRange = file->readPoint(); + + CGameObject::load(file); +} + +bool CEndGameCredits::ActMsg(CActMsg *msg) { + if (!_flag) { + if (msg->_action == "ExplodeCredits") + _frameRange = Point(0, 27); + if (msg->_action == "Credits") + _frameRange = Point(28, 46); + + changeView("TheEnd.Node 4.N"); + } + + return true; +} + +bool CEndGameCredits::EnterViewMsg(CEnterViewMsg *msg) { + playMovie(_frameRange.x, _frameRange.y, MOVIE_NOTIFY_OBJECT); + return true; +} + +bool CEndGameCredits::MovieEndMsg(CMovieEndMsg *msg) { + if (getMovieFrame() == 46) { + CVisibleMsg visibleMsg; + visibleMsg.execute("CreditsBackdrop"); + } + + return true; +} + +bool CEndGameCredits::TimerMsg(CTimerMsg *msg) { + CActMsg actMsg; + actMsg.execute("EndCreditsText"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/end_game_credits.h b/engines/titanic/game/end_game_credits.h new file mode 100644 index 0000000000..13a92423f6 --- /dev/null +++ b/engines/titanic/game/end_game_credits.h @@ -0,0 +1,56 @@ +/* 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_END_GAME_CREDITS_H +#define TITANIC_END_GAME_CREDITS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEndGameCredits : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool TimerMsg(CTimerMsg *msg); +private: + bool _flag; + Point _frameRange; +public: + CLASSDEF; + CEndGameCredits(); + + /** + * 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_END_GAME_CREDITS_H */ diff --git a/engines/titanic/game/end_sequence_control.cpp b/engines/titanic/game/end_sequence_control.cpp new file mode 100644 index 0000000000..033a7752a3 --- /dev/null +++ b/engines/titanic/game/end_sequence_control.cpp @@ -0,0 +1,84 @@ +/* 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/game/end_sequence_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEndSequenceControl, CGameObject) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CEndSequenceControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CEndSequenceControl::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CEndSequenceControl::TimerMsg(CTimerMsg *msg) { + switch (msg->_actionVal) { + case 1: + changeView("TheEnd.Node 2.N"); + break; + case 2: { + playSound("ShipFlyingMusic.wav"); + CActMsg actMsg("TakeOff"); + actMsg.execute("EndExplodeShip"); + break; + } + + default: + break; + } + + return true; +} + +bool CEndSequenceControl::MovieEndMsg(CMovieEndMsg *msg) { + setGlobalSoundVolume(-4, 2, -1); + changeView("TheEnd.Node 3.N"); + addTimer(2, 1000, 0); + return true; +} + +bool CEndSequenceControl::EnterRoomMsg(CEnterRoomMsg *msg) { + petHide(); + disableMouse(); + addTimer(1, 1000, 0); + playGlobalSound("a#15.wav", -1, true, true, 0); + return true; +} + +bool CEndSequenceControl::EnterViewMsg(CEnterViewMsg *msg) { + movieSetAudioTiming(true); + playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/end_sequence_control.h b/engines/titanic/game/end_sequence_control.h new file mode 100644 index 0000000000..223f25186d --- /dev/null +++ b/engines/titanic/game/end_sequence_control.h @@ -0,0 +1,53 @@ +/* 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_END_SEQUENCE_CONTROL_H +#define TITANIC_END_SEQUENCE_CONTROL_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CEndSequenceControl : public CGameObject { + DECLARE_MESSAGE_MAP; + bool TimerMsg(CTimerMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool EnterViewMsg(CEnterViewMsg *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_END_SEQUENCE_CONTROL_H */ diff --git a/engines/titanic/game/fan.cpp b/engines/titanic/game/fan.cpp new file mode 100644 index 0000000000..3fdebbd3ef --- /dev/null +++ b/engines/titanic/game/fan.cpp @@ -0,0 +1,126 @@ +/* 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/game/fan.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFan, CGameObject) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CFan::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_state, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CFan::load(SimpleFile *file) { + file->readNumber(); + _state = file->readNumber(); + _value2 = file->readNumber(); + + CGameObject::load(file); +} + +bool CFan::EnterViewMsg(CEnterViewMsg *msg) { + switch (_state) { + case 0: + case 1: + loadFrame(0); + break; + case 2: + playMovie(24, 34, MOVIE_REPEAT); + break; + case 3: + playMovie(63, 65, MOVIE_REPEAT); + break; + } + + return true; +} + +bool CFan::StatusChangeMsg(CStatusChangeMsg *msg) { + if (msg->_newStatus >= -1 && msg->_newStatus < 3) { + int oldState = _state; + _state = msg->_newStatus; + switch (_state) { + case -1: + case 0: + if (oldState == 0) + loadFrame(0); + else if (oldState == 1) + playMovie(24, 34, MOVIE_STOP_PREVIOUS | MOVIE_NOTIFY_OBJECT); + else if (oldState == 2) { + playMovie(66, 79, MOVIE_STOP_PREVIOUS); + playMovie(24, 34, MOVIE_NOTIFY_OBJECT); + } + break; + + case 1: + if (oldState == 0) + playMovie(24, 34, MOVIE_REPEAT | MOVIE_STOP_PREVIOUS); + if (oldState == 2) + playMovie(66, 79, MOVIE_NOTIFY_OBJECT | MOVIE_STOP_PREVIOUS); + break; + + case 2: + if (oldState == 1) + playMovie(48, 62, MOVIE_NOTIFY_OBJECT | MOVIE_STOP_PREVIOUS); + break; + + default: + break; + } + } + + msg->execute("PromDeckFanNoises"); + return true; +} + +bool CFan::MovieEndMsg(CMovieEndMsg *msg) { + switch (_state) { + case -1: + case 0: + loadFrame(0); + break; + + case 1: + playMovie(24, 34, MOVIE_REPEAT); + break; + + case 2: + playMovie(63, 65, MOVIE_REPEAT); + break; + + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/fan.h b/engines/titanic/game/fan.h new file mode 100644 index 0000000000..9cffce8b68 --- /dev/null +++ b/engines/titanic/game/fan.h @@ -0,0 +1,54 @@ +/* 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_FAN_H +#define TITANIC_FAN_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CFan : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +public: + int _state, _value2; +public: + CLASSDEF; + CFan() : CGameObject(), _state(0), _value2(0) {} + + /** + * 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_FAN_H */ diff --git a/engines/titanic/game/fan_control.cpp b/engines/titanic/game/fan_control.cpp new file mode 100644 index 0000000000..56a1e49dec --- /dev/null +++ b/engines/titanic/game/fan_control.cpp @@ -0,0 +1,182 @@ +/* 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/game/fan_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFanControl, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CFanControl::CFanControl() : CGameObject(), _state(-1), + _enabled(false), _fieldC4(0), _fieldC8(false), _fieldCC(0) { +} + +void CFanControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_state, indent); + file->writeNumberLine(_enabled, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_fieldCC, indent); + + CGameObject::save(file, indent); +} + +void CFanControl::load(SimpleFile *file) { + file->readNumber(); + _state = file->readNumber(); + _enabled = file->readNumber(); + _fieldC4 = file->readNumber(); + _fieldC8 = file->readNumber(); + _fieldCC = file->readNumber(); + + CGameObject::load(file); +} + +bool CFanControl::ActMsg(CActMsg *msg) { + if (msg->_action == "EnableObject") + _enabled = true; + else if (msg->_action == "DisableObject") + _enabled = false; + else if (msg->_action == "StarlingsDead") { + _fieldC4 = 0; + dec54(); + _fieldCC = 0; + } + + return true; +} + +bool CFanControl::StatusChangeMsg(CStatusChangeMsg *msg) { + if (!_fieldCC) { + playSound("z#42.wav"); + if (_enabled) { + switch (msg->_newStatus) { + case 1: + _fieldC8 = !_fieldC8; + if (_fieldC8) { + playMovie(6, 8, 0); + _state = 0; + } else { + switch (_state) { + case 0: + playMovie(4, 6, 0); + _state = -1; + break; + case 1: + playMovie(0, 6, 0); + break; + case 2: + playMovie(18, 24, 0); + playMovie(0, 6, 0); + break; + default: + break; + } + + _state = -1; + } + break; + + case 2: + if (_fieldC8) { + _state = (_state + 1) % 4; + switch (_state) { + case 0: + playMovie(18, 24, 0); + playMovie(0, 4, 0); + break; + case 1: + playMovie(8, 12, 0); + break; + case 2: + if (_fieldC4) { + inc54(); + _fieldCC = 1; + playMovie(12, 18, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else { + playMovie(12, 18, 0); + } + break; + default: + break; + } + } + break; + + default: + break; + } + + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _state; + statusMsg.execute("RightFan"); + } else { + petDisplayMessage(1, "Unfortunately this fan controller has blown a fuse."); + } + } + + return true; +} + +bool CFanControl::EnterViewMsg(CEnterViewMsg *msg) { + switch (_state) { + case 0: + loadFrame(6); + break; + case 1: + loadFrame(4); + break; + case 2: + loadFrame(0); + break; + case 3: + loadFrame(18); + break; + default: + break; + } + + return true; +} + +bool CFanControl::MovieEndMsg(CMovieEndMsg *msg) { + addTimer(2000); + return true; +} + +bool CFanControl::TimerMsg(CTimerMsg *msg) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("StarlingPuret"); + changeView("PromenadeDeck.Node 3.S"); + changeView("PromenadeDeck.Node 3.E"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/fan_control.h b/engines/titanic/game/fan_control.h new file mode 100644 index 0000000000..1f7402db12 --- /dev/null +++ b/engines/titanic/game/fan_control.h @@ -0,0 +1,60 @@ +/* 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_FAN_CONTROL_H +#define TITANIC_FAN_CONTROL_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CFanControl : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool TimerMsg(CTimerMsg *msg); +public: + int _state; + bool _enabled; + int _fieldC4; + bool _fieldC8; + int _fieldCC; +public: + CLASSDEF; + CFanControl(); + + /** + * 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_FAN_CONTROL_H */ diff --git a/engines/titanic/game/fan_decrease.cpp b/engines/titanic/game/fan_decrease.cpp new file mode 100644 index 0000000000..b0b9cc585f --- /dev/null +++ b/engines/titanic/game/fan_decrease.cpp @@ -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. + * + */ + +#include "titanic/game/fan_decrease.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFanDecrease, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CFanDecrease::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CFanDecrease::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CFanDecrease::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 2; + statusMsg.execute("FanController"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/fan_decrease.h b/engines/titanic/game/fan_decrease.h new file mode 100644 index 0000000000..2e90d09a3f --- /dev/null +++ b/engines/titanic/game/fan_decrease.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_FAN_DECREASE_H +#define TITANIC_FAN_DECREASE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CFanDecrease : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *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_FAN_DECREASE_H */ diff --git a/engines/titanic/game/fan_increase.cpp b/engines/titanic/game/fan_increase.cpp new file mode 100644 index 0000000000..abd2e019d3 --- /dev/null +++ b/engines/titanic/game/fan_increase.cpp @@ -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. + * + */ + +#include "titanic/game/fan_increase.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFanIncrease, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CFanIncrease::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CFanIncrease::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CFanIncrease::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("FanController"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/fan_increase.h b/engines/titanic/game/fan_increase.h new file mode 100644 index 0000000000..7ed74e1847 --- /dev/null +++ b/engines/titanic/game/fan_increase.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_FAN_INCREASE_H +#define TITANIC_FAN_INCREASE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CFanIncrease : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *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_FAN_INCREASE_H */ diff --git a/engines/titanic/game/fan_noises.cpp b/engines/titanic/game/fan_noises.cpp new file mode 100644 index 0000000000..c6e6d203dd --- /dev/null +++ b/engines/titanic/game/fan_noises.cpp @@ -0,0 +1,206 @@ +/* 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/game/fan_noises.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFanNoises, CGameObject) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(SetVolumeMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +CFanNoises::CFanNoises() : CGameObject(), _state(-1), + _soundHandle(0), _soundPercent(70), _soundV3(-1), _soundSeconds(0), + _stopSeconds(0), _startFlag(true) { +} + +void CFanNoises::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_state, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_soundPercent, indent); + file->writeNumberLine(_soundV3, indent); + file->writeNumberLine(_soundSeconds, indent); + file->writeNumberLine(_stopSeconds, indent); + file->writeNumberLine(_startFlag, indent); + + CGameObject::save(file, indent); +} + +void CFanNoises::load(SimpleFile *file) { + file->readNumber(); + _state = file->readNumber(); + _soundHandle = file->readNumber(); + _soundPercent = file->readNumber(); + _soundV3 = file->readNumber(); + _soundSeconds = file->readNumber(); + _stopSeconds = file->readNumber(); + _startFlag = file->readNumber(); + + CGameObject::load(file); +} + +bool CFanNoises::EnterRoomMsg(CEnterRoomMsg *msg) { + if (getParent() == msg->_newRoom) { + if (_soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, _stopSeconds); + _soundHandle = -1; + _startFlag = false; + } + + switch (_state) { + case 1: + _soundHandle = playSound("b#60.wav", 0, _soundV3, true); + setSoundVolume(_soundHandle, _soundPercent, _soundSeconds); + _startFlag = true; + break; + case 2: + _soundHandle = playSound("b#58.wav", 0, _soundV3, true); + setSoundVolume(_soundHandle, _soundPercent, _soundSeconds); + _startFlag = true; + break; + default: + break; + } + } + + return true; +} + +bool CFanNoises::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (getParent() == msg->_oldRoom && _soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, _stopSeconds); + + _soundHandle = -1; + _startFlag = false; + } + + return true; +} + +bool CFanNoises::StatusChangeMsg(CStatusChangeMsg *msg) { + if (msg->_newStatus >= -1 && msg->_newStatus <= 2) { + int oldState = _state; + _state = msg->_newStatus; + + switch (msg->_newStatus) { + case -1: + case 0: + if (_soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 1); + _soundHandle = -1; + _startFlag = false; + } + + switch (oldState) { + case 1: + case 2: + playSound("b#59.wav", _soundPercent, _soundV3); + break; + default: + break; + } + break; + + case 1: + if (_soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 1); + _soundHandle = -1; + _startFlag = false; + } + + switch (oldState) { + case 1: + case 2: + _soundHandle = playSound("b#60.wav", _soundPercent, _soundV3); + break; + default: + break; + } + break; + + case 2: + if (_soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 1); + _soundHandle = -1; + _startFlag = false; + } + + if (oldState == 1) { + _soundHandle = playSound("b#58.wav", _soundPercent, _soundV3); + } + break; + + default: + break; + } + } + + return true; +} + +bool CFanNoises::SetVolumeMsg(CSetVolumeMsg *msg) { + _soundPercent = msg->_volume; + + if (_soundHandle != -1 && isSoundActive(_soundHandle)) + setSoundVolume(_soundHandle, _soundPercent, msg->_secondsTransition); + + return true; +} + +bool CFanNoises::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_startFlag) { + _startFlag = false; + _soundHandle = -1; + + switch (_state) { + case 1: + playSound("b#60.wav", 0, _soundV3, true); + setSoundVolume(_soundHandle, _soundPercent, _soundSeconds); + _startFlag = true; + break; + + case 2: + playSound("b#58.wav", 0, _soundV3, true); + setSoundVolume(_soundHandle, _soundPercent, _soundSeconds); + _startFlag = true; + break; + + default: + break; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/fan_noises.h b/engines/titanic/game/fan_noises.h new file mode 100644 index 0000000000..56c80c0764 --- /dev/null +++ b/engines/titanic/game/fan_noises.h @@ -0,0 +1,63 @@ +/* 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_FAN_NOISES_H +#define TITANIC_FAN_NOISES_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CFanNoises : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool SetVolumeMsg(CSetVolumeMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +private: + int _state; + int _soundHandle; + int _soundPercent; + int _soundV3; + int _soundSeconds; + int _stopSeconds; + bool _startFlag; +public: + CLASSDEF; + CFanNoises(); + + /** + * 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_FAN_NOISES_H */ diff --git a/engines/titanic/game/floor_indicator.cpp b/engines/titanic/game/floor_indicator.cpp new file mode 100644 index 0000000000..3afb03c59d --- /dev/null +++ b/engines/titanic/game/floor_indicator.cpp @@ -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. + * + */ + +#include "titanic/game/floor_indicator.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CFloorIndicator, CGameObject) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CFloorIndicator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CFloorIndicator::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CFloorIndicator::EnterViewMsg(CEnterViewMsg *msg) { + int floorNum = MAX(1, getPetControl()->getRoomsFloorNum()); + loadFrame(floorNum - 1); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/floor_indicator.h b/engines/titanic/game/floor_indicator.h new file mode 100644 index 0000000000..38a1757ad0 --- /dev/null +++ b/engines/titanic/game/floor_indicator.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_FLOOR_INDICATOR_H +#define TITANIC_FLOOR_INDICATOR_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CFloorIndicator : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *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_FLOOR_INDICATOR_H */ diff --git a/engines/titanic/game/games_console.cpp b/engines/titanic/game/games_console.cpp new file mode 100644 index 0000000000..40311f70ee --- /dev/null +++ b/engines/titanic/game/games_console.cpp @@ -0,0 +1,65 @@ +/* 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/game/games_console.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGamesConsole, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CGamesConsole::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_active, indent); + CBackground::save(file, indent); +} + +void CGamesConsole::load(SimpleFile *file) { + file->readNumber(); + _active = file->readNumber(); + CBackground::load(file); +} + +bool CGamesConsole::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_active) { + playMovie(23, 44, 0); + _active = false; + } else { + playMovie(0, 23, 0); + _active = true; + } + + return true; +} + +bool CGamesConsole::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_active) { + _active = false; + playMovie(23, 44, MOVIE_GAMESTATE); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/games_console.h b/engines/titanic/game/games_console.h new file mode 100644 index 0000000000..f849fd08cc --- /dev/null +++ b/engines/titanic/game/games_console.h @@ -0,0 +1,53 @@ +/* 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_GAMES_CONSOLE_H +#define TITANIC_GAMES_CONSOLE_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CGamesConsole : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +public: + bool _active; +public: + CLASSDEF; + CGamesConsole() : CBackground(), _active(false) {} + + /** + * 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_GAMES_CONSOLE_H */ diff --git a/engines/titanic/game/get_lift_eye2.cpp b/engines/titanic/game/get_lift_eye2.cpp new file mode 100644 index 0000000000..914f306f0e --- /dev/null +++ b/engines/titanic/game/get_lift_eye2.cpp @@ -0,0 +1,100 @@ +/* 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/game/get_lift_eye2.h" +#include "titanic/game/transport/lift.h" +#include "titanic/core/project_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGetLiftEye2, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +CString *CGetLiftEye2::_destObject; + +void CGetLiftEye2::init() { + _destObject = new CString(); +} + +void CGetLiftEye2::deinit() { + delete _destObject; +} + +void CGetLiftEye2::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(*_destObject, indent); + CGameObject::save(file, indent); +} + +void CGetLiftEye2::load(SimpleFile *file) { + file->readNumber(); + *_destObject = file->readString(); + CGameObject::load(file); +} + +bool CGetLiftEye2::ActMsg(CActMsg *msg) { + *_destObject = msg->_action; + setVisible(true); + return true; +} + +bool CGetLiftEye2::EnterRoomMsg(CEnterRoomMsg *msg) { + CPetControl *pet = getPetControl(); + if (pet->getRoomsElevatorNum() == 4 && CLift::_v1 == 1 && !CLift::_v6) { + _cursorId = CURSOR_HAND; + setVisible(true); + } else { + _cursorId = CURSOR_ARROW; + setVisible(false); + } + + return true; +} + +bool CGetLiftEye2::VisibleMsg(CVisibleMsg *msg) { + setVisible(true); + _cursorId = CURSOR_HAND; + return true; +} + +bool CGetLiftEye2::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkPoint(msg->_mousePos, false, true)) { + _cursorId = CURSOR_ARROW; + setVisible(false); + CActMsg actMsg("EyeNotHead"); + actMsg.execute(*_destObject); + CPassOnDragStartMsg dragMsg(msg->_mousePos, 1); + dragMsg.execute(*_destObject); + + msg->_dragItem = getRoot()->findByName(*_destObject); + return true; + } else { + return false; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/get_lift_eye2.h b/engines/titanic/game/get_lift_eye2.h new file mode 100644 index 0000000000..c0dd49206e --- /dev/null +++ b/engines/titanic/game/get_lift_eye2.h @@ -0,0 +1,56 @@ +/* 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_GET_LIFT_EYE2_H +#define TITANIC_GET_LIFT_EYE2_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" +namespace Titanic { + +class CGetLiftEye2 : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +public: + static CString *_destObject; +public: + CLASSDEF; + static void init(); + static void deinit(); + + /** + * 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_GET_LIFT_EYE2_H */ diff --git a/engines/titanic/game/glass_smasher.cpp b/engines/titanic/game/glass_smasher.cpp new file mode 100644 index 0000000000..2123f2dfd0 --- /dev/null +++ b/engines/titanic/game/glass_smasher.cpp @@ -0,0 +1,56 @@ +/* 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/game/glass_smasher.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGlassSmasher, CGameObject) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CGlassSmasher::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CGlassSmasher::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CGlassSmasher::StatusChangeMsg(CStatusChangeMsg *msg) { + setVisible(true); + playSound("b#40.wav"); + playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + return true; +} + +bool CGlassSmasher::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(false); + CVisibleMsg visibleMsg(true); + visibleMsg.execute("LongStickDispenser"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/glass_smasher.h b/engines/titanic/game/glass_smasher.h new file mode 100644 index 0000000000..e1eef6f87a --- /dev/null +++ b/engines/titanic/game/glass_smasher.h @@ -0,0 +1,50 @@ +/* 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_GLASS_SMASHER_H +#define TITANIC_GLASS_SMASHER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CGlassSmasher : public CGameObject { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MovieEndMsg(CMovieEndMsg *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_GLASS_SMASHER_H */ diff --git a/engines/titanic/game/gondolier/gondolier_base.cpp b/engines/titanic/game/gondolier/gondolier_base.cpp new file mode 100644 index 0000000000..f3dc31c9f5 --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_base.cpp @@ -0,0 +1,79 @@ +/* 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/game/gondolier/gondolier_base.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGondolierBase, CGameObject) + ON_MESSAGE(PuzzleSolvedMsg) +END_MESSAGE_MAP() + +int CGondolierBase::_v1; +bool CGondolierBase::_puzzleSolved; +int CGondolierBase::_volume1; +int CGondolierBase::_v4; +int CGondolierBase::_v5; +int CGondolierBase::_volume2; +int CGondolierBase::_v7; +int CGondolierBase::_v8; +int CGondolierBase::_v9; +int CGondolierBase::_v10; + +void CGondolierBase::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_puzzleSolved, indent); + file->writeNumberLine(_volume1, indent); + file->writeNumberLine(_v4, indent); + file->writeNumberLine(_v5, indent); + file->writeNumberLine(_volume2, indent); + file->writeNumberLine(_v7, indent); + file->writeNumberLine(_v8, indent); + file->writeNumberLine(_v9, indent); + file->writeNumberLine(_v10, indent); + + CGameObject::save(file, indent); +} + +void CGondolierBase::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _puzzleSolved = file->readNumber(); + _volume1 = file->readNumber(); + _v4 = file->readNumber(); + _v5 = file->readNumber(); + _volume2 = file->readNumber(); + _v7 = file->readNumber(); + _v8 = file->readNumber(); + _v9 = file->readNumber(); + _v10 = file->readNumber(); + + CGameObject::load(file); +} + +bool CGondolierBase::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _puzzleSolved = true; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/gondolier/gondolier_base.h b/engines/titanic/game/gondolier/gondolier_base.h new file mode 100644 index 0000000000..06d77ba85f --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_base.h @@ -0,0 +1,60 @@ +/* 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_GONDOLIER_BASE_H +#define TITANIC_GONDOLIER_BASE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CGondolierBase : public CGameObject { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); +protected: + static int _v1; + static bool _puzzleSolved; + static int _volume1; + static int _v4; + static int _v5; + static int _volume2; + static int _v7; + static int _v8; + static int _v9; + static int _v10; +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_GONDOLIER_BASE_H */ diff --git a/engines/titanic/game/gondolier/gondolier_chest.cpp b/engines/titanic/game/gondolier/gondolier_chest.cpp new file mode 100644 index 0000000000..cf6656732b --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_chest.cpp @@ -0,0 +1,66 @@ +/* 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/game/gondolier/gondolier_chest.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGondolierChest, CGondolierBase) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CGondolierChest::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGondolierBase::save(file, indent); +} + +void CGondolierChest::load(SimpleFile *file) { + file->readNumber(); + CGondolierBase::load(file); +} + +bool CGondolierChest::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_v1) + playMovie(0, 14, MOVIE_NOTIFY_OBJECT); + else if (msg->_mousePos.y < 330) + return false; + else if (!_v8 && !_v5) { + playMovie(14, 29, 0); + _v1 = 0; + } + + return true; +} + +bool CGondolierChest::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == 14) + _v1 = 1; + return true; +} + +bool CGondolierChest::MouseDragStartMsg(CMouseDragStartMsg *msg) { + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/gondolier/gondolier_chest.h b/engines/titanic/game/gondolier/gondolier_chest.h new file mode 100644 index 0000000000..8f069241a0 --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_chest.h @@ -0,0 +1,51 @@ +/* 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_GONDOLIER_CHEST_H +#define TITANIC_GONDOLIER_CHEST_H + +#include "titanic/game/gondolier/gondolier_base.h" + +namespace Titanic { + +class CGondolierChest : public CGondolierBase { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *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_GONDOLIER_CHEST_H */ diff --git a/engines/titanic/game/gondolier/gondolier_face.cpp b/engines/titanic/game/gondolier/gondolier_face.cpp new file mode 100644 index 0000000000..d7bcfa3561 --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_face.cpp @@ -0,0 +1,58 @@ +/* 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/game/gondolier/gondolier_face.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGondolierFace, CGondolierBase) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +void CGondolierFace::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CGondolierBase::save(file, indent); +} + +void CGondolierFace::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CGondolierBase::load(file); +} + +bool CGondolierFace::EnterViewMsg(CEnterViewMsg *msg) { + if (_flag) + playMovie(MOVIE_REPEAT); + else + setVisible(false); + return true; +} + +bool CGondolierFace::StatusChangeMsg(CStatusChangeMsg *msg) { + _flag = msg->_newStatus != 1; + setVisible(_flag); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/gondolier/gondolier_face.h b/engines/titanic/game/gondolier/gondolier_face.h new file mode 100644 index 0000000000..b441204d3f --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_face.h @@ -0,0 +1,53 @@ +/* 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_GONDOLIER_FACE_H +#define TITANIC_GONDOLIER_FACE_H + +#include "titanic/game/gondolier/gondolier_base.h" + +namespace Titanic { + +class CGondolierFace : public CGondolierBase { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CGondolierFace() : CGondolierBase(), _flag(true) {} + + /** + * 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_GONDOLIER_FACE_H */ diff --git a/engines/titanic/game/gondolier/gondolier_mixer.cpp b/engines/titanic/game/gondolier/gondolier_mixer.cpp new file mode 100644 index 0000000000..26deda8bca --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_mixer.cpp @@ -0,0 +1,194 @@ +/* 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/game/gondolier/gondolier_mixer.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGondolierMixer, CGondolierBase) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(SetVolumeMsg) + ON_MESSAGE(SignalObject) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +CGondolierMixer::CGondolierMixer() : CGondolierBase(), + _soundName1("c#0.wav"), _soundName2("c#1.wav"), + _soundHandle1(-1), _soundHandle2(-1), _fieldC4(0), _fieldC8(0), + _fieldE4(false) { +} + +void CGondolierMixer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_soundHandle1, indent); + file->writeNumberLine(_soundHandle2, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeQuotedLine(_soundName1, indent); + file->writeQuotedLine(_soundName2, indent); + file->writeNumberLine(_fieldE4, indent); + + CGondolierBase::save(file, indent); +} + +void CGondolierMixer::load(SimpleFile *file) { + file->readNumber(); + _soundHandle1 = file->readNumber(); + _soundHandle2 = file->readNumber(); + _fieldC4 = file->readNumber(); + _fieldC8 = file->readNumber(); + _soundName1 = file->readString(); + _soundName2 = file->readString(); + _fieldE4 = file->readNumber(); + + CGondolierBase::load(file); +} + +bool CGondolierMixer::EnterRoomMsg(CEnterRoomMsg *msg) { + CRoomItem *parentRoom = dynamic_cast<CRoomItem *>(getParent()); + if (parentRoom == msg->_newRoom) { + CTurnOn onMsg; + onMsg.execute(this); + } + + return true; +} + +bool CGondolierMixer::LeaveRoomMsg(CLeaveRoomMsg *msg) { + CRoomItem *parentRoom = dynamic_cast<CRoomItem *>(getParent()); + if (parentRoom == msg->_oldRoom) { + CTurnOff offMsg; + offMsg.execute(this); + } + + return true; +} + +bool CGondolierMixer::TurnOn(CTurnOn *msg) { + if (!_puzzleSolved) { + if (_soundHandle1 == -1) { + _soundHandle1 = playSound(_soundName1, _volume1 * _v4 / 10, 0, true); + _fieldE4 = true; + } + + if (_soundHandle2 == -1) { + _soundHandle2 = playSound(_soundName1, _volume2 * _v7 / 10, 0, true); + _fieldE4 = true; + } + } + + return true; +} + +bool CGondolierMixer::TurnOff(CTurnOff *msg) { + if (_soundHandle1 != -1) { + if (isSoundActive(_soundHandle1)) + stopSound(_soundHandle1, 2); + + _soundHandle1 = -1; + _fieldE4 = false; + } + + if (_soundHandle2 != -1) { + if (isSoundActive(_soundHandle2)) + stopSound(_soundHandle2, 2); + + _soundHandle2 = -1; + _fieldE4 = false; + } + + return true; +} + +bool CGondolierMixer::SetVolumeMsg(CSetVolumeMsg *msg) { + if (!_puzzleSolved) { + _volume1 = _volume2 = msg->_volume; + + if (_soundHandle1 != -1 && isSoundActive(_soundHandle1)) + setSoundVolume(_soundHandle1, msg->_volume * _v4 / 10, 2); + if (_soundHandle2 != -1 && isSoundActive(_soundHandle2)) + setSoundVolume(_soundHandle2, msg->_volume * _v7 / 10, 2); + } + + return true; +} + +bool CGondolierMixer::SignalObject(CSignalObject *msg) { + if (!_puzzleSolved) { + if (msg->_strValue == "Fly") { + _v4 = CLIP(msg->_numValue, 0, 10); + + if (!_v8) { + _v7 = 10 - _v4; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _v7; + statusMsg.execute("GondolierRightLever"); + } + } + + if (msg->_strValue == "Tos") { + _v7 = CLIP(msg->_numValue, 0, 10); + + if (!_v5) { + _v4 = 10 - _v7; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _v4; + statusMsg.execute("GondolierLeftLever"); + } + } + + if (!_v4 && !_v7 && _v5 && _v8) { + _puzzleSolved = true; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("GondolierFace"); + CTurnOff offMsg; + offMsg.execute(this); + CVisibleMsg visibleMsg; + visibleMsg.execute("Mouth"); + + playSound("z#47.wav"); + } else { + CSetVolumeMsg volumeMsg(_volume1, 2); + volumeMsg.execute(this); + } + } + + return true; +} + +bool CGondolierMixer::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_fieldE4) { + _fieldE4 = 0; + _soundHandle1 = _soundHandle2 = -1; + CTurnOn onMsg; + onMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/gondolier/gondolier_mixer.h b/engines/titanic/game/gondolier/gondolier_mixer.h new file mode 100644 index 0000000000..167650f5bb --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_mixer.h @@ -0,0 +1,65 @@ +/* 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_GONDOLIER_MIXER_H +#define TITANIC_GONDOLIER_MIXER_H + +#include "titanic/game/gondolier/gondolier_base.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CGondolierMixer : public CGondolierBase { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool SetVolumeMsg(CSetVolumeMsg *msg); + bool SignalObject(CSignalObject *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +private: + int _soundHandle1; + int _soundHandle2; + int _fieldC4; + int _fieldC8; + CString _soundName1; + CString _soundName2; + bool _fieldE4; +public: + CLASSDEF; + CGondolierMixer(); + + /** + * 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_GONDOLIER_MIXER_H */ diff --git a/engines/titanic/game/gondolier/gondolier_slider.cpp b/engines/titanic/game/gondolier/gondolier_slider.cpp new file mode 100644 index 0000000000..e7a46eb33d --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_slider.cpp @@ -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. + * + */ + +#include "titanic/game/gondolier/gondolier_slider.h" + +namespace Titanic { + +static const int ARRAY[11] = { 0, 0, 1, 4, 9, 15, 21, 27, 32, 35, 36 }; + +BEGIN_MESSAGE_MAP(CGondolierSlider, CGondolierBase) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseDragMoveMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MouseDragEndMsg) + ON_MESSAGE(IsHookedOnMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(SignalObject) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +CGondolierSlider::CGondolierSlider() : CGondolierBase(), + _fieldBC(0), _fieldC0(0), _fieldC4(0), _fieldC8(0), + _arrayIndex(0), _string1("NULL"), _fieldFC(0), _field118(0) { +} + +void CGondolierSlider::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_sliderRect1.left, indent); + file->writeNumberLine(_sliderRect1.top, indent); + file->writeNumberLine(_sliderRect1.right, indent); + file->writeNumberLine(_sliderRect1.bottom, indent); + file->writeNumberLine(_sliderRect2.left, indent); + file->writeNumberLine(_sliderRect2.top, indent); + file->writeNumberLine(_sliderRect2.right, indent); + file->writeNumberLine(_sliderRect2.bottom, indent); + file->writeNumberLine(_sliderRect1.left, indent); + file->writeQuotedLine(_string1, indent); + file->writeNumberLine(_fieldFC, indent); + file->writeQuotedLine(_string2, indent); + file->writeQuotedLine(_string3, indent); + file->writeNumberLine(_field118, indent); + + CGondolierBase::save(file, indent); +} + +void CGondolierSlider::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + _fieldC4 = file->readNumber(); + _fieldC8 = file->readNumber(); + _sliderRect1.left = file->readNumber(); + _sliderRect1.top = file->readNumber(); + _sliderRect1.right = file->readNumber(); + _sliderRect1.bottom = file->readNumber(); + _sliderRect2.left = file->readNumber(); + _sliderRect2.top = file->readNumber(); + _sliderRect2.right = file->readNumber(); + _sliderRect2.bottom = file->readNumber(); + _arrayIndex = file->readNumber(); + _string1 = file->readString(); + _fieldFC = file->readNumber(); + _string2 = file->readString(); + _string3 = file->readString(); + _field118 = file->readNumber(); + + CGondolierBase::load(file); +} + +bool CGondolierSlider::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_v1) + return false; + if (_fieldFC ? _v5 : _v8) + return false; + + return _sliderRect1.contains(msg->_mousePos); +} + +bool CGondolierSlider::MouseDragMoveMsg(CMouseDragMoveMsg *msg) { + if (!(_fieldFC ? _v5 : _v8)) { + int minVal = 0x7FFFFFFF; + int foundIndex = -1; + int yp = (_sliderRect2.top + _sliderRect2.bottom) / 2 + + _bounds.top - msg->_mousePos.y; + + for (int idx = 0; idx < 11; ++idx) { + int yv = yp + ARRAY[idx]; + if (yv < 0) + yv = -yv; + if (yv < minVal) { + minVal = yv; + foundIndex = idx; + } + } + + if (foundIndex >= 0) { + _arrayIndex = foundIndex; + CSignalObject signalMsg; + signalMsg.execute(this); + } + } + + return true; +} + +bool CGondolierSlider::EnterViewMsg(CEnterViewMsg *msg) { + CSignalObject signalMsg; + signalMsg.execute(this); + return true; +} + +bool CGondolierSlider::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!_v1) + return false; + if (_fieldFC ? _v5 : _v8) + return false; + + _field118 = checkStartDragging(msg); + return _field118; +} + +bool CGondolierSlider::StatusChangeMsg(CStatusChangeMsg *msg) { + _arrayIndex = CLIP(10 - msg->_newStatus, 0, 10); + _sliderRect1 = _sliderRect2; + _sliderRect1.translate(_bounds.left, _bounds.top); + _sliderRect1.translate(0, ARRAY[_arrayIndex]); + + loadFrame(_arrayIndex); + return true; +} + +bool CGondolierSlider::MouseDragEndMsg(CMouseDragEndMsg *msg) { + _field118 = false; + return true; +} + +bool CGondolierSlider::IsHookedOnMsg(CIsHookedOnMsg *msg) { + if (_fieldFC ? _v5 : _v8) + return false; + + if (!_sliderRect1.intersects(msg->_rect)) { + _string2 = CString(); + msg->_result = false; + } else { + _string2 = _string1; + if (_fieldFC) { + _v5 = _v9 = 1; + } else { + _v8 = _v10 = 1; + } + + msg->_result = true; + } + + return true; +} + +bool CGondolierSlider::FrameMsg(CFrameMsg *msg) { + if (_fieldFC ? _v5 : _v8) { + if (_arrayIndex < 10) { + ++_arrayIndex; + CSignalObject signalMsg; + signalMsg.execute(this); + + int yp = 0; + if (_arrayIndex > 0) + yp = ARRAY[_arrayIndex] - ARRAY[_arrayIndex - 1]; + + if (!_string2.empty()) { + CTranslateObjectMsg transMsg; + transMsg._delta = Point(0, yp); + transMsg.execute(_string2); + } + } + } else if (_fieldFC ? _v10 : _v9) { + if (!_field118 && !_puzzleSolved && _arrayIndex > 0) { + CSignalObject signalMsg; + signalMsg.execute(this); + } + } + + return true; +} + +bool CGondolierSlider::SignalObject(CSignalObject *msg) { + _arrayIndex = CLIP(_arrayIndex, 0, 10); + _sliderRect1 = _sliderRect2; + _sliderRect1.translate(_bounds.left, _bounds.top); + _sliderRect1.translate(0, ARRAY[_arrayIndex]); + loadFrame(_arrayIndex); + + CSignalObject signalMsg; + signalMsg._numValue = 10 - _arrayIndex; + signalMsg._strValue = _fieldFC ? "Fly" : "Tos"; + signalMsg.execute(_string3); + + return true; +} + +bool CGondolierSlider::ActMsg(CActMsg *msg) { + if (msg->_action == "Unhook") { + if (_fieldFC) { + _v5 = _v9 = 0; + _v10 = _v8; + } else { + _v8 = _v10 = 0; + _v9 = _v5; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/gondolier/gondolier_slider.h b/engines/titanic/game/gondolier/gondolier_slider.h new file mode 100644 index 0000000000..d1562f5b2d --- /dev/null +++ b/engines/titanic/game/gondolier/gondolier_slider.h @@ -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. + * + */ + +#ifndef TITANIC_GONDOLIER_SLIDER_H +#define TITANIC_GONDOLIER_SLIDER_H + +#include "titanic/game/gondolier/gondolier_base.h" + +namespace Titanic { + +class CGondolierSlider : public CGondolierBase { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseDragMoveMsg(CMouseDragMoveMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MouseDragEndMsg(CMouseDragEndMsg *msg); + bool IsHookedOnMsg(CIsHookedOnMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool SignalObject(CSignalObject *msg); + bool ActMsg(CActMsg *msg); +private: + int _fieldBC; + int _fieldC0; + int _fieldC4; + int _fieldC8; + Rect _sliderRect1; + Rect _sliderRect2; + int _arrayIndex; + CString _string1; + int _fieldFC; + CString _string2; + CString _string3; + bool _field118; +public: + CLASSDEF; + CGondolierSlider(); + + /** + * 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_GONDOLIER_SLIDER_H */ diff --git a/engines/titanic/game/hammer_clip.cpp b/engines/titanic/game/hammer_clip.cpp new file mode 100644 index 0000000000..7fb64350af --- /dev/null +++ b/engines/titanic/game/hammer_clip.cpp @@ -0,0 +1,83 @@ +/* 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/game/hammer_clip.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHammerClip, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CHammerClip::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CHammerClip::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +bool CHammerClip::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CHammerClip::StatusChangeMsg(CStatusChangeMsg *msg) { + _value = msg->_newStatus == 1; + if (_value) { + CPuzzleSolvedMsg solvedMsg; + solvedMsg.execute("BigHammer"); + _cursorId = CURSOR_HAND; + } + + return true; +} + +bool CHammerClip::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) + return false; + + if (_value) { + CVisibleMsg visibleMsg(true); + visibleMsg.execute("BigHammer"); + CPassOnDragStartMsg passMsg(msg->_mousePos, 1); + passMsg.execute("BigHammer"); + + msg->_dragItem = getRoot()->findByName("BigHammer"); + + CActMsg actMsg("HammerTaken"); + actMsg.execute("HammerDispensor"); + actMsg.execute("HammerDispensorButton"); + _cursorId = CURSOR_ARROW; + _value = 0; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/hammer_clip.h b/engines/titanic/game/hammer_clip.h new file mode 100644 index 0000000000..4af58c22a5 --- /dev/null +++ b/engines/titanic/game/hammer_clip.h @@ -0,0 +1,54 @@ +/* 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_HAMMER_CLIP_H +#define TITANIC_HAMMER_CLIP_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CHammerClip : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +public: + int _value; +public: + CLASSDEF; + CHammerClip() : CGameObject(), _value(0) {} + + /** + * 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_HAMMER_CLIP_H */ diff --git a/engines/titanic/game/hammer_dispensor.cpp b/engines/titanic/game/hammer_dispensor.cpp new file mode 100644 index 0000000000..bc6a3d5ad8 --- /dev/null +++ b/engines/titanic/game/hammer_dispensor.cpp @@ -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. + * + */ + +#include "titanic/game/hammer_dispensor.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHammerDispensor, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +CHammerDispensor::CHammerDispensor() : CBackground(), + _fieldE0(false), _fieldE4(true), _state(0) { +} + +void CHammerDispensor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_state, indent); + + CBackground::save(file, indent); +} + +void CHammerDispensor::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _state = file->readNumber(); + + CBackground::load(file); +} + +bool CHammerDispensor::ActMsg(CActMsg *msg) { + if (msg->_action == "DispenseHammer" && !_fieldE0) { + _state = 1; + playMovie(15, 31, MOVIE_NOTIFY_OBJECT); + _fieldE0 = true; + } + + if (msg->_action == "HammerTaken" && _fieldE0) + loadFrame(32); + + return true; +} + +bool CHammerDispensor::EnterViewMsg(CEnterViewMsg *msg) { + if (_fieldE4) { + playMovie(7, 14, 0); + _fieldE4 = false; + } + + return true; +} + +bool CHammerDispensor::LeaveViewMsg(CLeaveViewMsg *msg) { + _fieldE4 = true; + _fieldE0 = 0; + _state = 2; + + if (_fieldE0) + playMovie(32, 50, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + else + playMovie(0, 7, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + return true; +} + +bool CHammerDispensor::MovieEndMsg(CMovieEndMsg *msg) { + if (_state == 1) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("HammerClip"); + } else if (_state == 2) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 2; + statusMsg.execute("HammerClip"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/hammer_dispensor.h b/engines/titanic/game/hammer_dispensor.h new file mode 100644 index 0000000000..2383a3349e --- /dev/null +++ b/engines/titanic/game/hammer_dispensor.h @@ -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. + * + */ + +#ifndef TITANIC_HAMMER_DISPENSOR_H +#define TITANIC_HAMMER_DISPENSOR_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CHammerDispensor : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + bool _fieldE0; + bool _fieldE4; + int _state; +public: + CLASSDEF; + CHammerDispensor(); + + /** + * 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_HAMMER_DISPENSOR_H */ diff --git a/engines/titanic/game/hammer_dispensor_button.cpp b/engines/titanic/game/hammer_dispensor_button.cpp new file mode 100644 index 0000000000..fbda501a24 --- /dev/null +++ b/engines/titanic/game/hammer_dispensor_button.cpp @@ -0,0 +1,145 @@ +/* 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/game/hammer_dispensor_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHammerDispensorButton, CStartAction) + ON_MESSAGE(PuzzleSolvedMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CHammerDispensorButton::CHammerDispensorButton() : CStartAction(), + _fieldF8(0), _fieldFC(0), _field100(0), _btnPos(Point(56, 6)), + _field10C(nullptr), _field110(0) { +} + +void CHammerDispensorButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_fieldFC, indent); + file->writeNumberLine(_field100, indent); + file->writeNumberLine(_btnPos.x, indent); + file->writeNumberLine(_btnPos.y, indent); + file->writeNumberLine(_field110, indent); + + CStartAction::save(file, indent); +} + +void CHammerDispensorButton::load(SimpleFile *file) { + file->readNumber(); + _fieldF8 = file->readNumber(); + _fieldFC = file->readNumber(); + _field100 = file->readNumber(); + _btnPos.x = file->readNumber(); + _btnPos.y = file->readNumber(); + _field110 = file->readNumber(); + + CStartAction::load(file); +} + +bool CHammerDispensorButton::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + _fieldF8 = 1; + return true; +} + +bool CHammerDispensorButton::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + playSound("z#93.wav"); + petDisplayMessage(1, "In case of emergency hammer requirement, poke with long stick."); + return true; +} + +bool CHammerDispensorButton::ActMsg(CActMsg *msg) { + if (msg->_action == "HammerTaken") + _field110 = true; + return true; +} + +bool CHammerDispensorButton::FrameMsg(CFrameMsg *msg) { + if (!_fieldF8) + return true; + + if (!_field10C) { + CGameObject *obj = getDraggingObject(); + if (obj) { + if (obj->isEquals("Perch") && getView() == findView()) + _field10C = obj; + } + } + + if (_field10C) { + Point pt(_btnPos.x + _bounds.left, _btnPos.y + _bounds.top); + bool flag = checkPoint(pt, true); + + switch (_fieldFC) { + case 0: + if (flag) { + playSound("z#93.wav"); + if (++_field100 == 5) { + if (!_field110) { + CActMsg actMsg(_msgAction); + actMsg.execute(_msgTarget); + } + + setVisible(false); + _fieldF8 = 0; + _field100 = 0; + } + + _fieldFC = 1; + } + break; + + case 1: + if (!flag) { + _fieldFC = 0; + ++_field100; + } + break; + + default: + break; + } + } + + return true; +} + +bool CHammerDispensorButton::LeaveViewMsg(CLeaveViewMsg *msg) { + _field10C = nullptr; + _field100 = 0; + _fieldFC = 0; + return true; +} + +bool CHammerDispensorButton::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(true); + _fieldF8 = 1; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/hammer_dispensor_button.h b/engines/titanic/game/hammer_dispensor_button.h new file mode 100644 index 0000000000..f497b9dae1 --- /dev/null +++ b/engines/titanic/game/hammer_dispensor_button.h @@ -0,0 +1,62 @@ +/* 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_HAMMER_DISPENSOR_BUTTON_H +#define TITANIC_HAMMER_DISPENSOR_BUTTON_H + +#include "titanic/game/start_action.h" + +namespace Titanic { + +class CHammerDispensorButton : public CStartAction { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool ActMsg(CActMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + int _fieldF8; + int _fieldFC; + int _field100; + Point _btnPos; + CGameObject *_field10C; + int _field110; +public: + CLASSDEF; + CHammerDispensorButton(); + + /** + * 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_HAMMER_DISPENSOR_BUTTON_H */ diff --git a/engines/titanic/game/head_slot.cpp b/engines/titanic/game/head_slot.cpp new file mode 100644 index 0000000000..f7df02d364 --- /dev/null +++ b/engines/titanic/game/head_slot.cpp @@ -0,0 +1,184 @@ +/* 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/game/head_slot.h" +#include "titanic/core/project_item.h" +#include "titanic/game/brain_slot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHeadSlot, CGameObject) + ON_MESSAGE(AddHeadPieceMsg) + ON_MESSAGE(SenseWorkingMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(LoadSuccessMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +int CHeadSlot::_v1; + +CHeadSlot::CHeadSlot() : CGameObject(), _string1("NotWorking"), _string2("NULL"), + _fieldBC(0), _fieldD8(0), _fieldDC(27), _fieldE0(56), + _fieldE4(82), _fieldE8(112), _fieldEC(false) { +} + +void CHeadSlot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_fieldD8, indent); + file->writeNumberLine(_fieldDC, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_fieldEC, indent); + + CGameObject::save(file, indent); +} + +void CHeadSlot::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + _fieldD8 = file->readNumber(); + _fieldDC = file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _v1 = file->readNumber(); + _fieldEC = file->readNumber(); + + CGameObject::load(file); +} + +bool CHeadSlot::AddHeadPieceMsg(CAddHeadPieceMsg *msg) { + setVisible(true); + _fieldBC = 1; + _string2 = msg->_value; + playMovie(_fieldDC, _fieldE8, 0); + _cursorId = CURSOR_HAND; + msg->execute("TitaniaControl"); + return true; +} + +bool CHeadSlot::SenseWorkingMsg(CSenseWorkingMsg *msg) { + if (_fieldEC) + playMovie(_fieldE4, _fieldE8, 0); + + _string1 = msg->_value; + _fieldEC = false; + return true; +} + +bool CHeadSlot::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(true); + if (_v1) + _cursorId = CURSOR_ARROW; + + if (_v1 == 1 || _string1 == "Working") { + playMovie(_fieldE0, _fieldE4, MOVIE_GAMESTATE); + _fieldEC = true; + } else if (_fieldBC) { + playMovie(_fieldE0, _fieldE8, MOVIE_GAMESTATE); + _fieldEC = false; + } else { + playMovie(0, _fieldDC, MOVIE_GAMESTATE); + } + + addTimer(5000 + getRandomNumber(3000)); + return true; +} + +bool CHeadSlot::LeaveViewMsg(CLeaveViewMsg *msg) { + if (getName() == "YepItsASlot") { + stopMovie(); + + if (_fieldBC) { + loadFrame(_fieldE0); + playMovie(_fieldE0, _fieldE8, MOVIE_GAMESTATE); + _fieldEC = false; + } else { + loadFrame(_fieldDC); + playMovie(_fieldDC, _fieldE0, MOVIE_GAMESTATE); + } + + _fieldEC = false; + } + + return true; +} + +bool CHeadSlot::LoadSuccessMsg(CLoadSuccessMsg *msg) { + return true; +} + +bool CHeadSlot::TimerMsg(CTimerMsg *msg) { + if (compareViewNameTo("Titania.Node 15.S") && CBrainSlot::_added == 5 + && _fieldBC == 1) { + if (_string1 == "Working" && !_fieldEC) { + playMovie(_fieldE0, _fieldE4, 0); + _fieldEC = true; + } else if (_string1 == "Random") { + playMovie(_fieldE0, _fieldE8, 0); + } + } + + if (compareViewNameTo("Titania.Node 15.S")) { + _fieldD8 = 7000 + getRandomNumber(5000); + addTimer(_fieldD8); + } + + return true; +} + +bool CHeadSlot::ActMsg(CActMsg *msg) { + if (msg->_action == "Woken") + _v1 = 1; + return true; +} + +bool CHeadSlot::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (_fieldBC && !_v1 && checkPoint(msg->_mousePos, false, true)) { + CPassOnDragStartMsg passMsg; + passMsg._mousePos = msg->_mousePos; + passMsg.execute(_string2); + + msg->_dragItem = getRoot()->findByName(_string2); + _cursorId = CURSOR_ARROW; + _fieldBC = 0; + _fieldEC = false; + _string2 = "NULL"; + stopMovie(); + loadFrame(0); + playMovie(0, _fieldDC, 0); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/head_slot.h b/engines/titanic/game/head_slot.h new file mode 100644 index 0000000000..2767db3b61 --- /dev/null +++ b/engines/titanic/game/head_slot.h @@ -0,0 +1,69 @@ +/* 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_HEAD_SLOT_H +#define TITANIC_HEAD_SLOT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CHeadSlot : public CGameObject { + DECLARE_MESSAGE_MAP; + bool AddHeadPieceMsg(CAddHeadPieceMsg *msg); + bool SenseWorkingMsg(CSenseWorkingMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool ActMsg(CActMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +public: + static int _v1; +public: + int _fieldBC; + CString _string1; + CString _string2; + int _fieldD8; + int _fieldDC; + int _fieldE0; + int _fieldE4; + int _fieldE8; + bool _fieldEC; +public: + CLASSDEF; + CHeadSlot(); + + /** + * 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_HEAD_SLOT_H */ diff --git a/engines/titanic/game/head_smash_event.cpp b/engines/titanic/game/head_smash_event.cpp new file mode 100644 index 0000000000..5ec3d299d5 --- /dev/null +++ b/engines/titanic/game/head_smash_event.cpp @@ -0,0 +1,56 @@ +/* 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/game/head_smash_event.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHeadSmashEvent, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CHeadSmashEvent::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CHeadSmashEvent::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +bool CHeadSmashEvent::ActMsg(CActMsg *msg) { + if (msg->_action == "PlayToEnd") { + setVisible(true); + playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + + return true; +} + +bool CHeadSmashEvent::MovieEndMsg(CMovieEndMsg *msg) { + changeView("CreatorsChamber.Node 1.W"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/head_smash_event.h b/engines/titanic/game/head_smash_event.h new file mode 100644 index 0000000000..09fd7a54cc --- /dev/null +++ b/engines/titanic/game/head_smash_event.h @@ -0,0 +1,50 @@ +/* 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_HEAD_SMASH_EVENT_H +#define TITANIC_HEAD_SMASH_EVENT_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CHeadSmashEvent : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *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_HEAD_SMASH_EVENT_H */ diff --git a/engines/titanic/game/head_smash_lever.cpp b/engines/titanic/game/head_smash_lever.cpp new file mode 100644 index 0000000000..d5c2eaf8c4 --- /dev/null +++ b/engines/titanic/game/head_smash_lever.cpp @@ -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. + * + */ + +#include "titanic/game/head_smash_lever.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CHeadSmashLever, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +CHeadSmashLever::CHeadSmashLever() : CBackground(), + _enabled(false), _fieldE4(false), _ticksCount(0) {} + +void CHeadSmashLever::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_enabled, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_ticksCount, indent); + + CBackground::save(file, indent); +} + +void CHeadSmashLever::load(SimpleFile *file) { + file->readNumber(); + _enabled = file->readNumber(); + _fieldE4 = file->readNumber(); + _ticksCount = file->readNumber(); + + CBackground::load(file); +} + +bool CHeadSmashLever::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_enabled) { + playMovie(0, 14, 0); + playSound("z#54.wav"); + int soundHandle = playSound("z#45.wav"); + queueSound("z#49.wav", soundHandle); + _ticksCount = getTicksCount(); + _fieldE4 = true; + } else { + playMovie(0); + playSound("z#56.wav"); + } + + return true; +} + +bool CHeadSmashLever::ActMsg(CActMsg *msg) { + if (msg->_action == "EnableObject") + _enabled = true; + else if (msg->_action == "DisableObject") + _enabled = false; + + return true; +} + +bool CHeadSmashLever::FrameMsg(CFrameMsg *msg) { + if (_fieldE4 && msg->_ticks > (_ticksCount + 750)) { + CActMsg actMsg1("CreatorsChamber.Node 1.S"); + actMsg1.execute("MoveToCreators"); + CActMsg actMsg2("PlayToEnd"); + actMsg2.execute("SmashingStatue"); + + playSound("b#16.wav"); + _fieldE4 = false; + } + + return true; +} + +bool CHeadSmashLever::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_fieldE4) + _ticksCount = getTicksCount(); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/head_smash_lever.h b/engines/titanic/game/head_smash_lever.h new file mode 100644 index 0000000000..e2426b68da --- /dev/null +++ b/engines/titanic/game/head_smash_lever.h @@ -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. + * + */ + +#ifndef TITANIC_HEAD_SMASH_LEVER_H +#define TITANIC_HEAD_SMASH_LEVER_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CHeadSmashLever : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ActMsg(CActMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +public: + bool _enabled; + bool _fieldE4; + int _ticksCount; +public: + CLASSDEF; + CHeadSmashLever(); + + /** + * 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_HEAD_SMASH_LEVER_H */ diff --git a/engines/titanic/game/head_spinner.cpp b/engines/titanic/game/head_spinner.cpp new file mode 100644 index 0000000000..2fb3654c4a --- /dev/null +++ b/engines/titanic/game/head_spinner.cpp @@ -0,0 +1,43 @@ +/* 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/game/head_spinner.h" + +namespace Titanic { + +void CHeadSpinner::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CHeadSpinner::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _value2 = file->readNumber(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/head_spinner.h b/engines/titanic/game/head_spinner.h new file mode 100644 index 0000000000..4456070ee4 --- /dev/null +++ b/engines/titanic/game/head_spinner.h @@ -0,0 +1,50 @@ +/* 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_HEAD_SPINNER_H +#define TITANIC_HEAD_SPINNER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CHeadSpinner : public CGameObject { +public: + int _value1, _value2; +public: + CHeadSpinner() : CGameObject(), _value1(0), _value2(0) {} + 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_HEAD_SPINNER_H */ diff --git a/engines/titanic/game/idle_summoner.cpp b/engines/titanic/game/idle_summoner.cpp new file mode 100644 index 0000000000..5ca3209e28 --- /dev/null +++ b/engines/titanic/game/idle_summoner.cpp @@ -0,0 +1,130 @@ +/* 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/game/idle_summoner.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CIdleSummoner, CGameObject) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +CIdleSummoner::CIdleSummoner() : CGameObject(), _fieldBC(360000), + _fieldC0(60000), _fieldC4(360000), _fieldC8(60000), + _fieldCC(0), _fieldD0(0), _fieldD4(0), _fieldD8(0), _ticks(0) { +} + +void CIdleSummoner::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_fieldCC, indent); + file->writeNumberLine(_fieldD0, indent); + file->writeNumberLine(_fieldD4, indent); + file->writeNumberLine(_fieldD8, indent); + file->writeNumberLine(_ticks, indent); + + CGameObject::save(file, indent); +} + +void CIdleSummoner::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + _fieldC4 = file->readNumber(); + _fieldC8 = file->readNumber(); + _fieldCC = file->readNumber(); + _fieldD0 = file->readNumber(); + _fieldD4 = file->readNumber(); + _fieldD8 = file->readNumber(); + _ticks = file->readNumber(); + + CGameObject::load(file); +} + +bool CIdleSummoner::EnterViewMsg(CEnterViewMsg *msg) { + CActMsg actMsg("Enable"); + actMsg.execute(this); + return true; +} + +bool CIdleSummoner::TimerMsg(CTimerMsg *msg) { + uint nodesCtr = getNodeChangedCtr(); + if (msg->_actionVal == 1 && !petDoorOrBellbotPresent() + && nodesCtr > 0 && _fieldD8) { + if (!compareRoomNameTo("TopOfWell") && !compareRoomNameTo("EmbLobby")) + return true; + + int region = talkGetDialRegion("BellBot", 1); + uint delay = region == 1 ? 15000 : 12000; + uint enterTicks = MIN(getNodeEnterTicks(), _ticks); + + CString name; + uint ticks = getTicksCount() - enterTicks; + if (ticks > delay) { + if (region == 1 || getRandomNumber(1) == 1) { + name = "BellBot"; + } else { + name = "DoorBot"; + } + _fieldD8 = nodesCtr; + + if (getRoom()) { + CSummonBotQueryMsg queryMsg(name); + if (queryMsg.execute(this)) { + CSummonBotMsg summonMsg(name, 1); + summonMsg.execute(this); + } + } + } + } + + return true; +} + +bool CIdleSummoner::ActMsg(CActMsg *msg) { + if (msg->_action == "Enable") { + if (!_fieldD4) + _fieldD4 = addTimer(15000, 15000); + } else if (msg->_action == "Disable") { + if (_fieldD4 > 0) { + stopAnimTimer(_fieldD4); + _fieldD4 = 0; + } + } else if (msg->_action == "DoorbotDismissed" || msg->_action == "BellbotDismissed") { + _ticks = getTicksCount(); + } + + return true; +} + +bool CIdleSummoner::LoadSuccessMsg(CLoadSuccessMsg *msg) { + _ticks = getTicksCount(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/idle_summoner.h b/engines/titanic/game/idle_summoner.h new file mode 100644 index 0000000000..0066694b68 --- /dev/null +++ b/engines/titanic/game/idle_summoner.h @@ -0,0 +1,63 @@ +/* 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_IDLE_SUMMONER_H +#define TITANIC_IDLE_SUMMONER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CIdleSummoner : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool ActMsg(CActMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +public: + int _fieldBC; + int _fieldC0; + int _fieldC4; + int _fieldC8; + int _fieldCC; + int _fieldD0; + int _fieldD4; + int _fieldD8; + uint _ticks; +public: + CIdleSummoner(); + 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_IDLE_SUMMONER_H */ diff --git a/engines/titanic/game/leave_sec_class_state.cpp b/engines/titanic/game/leave_sec_class_state.cpp new file mode 100644 index 0000000000..3e23e3ad1c --- /dev/null +++ b/engines/titanic/game/leave_sec_class_state.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/game/leave_sec_class_state.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CLeaveSecClassState, CGameObject); + +void CLeaveSecClassState::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CLeaveSecClassState::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/leave_sec_class_state.h b/engines/titanic/game/leave_sec_class_state.h new file mode 100644 index 0000000000..0b1e854f57 --- /dev/null +++ b/engines/titanic/game/leave_sec_class_state.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_LEAVE_SEC_CLASS_STATE_H +#define TITANIC_LEAVE_SEC_CLASS_STATE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CLeaveSecClassState : 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_LEAVE_SEC_CLASS_STATE_H */ diff --git a/engines/titanic/game/lemon_dispensor.cpp b/engines/titanic/game/lemon_dispensor.cpp new file mode 100644 index 0000000000..31a04cbeca --- /dev/null +++ b/engines/titanic/game/lemon_dispensor.cpp @@ -0,0 +1,123 @@ +/* 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/game/lemon_dispensor.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLemonDispensor, CBackground) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +bool CLemonDispensor::_isSummer; +int CLemonDispensor::_v2; +int CLemonDispensor::_v3; +CGameObject *CLemonDispensor::_draggingObject; + +CLemonDispensor::CLemonDispensor() : CBackground(), + _fieldE0(0), _origPt(Point(9, 15)), _fieldEC(0) { +} + +void CLemonDispensor::init() { + _isSummer = false; + _v2 = 0; + _v3 = 0; + _draggingObject = nullptr; +} + +void CLemonDispensor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_isSummer, indent); + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_v3, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_origPt.x, indent); + file->writeNumberLine(_origPt.y, indent); + file->writeNumberLine(_fieldEC, indent); + + CBackground::save(file, indent); +} + +void CLemonDispensor::load(SimpleFile *file) { + file->readNumber(); + _isSummer = file->readNumber(); + _v2 = file->readNumber(); + _v3 = file->readNumber(); + _fieldE0 = file->readNumber(); + _origPt.x = file->readNumber(); + _origPt.y = file->readNumber(); + _fieldEC = file->readNumber(); + + CBackground::load(file); +} + +bool CLemonDispensor::FrameMsg(CFrameMsg *msg) { + if (_v2 || !_isSummer) + return true; + + if (!_draggingObject) { + CGameObject *obj = getDraggingObject(); + if (obj && getView() == findView()) { + if (obj->isEquals("Perch")) { + petDisplayMessage(1, "This stick is too short to reach the branches."); + return true; + } + + if (obj->isEquals("LongStick")) + _draggingObject = obj; + } + } + + if (_draggingObject) { + Point pt(_origPt.x + _draggingObject->_bounds.left, + _origPt.y + _draggingObject->_bounds.top); + bool flag = checkPoint(pt, true); + + if (_fieldEC == 0) { + if (flag && ++_v3 > 10) { + CLemonFallsFromTreeMsg lemonMsg(pt); + lemonMsg.execute("Lemon"); + _v2 = 1; + } + } else if (_fieldEC == 1 && !flag) { + _fieldEC = 0; + } + } + + return true; +} + +bool CLemonDispensor::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + _isSummer = msg->_season == "Summer"; + return true; +} + +bool CLemonDispensor::LeaveViewMsg(CLeaveViewMsg *msg) { + _draggingObject = nullptr; + _v3 = 0; + _fieldEC = 0; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/lemon_dispensor.h b/engines/titanic/game/lemon_dispensor.h new file mode 100644 index 0000000000..933e0b6af0 --- /dev/null +++ b/engines/titanic/game/lemon_dispensor.h @@ -0,0 +1,66 @@ +/* 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_LEMON_DISPENSOR_H +#define TITANIC_LEMON_DISPENSOR_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CLemonDispensor : public CBackground { + DECLARE_MESSAGE_MAP; + bool FrameMsg(CFrameMsg *msg); + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +private: + static bool _isSummer; + static int _v2; + static int _v3; + static CGameObject *_draggingObject; + + int _fieldE0; + Point _origPt; + int _fieldEC; +public: + CLASSDEF; + CLemonDispensor(); + + /** + * Initialize statics + */ + static void init(); + + /** + * 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_LEMON_DISPENSOR_H */ diff --git a/engines/titanic/game/light.cpp b/engines/titanic/game/light.cpp new file mode 100644 index 0000000000..65e357047e --- /dev/null +++ b/engines/titanic/game/light.cpp @@ -0,0 +1,152 @@ +/* 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/game/light.h" +#include "titanic/game/television.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLight, CBackground) + ON_MESSAGE(TurnOff) + ON_MESSAGE(LightsMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +CLight::CLight() : CBackground(), _fieldE0(0), _fieldE4(0), + _fieldE8(0), _fieldEC(0), _fieldF0(0), _fieldF4(0), + _fieldF8(0), _fieldFC(0) { +} + +void CLight::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_fieldF4, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_fieldFC, indent); + + CBackground::save(file, indent); +} + +void CLight::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + _fieldF4 = file->readNumber(); + _fieldF8 = file->readNumber(); + _fieldFC = file->readNumber(); + + CBackground::load(file); +} + +bool CLight::TurnOff(CTurnOff *msg) { + setVisible(false); + return true; +} + +bool CLight::LightsMsg(CLightsMsg *msg) { + if ((msg->_flag2 && _fieldE8) || (msg->_flag3 && _fieldEC) + || (msg->_flag1 && _fieldE4) || (msg->_flag4 && _fieldF0)) { + setVisible(true); + } else { + setVisible(false); + } + + return true; +} + +bool CLight::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + // WORKAROUND: Original code doesn't seem to do anything + return true; +} + +bool CLight::TurnOn(CTurnOn *msg) { + setVisible(true); + return true; +} + +bool CLight::StatusChangeMsg(CStatusChangeMsg *msg) { + CPetControl *pet = getPetControl(); + bool flag = pet ? pet->isRoom59706() : false; + + if (_fieldFC == 1 && flag) { + petDisplayMessage(1, "That light appears to be loose."); + playSound("z#144.wav", 70); + } else { + petDisplayMessage(1, "Lumi-Glow(tm) Lights. They glow in the dark!"); + playSound("z#62.wav", 70); + } + + return true; +} + +bool CLight::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CPetControl *pet = getPetControl(); + bool flag = pet ? pet->isRoom59706() : false; + + if (_fieldFC == 1 && flag) { + petDisplayMessage(1, "That light appears to be loose."); + playSound("z#144.wav", 70); + } else { + petDisplayMessage(1, "Lumi-Glow(tm) Lights. They glow in the dark!"); + playSound("z#62.wav", 70); + } + + return true; +} + +bool CLight::ActMsg(CActMsg *msg) { + if (msg->_action == "Eye Removed") + _fieldFC = 0; + + return true; +} + +bool CLight::EnterRoomMsg(CEnterRoomMsg *msg) { + CPetControl *pet = getPetControl(); + setVisible(true); + + if (isEquals("6WTL")) { + CLightsMsg lightsMsg(1, 1, 1, 1); + lightsMsg.execute("1stClassState", CLight::_type, MSGFLAG_SCAN); + + bool flag = pet ? pet->isRoom59706() : false; + if (flag) + CTelevision::_turnOn = true; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/light.h b/engines/titanic/game/light.h new file mode 100644 index 0000000000..68223275e5 --- /dev/null +++ b/engines/titanic/game/light.h @@ -0,0 +1,67 @@ +/* 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_LIGHT_H +#define TITANIC_LIGHT_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CLight : public CBackground { + DECLARE_MESSAGE_MAP; + bool TurnOff(CTurnOff *msg); + bool LightsMsg(CLightsMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool TurnOn(CTurnOn *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ActMsg(CActMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); +private: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _fieldF0; + int _fieldF4; + int _fieldF8; + int _fieldFC; +public: + CLASSDEF; + CLight(); + + /** + * 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_LIGHT_H */ diff --git a/engines/titanic/game/light_switch.cpp b/engines/titanic/game/light_switch.cpp new file mode 100644 index 0000000000..188691033a --- /dev/null +++ b/engines/titanic/game/light_switch.cpp @@ -0,0 +1,152 @@ +/* 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/game/light_switch.h" +#include "titanic/game/light.h" +#include "titanic/game/television.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLightSwitch, CBackground) + ON_MESSAGE(PETUpMsg) + ON_MESSAGE(PETDownMsg) + ON_MESSAGE(PETLeftMsg) + ON_MESSAGE(PETRightMsg) + ON_MESSAGE(PETActivateMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +bool CLightSwitch::_flag; + +CLightSwitch::CLightSwitch() : CBackground(), + _fieldE0(0), _fieldE4(0), _fieldE8(0) { +} + +void CLightSwitch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_flag, indent); + file->writeNumberLine(_fieldE8, indent); + + CBackground::save(file, indent); +} + +void CLightSwitch::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _flag = file->readNumber(); + _fieldE8 = file->readNumber(); + + CBackground::load(file); +} + +bool CLightSwitch::PETUpMsg(CPETUpMsg *msg) { + if (msg->_name == "Light") { + CLightsMsg lightsMsg(true, true, false, false); + lightsMsg.execute("1stClassState", CLight::_type, MSGFLAG_SCAN); + + if (_fieldE8) + CTelevision::_turnOn = true; + } + + return true; +} + +bool CLightSwitch::PETDownMsg(CPETDownMsg *msg) { + if (msg->_name == "Light") { + CLightsMsg lightsMsg(false, false, true, true); + lightsMsg.execute("1stClassState", CLight::_type, MSGFLAG_SCAN); + + if (_fieldE8) + CTelevision::_turnOn = true; + } + + return true; +} + +bool CLightSwitch::PETLeftMsg(CPETLeftMsg *msg) { + if (msg->_name == "Light") { + CLightsMsg lightsMsg(false, true, true, false); + lightsMsg.execute("1stClassState", CLight::_type, MSGFLAG_SCAN); + + if (_fieldE8) + CTelevision::_turnOn = true; + } + + return true; +} + +bool CLightSwitch::PETRightMsg(CPETRightMsg *msg) { + if (msg->_name == "Light") { + CLightsMsg lightsMsg(true, false, false, true); + lightsMsg.execute("1stClassState", CLight::_type, MSGFLAG_SCAN); + + if (_fieldE8) + CTelevision::_turnOn = true; + } + + return true; +} + +bool CLightSwitch::PETActivateMsg(CPETActivateMsg *msg) { + if (msg->_name == "Light") { + if (_flag) { + CTurnOff offMsg; + offMsg.execute("1stClassState", CLight::_type, MSGFLAG_CLASS_DEF | MSGFLAG_SCAN); + + } else { + CTurnOn onMsg; + onMsg.execute("1stClassState", CLight::_type, MSGFLAG_CLASS_DEF | MSGFLAG_SCAN); + _flag = false; + if (_fieldE8) + CTelevision::_turnOn = false; + } + } + + return true; +} + +bool CLightSwitch::EnterViewMsg(CEnterViewMsg *msg) { + petSetRemoteTarget(); + return true; +} + +bool CLightSwitch::LeaveViewMsg(CLeaveViewMsg *msg) { + petClear(); + return true; +} + +bool CLightSwitch::EnterRoomMsg(CEnterRoomMsg *msg) { + _flag = true; + CPetControl *pet = getPetControl(); + if (pet) + _fieldE8 = pet->isRoom59706(); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/light_switch.h b/engines/titanic/game/light_switch.h new file mode 100644 index 0000000000..f8c01dc8b0 --- /dev/null +++ b/engines/titanic/game/light_switch.h @@ -0,0 +1,65 @@ +/* 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_LIGHT_SWITCH_H +#define TITANIC_LIGHT_SWITCH_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CLightSwitch : public CBackground { + DECLARE_MESSAGE_MAP; + bool PETUpMsg(CPETUpMsg *msg); + bool PETDownMsg(CPETDownMsg *msg); + bool PETLeftMsg(CPETLeftMsg *msg); + bool PETRightMsg(CPETRightMsg *msg); + bool PETActivateMsg(CPETActivateMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); +public: + static bool _flag; +private: + int _fieldE0; + int _fieldE4; + int _fieldE8; +public: + CLASSDEF; + CLightSwitch(); + + /** + * 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_LIGHT_SWITCH_H */ diff --git a/engines/titanic/game/little_lift_button.cpp b/engines/titanic/game/little_lift_button.cpp new file mode 100644 index 0000000000..afda4cac1d --- /dev/null +++ b/engines/titanic/game/little_lift_button.cpp @@ -0,0 +1,64 @@ +/* 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/game/little_lift_button.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLittleLiftButton, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CLittleLiftButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CBackground::save(file, indent); +} + +void CLittleLiftButton::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CBackground::load(file); +} + +bool CLittleLiftButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + playMovie(MOVIE_NOTIFY_OBJECT); + playSound("z#60.wav"); + return true; +} + +bool CLittleLiftButton::MovieEndMsg(CMovieEndMsg *msg) { + changeView("SecClassLittleLift.Node 1.N"); + + CRoomItem *room = getRoom(); + if (room) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _value; + statusMsg.execute(room, nullptr, MSGFLAG_SCAN); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/little_lift_button.h b/engines/titanic/game/little_lift_button.h new file mode 100644 index 0000000000..2cbf3b97ff --- /dev/null +++ b/engines/titanic/game/little_lift_button.h @@ -0,0 +1,53 @@ +/* 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_LITTLE_LIFT_BUTTON_H +#define TITANIC_LITTLE_LIFT_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CLittleLiftButton : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + int _value; +public: + CLASSDEF; + CLittleLiftButton() : CBackground(), _value(0) {} + + /** + * 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_LITTLE_LIFT_BUTTON_H */ diff --git a/engines/titanic/game/long_stick_dispenser.cpp b/engines/titanic/game/long_stick_dispenser.cpp new file mode 100644 index 0000000000..08a29f2e4b --- /dev/null +++ b/engines/titanic/game/long_stick_dispenser.cpp @@ -0,0 +1,150 @@ +/* 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/game/long_stick_dispenser.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLongStickDispenser, CGameObject) + ON_MESSAGE(PuzzleSolvedMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CLongStickDispenser::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + file->writeNumberLine(_fieldC4, indent); + + CGameObject::save(file, indent); +} + +void CLongStickDispenser::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + _fieldC4 = file->readNumber(); + + CGameObject::load(file); +} + +bool CLongStickDispenser::PuzzleSolvedMsg(CPuzzleSolvedMsg *msg) { + if (!_fieldBC && !_fieldC4 && !_fieldC0) { + CStatusChangeMsg statusMsg; + statusMsg.execute("ShatterGlass"); + _fieldC0 = 1; + loadFrame(19); + } else if (_fieldC0) { + playSound("z#63.wav"); + petDisplayMessage(1, "'This glass is totally and utterly unbreakable."); + } + + return true; +} + +bool CLongStickDispenser::MovieEndMsg(CMovieEndMsg *msg) { + CPuzzleSolvedMsg puzzleMsg; + puzzleMsg.execute("LongStick"); + _fieldC0 = 1; + return true; +} + +bool CLongStickDispenser::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +bool CLongStickDispenser::EnterRoomMsg(CEnterRoomMsg *msg) { + _fieldC0 = 0; + _fieldC4 = 1; + return true; +} + +bool CLongStickDispenser::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_fieldC0) { + playSound("z#62.wav"); + + switch (_fieldBC) { + case 0: + petDisplayMessage(1, "For emergency long stick, smash glass."); + break; + case 1: + petDisplayMessage(1, "This dispenser has suddenly been fitted with unbreakable glass " + "to prevent unseemly hoarding of sticks."); + break; + default: + break; + } + } + + return true; +} + +bool CLongStickDispenser::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_fieldC0 == 1) { + if (_fieldC4) { + playMovie(19, 38, MOVIE_GAMESTATE); + } else { + playMovie(0, 18, MOVIE_GAMESTATE); + _fieldBC = 1; + } + + _fieldC4 = 1; + _fieldC0 = 0; + } + + return true; +} + +bool CLongStickDispenser::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(true); + loadFrame(38); + _cursorId = CURSOR_HAND; + return true; +} + +bool CLongStickDispenser::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) { + return false; + } else if (_fieldC0 == 1 && _fieldC4 == 1) { + CVisibleMsg visibleMsg(true); + visibleMsg.execute("LongStick"); + CPassOnDragStartMsg dragMsg(msg->_mousePos, 1); + dragMsg.execute("LongStick"); + + msg->_dragItem = getRoot()->findByName("LongStick"); + loadFrame(0); + _fieldC4 = 0; + _cursorId = CURSOR_ARROW; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/long_stick_dispenser.h b/engines/titanic/game/long_stick_dispenser.h new file mode 100644 index 0000000000..be05ef9c65 --- /dev/null +++ b/engines/titanic/game/long_stick_dispenser.h @@ -0,0 +1,63 @@ +/* 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_LONG_STICK_DISPENSER_H +#define TITANIC_LONG_STICK_DISPENSER_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CLongStickDispenser : public CGameObject { + DECLARE_MESSAGE_MAP; + bool PuzzleSolvedMsg(CPuzzleSolvedMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +private: + int _fieldBC; + int _fieldC0; + int _fieldC4; +public: + CLASSDEF; + CLongStickDispenser() : CGameObject(), _fieldBC(0), + _fieldC0(0), _fieldC4(1) {} + + /** + * 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_LONG_STICK_DISPENSER_H */ diff --git a/engines/titanic/game/maitred/maitred_arm_holder.cpp b/engines/titanic/game/maitred/maitred_arm_holder.cpp new file mode 100644 index 0000000000..75d95640d2 --- /dev/null +++ b/engines/titanic/game/maitred/maitred_arm_holder.cpp @@ -0,0 +1,56 @@ +/* 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/game/maitred/maitred_arm_holder.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreDArmHolder, CDropTarget) + ON_MESSAGE(MaitreDArmHolder) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +void CMaitreDArmHolder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CDropTarget::save(file, indent); +} + +void CMaitreDArmHolder::load(SimpleFile *file) { + file->readNumber(); + CDropTarget::load(file); +} + +bool CMaitreDArmHolder::MaitreDArmHolder(CMaitreDArmHolder *msg) { + _fieldF4 = 0; + return true; +} + +bool CMaitreDArmHolder::ActMsg(CActMsg *msg) { + if (msg->_action == "LoseArm") { + _bounds = Rect(); + setVisible(false); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/maitred/maitred_arm_holder.h b/engines/titanic/game/maitred/maitred_arm_holder.h new file mode 100644 index 0000000000..22f961f236 --- /dev/null +++ b/engines/titanic/game/maitred/maitred_arm_holder.h @@ -0,0 +1,50 @@ +/* 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_MAITRED_ARM_HOLDER_H +#define TITANIC_MAITRED_ARM_HOLDER_H + +#include "titanic/core/drop_target.h" + +namespace Titanic { + +class CMaitreDArmHolder : public CDropTarget { + DECLARE_MESSAGE_MAP; + bool MaitreDArmHolder(CMaitreDArmHolder *msg); + bool ActMsg(CActMsg *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_MAITRED_ARM_HOLDER_H */ diff --git a/engines/titanic/game/maitred/maitred_body.cpp b/engines/titanic/game/maitred/maitred_body.cpp new file mode 100644 index 0000000000..4cb12aac8f --- /dev/null +++ b/engines/titanic/game/maitred/maitred_body.cpp @@ -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. + * + */ + +#include "titanic/game/maitred/maitred_body.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreDBody, CMaitreDProdReceptor) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(AnimateMaitreDMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +void CMaitreDBody::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_armed, indent); + CMaitreDProdReceptor::save(file, indent); +} + +void CMaitreDBody::load(SimpleFile *file) { + file->readNumber(); + _armed = file->readNumber(); + CMaitreDProdReceptor::load(file); +} + +bool CMaitreDBody::EnterViewMsg(CEnterViewMsg *msg) { + return true; +} + +bool CMaitreDBody::AnimateMaitreDMsg(CAnimateMaitreDMsg *msg) { + static const char *const ARMED_CLIPS[5] = { + "Talking 1", "Talking 2", "Talking 3", "Talking 4", nullptr + }; + static const char *const UNARMED_CLIPS[5] = { + "Armless Talking 1", "Armless Talking 2", "Armless Talking 3", + "Armless Talking 4", nullptr + }; + + if (!hasActiveMovie()) { + playRandomClip(_armed ? ARMED_CLIPS : UNARMED_CLIPS); + } + + return true; +} + +bool CMaitreDBody::ActMsg(CActMsg *msg) { + if (msg->_action == "LoseArm") { + _armed = false; + loadFrame(262); + playSound("c#75.wav"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/maitred/maitred_body.h b/engines/titanic/game/maitred/maitred_body.h new file mode 100644 index 0000000000..1798958e84 --- /dev/null +++ b/engines/titanic/game/maitred/maitred_body.h @@ -0,0 +1,54 @@ +/* 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_MAITRED_BODY_H +#define TITANIC_MAITRED_BODY_H + +#include "titanic/game/maitred/maitred_prod_receptor.h" + +namespace Titanic { + +class CMaitreDBody : public CMaitreDProdReceptor { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool AnimateMaitreDMsg(CAnimateMaitreDMsg *msg); + bool ActMsg(CActMsg *msg); +private: + bool _armed; +public: + CLASSDEF; + CMaitreDBody() : CMaitreDProdReceptor(), _armed(true) {} + + /** + * 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_MAITRED_BODY_H */ diff --git a/engines/titanic/game/maitred/maitred_legs.cpp b/engines/titanic/game/maitred/maitred_legs.cpp new file mode 100644 index 0000000000..8c0b0db5ea --- /dev/null +++ b/engines/titanic/game/maitred/maitred_legs.cpp @@ -0,0 +1,95 @@ +/* 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/game/maitred/maitred_legs.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreDLegs, CMaitreDProdReceptor) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(AnimateMaitreDMsg) +END_MESSAGE_MAP() + +void CMaitreDLegs::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CMaitreDProdReceptor::save(file, indent); +} + +void CMaitreDLegs::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CMaitreDProdReceptor::load(file); +} + +bool CMaitreDLegs::EnterViewMsg(CEnterViewMsg *msg) { + _flag = true; + loadFrame(0); + return true; +} + +bool CMaitreDLegs::AnimateMaitreDMsg(CAnimateMaitreDMsg *msg) { + static const char *const WIGGLE_CLIPS[4] = { + "Hip Wiggle", "Knee Bend", "Wire Wiggle", nullptr + }; + static const char *const FIGHTING_CLIPS[4] = { + "Fighting 1", "Fighting 2", "Leg Fidget", nullptr + }; + static const char *const ARCING_SOUNDS[9] = { + "MaitreD Arcing 1.wav", "MaitreD Arcing 2.wav", + "MaitreD Arcing 3.wav", "MaitreD Arcing 4.wav", + "MaitreD Arcing 5.wav", "MaitreD Arcing 6.wav", + "MaitreD Arcing 7.wav", "MaitreD Arcing 8.wav", + "MaitreD Arcing 9.wav" + }; + + switch (msg->_value) { + case 0: + if (_flag) { + playRandomClip(FIGHTING_CLIPS); + + if (getRandomNumber(2) != 0) + playSound(ARCING_SOUNDS[getRandomNumber(9)], + 40 + getRandomNumber(30)); + } else { + playClip("Walk Right"); + _flag = true; + } + break; + + case 1: + if (_flag) { + playClip("Walk Left"); + _flag = false; + } else { + playRandomClip(WIGGLE_CLIPS); + } + break; + + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/maitred/maitred_legs.h b/engines/titanic/game/maitred/maitred_legs.h new file mode 100644 index 0000000000..b8a32eef4c --- /dev/null +++ b/engines/titanic/game/maitred/maitred_legs.h @@ -0,0 +1,53 @@ +/* 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_MAITRED_LEGS_H +#define TITANIC_MAITRED_LEGS_H + +#include "titanic/game/maitred/maitred_prod_receptor.h" + +namespace Titanic { + +class CMaitreDLegs : public CMaitreDProdReceptor { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool AnimateMaitreDMsg(CAnimateMaitreDMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CMaitreDLegs() : CMaitreDProdReceptor(), _flag(true) {} + + /** + * 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_MAITRED_LEGS_H */ diff --git a/engines/titanic/game/maitred/maitred_prod_receptor.cpp b/engines/titanic/game/maitred/maitred_prod_receptor.cpp new file mode 100644 index 0000000000..66533a542f --- /dev/null +++ b/engines/titanic/game/maitred/maitred_prod_receptor.cpp @@ -0,0 +1,122 @@ +/* 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/game/maitred/maitred_prod_receptor.h" +#include "titanic/npcs/maitre_d.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreDProdReceptor, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseMoveMsg) + ON_MESSAGE(ProdMaitreDMsg) + ON_MESSAGE(DisableMaitreDProdReceptor) +END_MESSAGE_MAP() + +void CMaitreDProdReceptor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_counter, indent); + file->writeNumberLine(_fieldC4, indent); + + CGameObject::save(file, indent); +} + +void CMaitreDProdReceptor::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _counter = file->readNumber(); + _fieldC4 = file->readNumber(); + + CGameObject::load(file); +} + +bool CMaitreDProdReceptor::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_fieldBC == 2 && static_cast<CGameObject *>(getParent())->hasActiveMovie()) { + return false; + } else { + CProdMaitreDMsg prodMsg(126); + prodMsg.execute(this); + return true; + } +} + +bool CMaitreDProdReceptor::MouseMoveMsg(CMouseMoveMsg *msg) { + if (_fieldBC == 2 && static_cast<CGameObject *>(getParent())->hasActiveMovie()) + return false; + else if (++_counter < 20) + return true; + + _counter = 0; + CProdMaitreDMsg prodMsg(126); + + if (isEquals("Stick")) + prodMsg._value = 121; + else if (isEquals("Hammer")) + prodMsg._value = 122; + else if (isEquals("Lemon")) + prodMsg._value = 123; + else if (isEquals("Chicken")) + prodMsg._value = 124; + else if (isEquals("Perch")) + prodMsg._value = 125; + + CMaitreD *maitreD = static_cast<CMaitreD *>(findRoomObject("MaitreD")); + if (maitreD->_field100 <= 0) + prodMsg.execute(this); + + return true; +} + +bool CMaitreDProdReceptor::ProdMaitreDMsg(CProdMaitreDMsg *msg) { + if (_fieldC4) { + CMaitreD *maitreD = static_cast<CMaitreD *>(findRoomObject("MaitreD")); + if (maitreD->_field100 <= 0) { + CViewItem *view = findView(); + startTalking(maitreD, msg->_value, view); + + switch (_fieldBC) { + case 1: + startTalking(maitreD, 128, view); + break; + case 2: + startTalking(maitreD, 129, view); + break; + case 3: + startTalking(maitreD, 127, view); + break; + default: + startTalking(maitreD, 130, view); + break; + } + } + } + + return true; +} + +bool CMaitreDProdReceptor::DisableMaitreDProdReceptor(CDisableMaitreDProdReceptor *msg) { + _fieldC4 = 0; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/maitred/maitred_prod_receptor.h b/engines/titanic/game/maitred/maitred_prod_receptor.h new file mode 100644 index 0000000000..0b00ce0014 --- /dev/null +++ b/engines/titanic/game/maitred/maitred_prod_receptor.h @@ -0,0 +1,58 @@ +/* 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_MAITRED_PROD_RECEPTOR_H +#define TITANIC_MAITRED_PROD_RECEPTOR_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CMaitreDProdReceptor : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseMoveMsg(CMouseMoveMsg *msg); + bool ProdMaitreDMsg(CProdMaitreDMsg *msg); + bool DisableMaitreDProdReceptor(CDisableMaitreDProdReceptor *msg); +protected: + int _fieldBC; + int _counter; + int _fieldC4; +public: + CLASSDEF; + CMaitreDProdReceptor() : CGameObject(), + _fieldBC(0), _counter(0), _fieldC4(1) {} + + /** + * 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_MAITRED_PROD_RECEPTOR_H */ diff --git a/engines/titanic/game/missiveomat.cpp b/engines/titanic/game/missiveomat.cpp new file mode 100644 index 0000000000..6f47131716 --- /dev/null +++ b/engines/titanic/game/missiveomat.cpp @@ -0,0 +1,330 @@ +/* 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/game/missiveomat.h" +#include "titanic/core/room_item.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMissiveOMat, CGameObject) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(KeyCharMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(MissiveOMatActionMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +CMissiveOMat::CMissiveOMat() : CGameObject(), _mode(1), + _totalMessages(0), _messageNum(0), _personIndex(-1) { + // Load data for the messages, their from and to names + loadArray(_welcomeMessages, "TEXT/MISSIVEOMAT/WELCOME", 3); + loadArray(_messages, "TEXT/MISSIVEOMAT/MESSAGES", 58); + loadArray(_from, "TEXT/MISSIVEOMAT/FROM", 58); + loadArray(_to, "TEXT/MISSIVEOMAT/TO", 58); +} + +void CMissiveOMat::loadArray(CString *arr, const CString &resName, int count) { + Common::SeekableReadStream *s = g_vm->_filesManager->getResource(resName); + for (int idx = 0; idx < count; ++idx) + arr[idx] = readStringFromStream(s); + delete s; +} + +void CMissiveOMat::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_mode, indent); + file->writeNumberLine(_totalMessages, indent); + file->writeNumberLine(_messageNum, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_personIndex, indent); + + CGameObject::save(file, indent); +} + +void CMissiveOMat::load(SimpleFile *file) { + file->readNumber(); + _mode = file->readNumber(); + _totalMessages = file->readNumber(); + _messageNum = file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + _personIndex = file->readNumber(); + + CGameObject::load(file); +} + +bool CMissiveOMat::EnterViewMsg(CEnterViewMsg *msg) { + CMissiveOMatActionMsg actionMsg(9); + actionMsg.execute(this); + return true; +} + +bool CMissiveOMat::KeyCharMsg(CKeyCharMsg *msg) { + CTreeItem *loginControl = findRoom()->findByName("MissiveOMat Login Control"); + CTreeItem *welcome = findRoom()->findByName("MissiveOMat Welcome"); + CTreeItem *scrollUp = findRoom()->findByName("MissiveOMat ScrollUp Button"); + CEditControlMsg editMsg; + + switch (_mode) { + case 1: { + playSound("z#228.wav"); + editMsg._mode = 6; + editMsg._param = msg->_key; + editMsg.execute(loginControl); + + if (editMsg._param == 1000) { + editMsg._mode = 3; + editMsg.execute(loginControl); + + _string1 = editMsg._text; + if (!_string1.empty()) { + loadFrame(2); + _mode = 2; + + editMsg._mode = 1; + editMsg.execute(loginControl); + editMsg._mode = 10; + editMsg._param = 24; + editMsg.execute(loginControl); + } + } + break; + } + + case 2: { + playSound("z#228.wav"); + editMsg._mode = 6; + editMsg._param = msg->_key; + editMsg.execute(loginControl); + + _string2 = editMsg._text; + if (_string1 == "Droot Scraliontis") { + _string1 = "Scraliontis"; + } else if (_string1 == "Antar Brobostigon") { + _string1 = "Brobostigon"; + } else if (_string1 == "colin") { + _string1 = "Leovinus"; + } + + bool flag = false; + if (_string1 == "Leovinus") { + if (_string2 == "Other") { + flag = true; + _personIndex = 0; + } + } else if (_string1 == "Scraliontis") { + if (_string2 == "This") { + flag = true; + _personIndex = 1; + } + } else if (_string1 == "Brobostigon") { + if (_string2 == "That") { + flag = true; + _personIndex = 2; + } + } + + if (flag) { + _mode = 4; + loadFrame(4); + editMsg._mode = 1; + editMsg.execute(loginControl); + + getTextCursor()->hide(); + editMsg._mode = 13; + editMsg.execute(loginControl); + + editMsg._mode = 12; + editMsg.execute(welcome); + + editMsg._mode = 2; + editMsg._text = _welcomeMessages[_personIndex]; + editMsg.execute(welcome); + + editMsg._mode = 12; + editMsg._text = "MissiveOMat OK Button"; + editMsg.execute(welcome); + editMsg.execute(scrollUp); + } else { + _mode = 3; + loadFrame(3); + addTimer(1500); + + editMsg._mode = 1; + editMsg.execute(loginControl); + + getTextCursor()->hide(); + } + break; + } + + default: + break; + } + + return true; +} + +bool CMissiveOMat::TimerMsg(CTimerMsg *msg) { + if (_mode == 3) { + CTreeItem *loginControl = findRoom()->findByName("MissiveOMat Login Control"); + CEditControlMsg editMsg; + editMsg._mode = 10; + editMsg._param = 8; + editMsg.execute(loginControl); + } + + return true; +} + +bool CMissiveOMat::MissiveOMatActionMsg(CMissiveOMatActionMsg *msg) { + CTreeItem *welcome = findByName("MissiveOMat Welcome"); + + switch (msg->_action) { + case MESSAGE_SHOW: { + CTreeItem *btnOk = findRoom()->findByName("MissiveOMat OK Button"); + CTreeItem *btnNext = findRoom()->findByName("MissiveOMat Next Button"); + CTreeItem *btnPrev = findRoom()->findByName("MissiveOMat Prev Button"); + CTreeItem *btnLogout = findRoom()->findByName("MissiveOMat Logout Button"); + + _mode = MESSAGE_5; + CVisibleMsg visibleMsg; + visibleMsg._visible = false; + visibleMsg.execute(btnOk); + visibleMsg._visible = true; + visibleMsg.execute(btnNext); + visibleMsg.execute(btnPrev); + visibleMsg.execute(btnLogout); + + _messageNum = 0; + _totalMessages = 0; + CString *strP = &_messages[_personIndex * 19]; + for (_totalMessages = 0; !strP->empty(); ++strP, ++_totalMessages) + ; + + CMissiveOMatActionMsg actionMsg; + actionMsg._action = REDRAW_MESSAGE; + actionMsg.execute(this); + break; + } + + case NEXT_MESSAGE: + if (_messageNum < (_totalMessages - 1)) { + ++_messageNum; + CMissiveOMatActionMsg actionMsg; + actionMsg._action = REDRAW_MESSAGE; + actionMsg.execute(this); + } + break; + + case PRIOR_MESSAGE: + if (_messageNum > 0) { + --_messageNum; + CMissiveOMatActionMsg actionMsg; + actionMsg._action = REDRAW_MESSAGE; + actionMsg.execute(this); + } + break; + + case MESSAGE_5: { + CMissiveOMatActionMsg actionMsg; + actionMsg._action = MESSAGE_9; + actionMsg.execute(this); + break; + } + + case MESSAGE_DOWN: + if (welcome) + scrollTextDown(); + break; + + case MESSAGE_UP: + if (welcome) + scrollTextUp(); + break; + + case REDRAW_MESSAGE: + if (welcome) { + CString str = CString::format( + "Missive %d of %d.\nFrom: %s\nTo: %s\n\n%s\n", + _messageNum + 1, _totalMessages, _from[_messageNum].c_str(), + _to[_messageNum].c_str(), _messages[_messageNum].c_str()); + + setText(str); + } + break; + + case MESSAGE_9: { + loadFrame(1); + _mode = MESSAGE_NONE; + _personIndex = -1; + + static const char *const WIDGETS[7] = { + "MissiveOMat Login Control", "MissiveOMat OK Button", + "MissiveOMat Next Button", "MissiveOMat Prev Button", + "MissiveOMat Logout Button", "MissiveOMat ScrollDown Button", + "MissiveOMat ScrollUp Button" + }; + CEditControlMsg editMsg; + + for (int idx = 0; idx < 7; ++idx) { + editMsg._mode = 0; + editMsg._param = 12; + editMsg.execute(WIDGETS[idx]); + editMsg._mode = 1; + editMsg.execute(WIDGETS[idx]); + editMsg._mode = 13; + editMsg.execute(WIDGETS[idx]); + } + + editMsg._mode = 12; + editMsg.execute("MissiveOMat Login Control"); + editMsg._mode = 10; + editMsg._param = 8; + editMsg.execute("MissiveOMat Login Control"); + editMsg._mode = 8; + editMsg.execute("MissiveOMat Login Control"); + + _string1.clear(); + _string2.clear(); + break; + } + + default: + break; + } + + return true; +} + +bool CMissiveOMat::LeaveViewMsg(CLeaveViewMsg *msg) { + CEditControlMsg editMsg; + editMsg._mode = 9; + editMsg.execute("MissiveOMat Login Control"); + petShowCursor(); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/missiveomat.h b/engines/titanic/game/missiveomat.h new file mode 100644 index 0000000000..9810fcc403 --- /dev/null +++ b/engines/titanic/game/missiveomat.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_MISSIVEOMAT_H +#define TITANIC_MISSIVEOMAT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +enum MissiveOMatAction { + MESSAGE_NONE = 1, MESSAGE_SHOW = 2, NEXT_MESSAGE = 3, PRIOR_MESSAGE = 4, + MESSAGE_5 = 5, MESSAGE_DOWN = 6, MESSAGE_UP = 7, REDRAW_MESSAGE = 8, + MESSAGE_9 = 9 +}; + +class CMissiveOMat : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool KeyCharMsg(CKeyCharMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool MissiveOMatActionMsg(CMissiveOMatActionMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +private: + CString _welcomeMessages[3]; + CString _messages[58]; + CString _from[58]; + CString _to[58]; +private: + void loadArray(CString *arr, const CString &resName, int count); +public: + int _mode; + int _totalMessages; + int _messageNum; + CString _string1; + CString _string2; + int _personIndex; +public: + CLASSDEF; + CMissiveOMat(); + + /** + * 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_MISSIVEOMAT_H */ diff --git a/engines/titanic/game/missiveomat_button.cpp b/engines/titanic/game/missiveomat_button.cpp new file mode 100644 index 0000000000..b7ad7f8f6f --- /dev/null +++ b/engines/titanic/game/missiveomat_button.cpp @@ -0,0 +1,67 @@ +/* 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/game/missiveomat_button.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMissiveOMatButton, CEditControl) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(MouseDoubleClickMsg) +END_MESSAGE_MAP() + +void CMissiveOMatButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_buttonId, indent); + + CEditControl::save(file, indent); +} + +void CMissiveOMatButton::load(SimpleFile *file) { + file->readNumber(); + _buttonId = file->readNumber(); + + CEditControl::load(file); +} + +bool CMissiveOMatButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CMissiveOMatActionMsg actionMsg; + actionMsg._action = _buttonId; + actionMsg.execute(findRoom()->findByName("MissiveOMat")); + return true; +} + +bool CMissiveOMatButton::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +bool CMissiveOMatButton::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + CMissiveOMatActionMsg actionMsg; + actionMsg._action = _buttonId; + actionMsg.execute(findRoom()->findByName("MissiveOMat")); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/missiveomat_button.h b/engines/titanic/game/missiveomat_button.h new file mode 100644 index 0000000000..6dbfd4cd56 --- /dev/null +++ b/engines/titanic/game/missiveomat_button.h @@ -0,0 +1,54 @@ +/* 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_MISSIVEOMAT_BUTTON_H +#define TITANIC_MISSIVEOMAT_BUTTON_H + +#include "titanic/gfx/edit_control.h" + +namespace Titanic { + +class CMissiveOMatButton : public CEditControl { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); +public: + int _buttonId; +public: + CLASSDEF; + CMissiveOMatButton() : CEditControl(), _buttonId(2) {} + + /** + * 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_MISSIVEOMAT_BUTTON_H */ diff --git a/engines/titanic/game/movie_tester.cpp b/engines/titanic/game/movie_tester.cpp new file mode 100644 index 0000000000..bbd66a9bce --- /dev/null +++ b/engines/titanic/game/movie_tester.cpp @@ -0,0 +1,59 @@ +/* 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/game/movie_tester.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMovieTester, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CMovieTester::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_movieNumFrames, indent); + file->writeNumberLine(_movieFrameNum, indent); + CGameObject::save(file, indent); +} + +void CMovieTester::load(SimpleFile *file) { + file->readNumber(); + _movieNumFrames = file->readNumber(); + _movieFrameNum = file->readNumber(); + CGameObject::load(file); +} + +bool CMovieTester::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (msg->_buttons == MB_RIGHT) { + if (--_movieFrameNum < 0) { + _movieFrameNum = _movieNumFrames - 1; + } + } else { + if (++_movieFrameNum >= _movieNumFrames) + _movieFrameNum = 0; + } + + loadFrame(_movieFrameNum); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/movie_tester.h b/engines/titanic/game/movie_tester.h new file mode 100644 index 0000000000..17a7d489d8 --- /dev/null +++ b/engines/titanic/game/movie_tester.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_MOVIE_TESTER_H +#define TITANIC_MOVIE_TESTER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CMovieTester : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + int _movieNumFrames, _movieFrameNum; +public: + CLASSDEF; + CMovieTester() : CGameObject(), _movieNumFrames(0), _movieFrameNum(0) {} + + /** + * 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_MOVIE_TESTER_H */ diff --git a/engines/titanic/game/music_console_button.cpp b/engines/titanic/game/music_console_button.cpp new file mode 100644 index 0000000000..9cf385e3a7 --- /dev/null +++ b/engines/titanic/game/music_console_button.cpp @@ -0,0 +1,133 @@ +/* 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/game/music_console_button.h" +#include "titanic/core/room_item.h" +#include "titanic/sound/music_handler.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicConsoleButton, CMusicPlayer) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(SetMusicControlsMsg) +END_MESSAGE_MAP() + +void CMusicConsoleButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicPlayer::save(file, indent); +} + +void CMusicConsoleButton::load(SimpleFile *file) { + file->readNumber(); + CMusicPlayer::load(file); +} + +bool CMusicConsoleButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_isActive) { + CStopMusicMsg stopMsg(this); + stopMsg.execute(this); + stopMovie(); + loadFrame(0); + } else { + CStartMusicMsg startMsg(this); + startMsg.execute(this); + playMovie(MOVIE_REPEAT); + + CMusicHasStartedMsg startedMsg; + startedMsg.execute("Music Room Phonograph"); + + if (CMusicRoom::_musicHandler->checkSound(1) + && CMusicRoom::_musicHandler->checkSound(2) + && CMusicRoom::_musicHandler->checkSound(3)) { + CCorrectMusicPlayedMsg correctMsg; + correctMsg.execute(findRoom()); + } + } + + return true; +} + +bool CMusicConsoleButton::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_isActive) { + CStopMusicMsg stopMsg(this); + stopMsg.execute(this); + stopMovie(); + loadFrame(0); + } + + return true; +} + +bool CMusicConsoleButton::SetMusicControlsMsg(CSetMusicControlsMsg *msg) { + CMusicRoom *musicRoom = getMusicRoom(); + CQueryMusicControlSettingMsg queryMsg; + + queryMsg.execute("Bells Mute Control"); + musicRoom->setItem5(BELLS, queryMsg._value == 1 ? 1 : 0); + queryMsg.execute("Bells Pitch Control"); + musicRoom->setItem2(BELLS, queryMsg._value); + queryMsg.execute("Bells Speed Control"); + musicRoom->setItem1(BELLS, queryMsg._value); + queryMsg.execute("Bells Inversion Control"); + musicRoom->setItem4(BELLS, queryMsg._value == 0 ? 1 : 0); + queryMsg.execute("Bells Direction Control"); + musicRoom->setItem3(BELLS, queryMsg._value == 0 ? 1 : 0); + + queryMsg.execute("Snake Mute Control"); + musicRoom->setItem5(SNAKE, queryMsg._value == 1 ? 1 : 0); + queryMsg.execute("Snake Pitch Control"); + musicRoom->setItem2(SNAKE, queryMsg._value); + queryMsg.execute("Snake Speed Control"); + musicRoom->setItem1(SNAKE, queryMsg._value); + queryMsg.execute("Snake Inversion Control"); + musicRoom->setItem4(SNAKE, queryMsg._value == 0 ? 1 : 0); + queryMsg.execute("Snake Direction Control"); + musicRoom->setItem3(SNAKE, queryMsg._value == 0 ? 1 : 0); + + queryMsg.execute("Piano Mute Control"); + musicRoom->setItem5(PIANO, queryMsg._value == 1 ? 1 : 0); + queryMsg.execute("Piano Pitch Control"); + musicRoom->setItem2(PIANO, queryMsg._value); + queryMsg.execute("Piano Speed Control"); + musicRoom->setItem1(PIANO, queryMsg._value); + queryMsg.execute("Piano Inversion Control"); + musicRoom->setItem4(PIANO, queryMsg._value == 0 ? 1 : 0); + queryMsg.execute("Piano Direction Control"); + musicRoom->setItem3(PIANO, queryMsg._value == 0 ? 1 : 0); + + queryMsg.execute("Bass Mute Control"); + musicRoom->setItem5(BASS, queryMsg._value == 1 ? 1 : 0); + queryMsg.execute("Bass Pitch Control"); + musicRoom->setItem2(BASS, queryMsg._value); + queryMsg.execute("Bass Speed Control"); + musicRoom->setItem1(BASS, queryMsg._value); + queryMsg.execute("Bass Inversion Control"); + musicRoom->setItem4(BASS, queryMsg._value == 0 ? 1 : 0); + queryMsg.execute("Bass Direction Control"); + musicRoom->setItem3(BASS, queryMsg._value == 0 ? 1 : 0); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/music_console_button.h b/engines/titanic/game/music_console_button.h new file mode 100644 index 0000000000..80ce719c96 --- /dev/null +++ b/engines/titanic/game/music_console_button.h @@ -0,0 +1,51 @@ +/* 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_MUSIC_CONSOLE_BUTTON_H +#define TITANIC_MUSIC_CONSOLE_BUTTON_H + +#include "titanic/sound/music_player.h" + +namespace Titanic { + +class CMusicConsoleButton : public CMusicPlayer { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool SetMusicControlsMsg(CSetMusicControlsMsg *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_MUSIC_CONSOLE_BUTTON_H */ diff --git a/engines/titanic/game/music_room_phonograph.cpp b/engines/titanic/game/music_room_phonograph.cpp new file mode 100644 index 0000000000..06a35dc4d5 --- /dev/null +++ b/engines/titanic/game/music_room_phonograph.cpp @@ -0,0 +1,41 @@ +/* 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/game/music_room_phonograph.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CMusicRoomPhonograph, CRestaurantPhonograph); + +void CMusicRoomPhonograph::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field118, indent); + CRestaurantPhonograph::save(file, indent); +} + +void CMusicRoomPhonograph::load(SimpleFile *file) { + file->readNumber(); + _field118 = file->readNumber(); + CRestaurantPhonograph::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/music_room_phonograph.h b/engines/titanic/game/music_room_phonograph.h new file mode 100644 index 0000000000..9286861785 --- /dev/null +++ b/engines/titanic/game/music_room_phonograph.h @@ -0,0 +1,51 @@ +/* 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_MUSIC_ROOM_PHONOGRAPH_H +#define TITANIC_MUSIC_ROOM_PHONOGRAPH_H + +#include "titanic/game/restaurant_phonograph.h" + +namespace Titanic { + +class CMusicRoomPhonograph : public CRestaurantPhonograph { + DECLARE_MESSAGE_MAP; +private: + int _field118; +public: + CLASSDEF; + CMusicRoomPhonograph() : CRestaurantPhonograph(), _field118(0) {} + + /** + * 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_MUSIC_ROOM_PHONOGRAPH_H */ diff --git a/engines/titanic/game/music_room_stop_phonograph_button.cpp b/engines/titanic/game/music_room_stop_phonograph_button.cpp new file mode 100644 index 0000000000..dee2c0883e --- /dev/null +++ b/engines/titanic/game/music_room_stop_phonograph_button.cpp @@ -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. + * + */ + +#include "titanic/game/music_room_stop_phonograph_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicRoomStopPhonographButton, CEjectPhonographButton) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +void CMusicRoomStopPhonographButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_ticks, indent); + CEjectPhonographButton::save(file, indent); +} + +void CMusicRoomStopPhonographButton::load(SimpleFile *file) { + file->readNumber(); + _ticks = file->readNumber(); + CEjectPhonographButton::load(file); +} + +bool CMusicRoomStopPhonographButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_ejected) { + loadFrame(1); + playSound(_soundName); + _readyFlag = true; + + CPhonographStopMsg stopMsg; + stopMsg.execute(getParent(), nullptr, MSGFLAG_SCAN); + if (stopMsg._value2) { + _ticks = getTicksCount(); + } else { + CEjectCylinderMsg ejectMsg; + ejectMsg.execute(getParent(), nullptr, MSGFLAG_SCAN); + _ejected = true; + } + } + + return true; +} + +bool CMusicRoomStopPhonographButton::FrameMsg(CFrameMsg *msg) { + if (_readyFlag && _ticks && msg->_ticks >= (_ticks + 100)) { + loadFrame(0); + playSound(_readySoundName); + _ticks = 0; + _readyFlag = false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/music_room_stop_phonograph_button.h b/engines/titanic/game/music_room_stop_phonograph_button.h new file mode 100644 index 0000000000..dd9e8b4bc0 --- /dev/null +++ b/engines/titanic/game/music_room_stop_phonograph_button.h @@ -0,0 +1,53 @@ +/* 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_MUSIC_ROOM_STOP_PHONOGRAPH_BUTTON_H +#define TITANIC_MUSIC_ROOM_STOP_PHONOGRAPH_BUTTON_H + +#include "titanic/game/eject_phonograph_button.h" + +namespace Titanic { + +class CMusicRoomStopPhonographButton : public CEjectPhonographButton { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool FrameMsg(CFrameMsg *msg); +private: + uint _ticks; +public: + CLASSDEF; + CMusicRoomStopPhonographButton() : CEjectPhonographButton(), _ticks(0) {} + + /** + * 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_MUSIC_ROOM_STOP_PHONOGRAPH_BUTTON_H */ diff --git a/engines/titanic/game/music_system_lock.cpp b/engines/titanic/game/music_system_lock.cpp new file mode 100644 index 0000000000..074864e7c3 --- /dev/null +++ b/engines/titanic/game/music_system_lock.cpp @@ -0,0 +1,67 @@ +/* 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/game/music_system_lock.h" +#include "titanic/core/room_item.h" +#include "titanic/carry/carry.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicSystemLock, CDropTarget) + ON_MESSAGE(DropObjectMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CMusicSystemLock::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CDropTarget::save(file, indent); +} + +void CMusicSystemLock::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CDropTarget::load(file); +} + +bool CMusicSystemLock::DropObjectMsg(CDropObjectMsg *msg) { + CTreeItem *key = msg->_item->findByName("Music System Key"); + if (key) { + setVisible(true); + playMovie(MOVIE_NOTIFY_OBJECT); + } + + return true; +} + +bool CMusicSystemLock::MovieEndMsg(CMovieEndMsg *msg) { + CTreeItem *phonograph = findRoom()->findByName("Restaurant Phonograph"); + CQueryPhonographState queryMsg; + queryMsg.execute(phonograph); + CLockPhonographMsg lockMsg(queryMsg._value); + lockMsg.execute(phonograph, nullptr, MSGFLAG_SCAN); + + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/music_system_lock.h b/engines/titanic/game/music_system_lock.h new file mode 100644 index 0000000000..0947915caa --- /dev/null +++ b/engines/titanic/game/music_system_lock.h @@ -0,0 +1,53 @@ +/* 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_MUSIC_SYSTEM_LOCK_H +#define TITANIC_MUSIC_SYSTEM_LOCK_H + +#include "titanic/core/drop_target.h" + +namespace Titanic { + +class CMusicSystemLock : public CDropTarget { + DECLARE_MESSAGE_MAP; + bool DropObjectMsg(CDropObjectMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + int _value; +public: + CLASSDEF; + CMusicSystemLock() : CDropTarget(), _value(0) {} + + /** + * 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_MUSIC_SYSTEM_LOCK_H */ diff --git a/engines/titanic/game/musical_instrument.cpp b/engines/titanic/game/musical_instrument.cpp new file mode 100644 index 0000000000..3bd2e37ccc --- /dev/null +++ b/engines/titanic/game/musical_instrument.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/game/musical_instrument.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CMusicalInstrument, CBackground); + +void CMusicalInstrument::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CMusicalInstrument::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/musical_instrument.h b/engines/titanic/game/musical_instrument.h new file mode 100644 index 0000000000..5d18ed91f0 --- /dev/null +++ b/engines/titanic/game/musical_instrument.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_MUSICAL_INSTRUMENT_H +#define TITANIC_MUSICAL_INSTRUMENT_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CMusicalInstrument : public CBackground { + 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_MUSICAL_INSTRUMENT_H */ diff --git a/engines/titanic/game/nav_helmet.cpp b/engines/titanic/game/nav_helmet.cpp new file mode 100644 index 0000000000..08ff073c26 --- /dev/null +++ b/engines/titanic/game/nav_helmet.cpp @@ -0,0 +1,134 @@ +/* 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/game/nav_helmet.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNavHelmet, CGameObject) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(PETHelmetOnOffMsg) + ON_MESSAGE(PETPhotoOnOffMsg) + ON_MESSAGE(PETStarFieldLockMsg) + ON_MESSAGE(PETSetStarDestinationMsg) +END_MESSAGE_MAP() + +void CNavHelmet::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CGameObject::save(file, indent); +} + +void CNavHelmet::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CGameObject::load(file); +} + +bool CNavHelmet::MovieEndMsg(CMovieEndMsg *msg) { + if (_flag) { + setVisible(false); + + CPetControl *pet = getPetControl(); + if (pet) { + pet->setArea(PET_STARFIELD); + petDisplayMessage(1, "Now would be an excellent opportunity to adjust your viewing apparatus."); + pet->incAreaLocks(); + } + + starFn1(0); + starFn1(12); + } + + return true; +} + +bool CNavHelmet::EnterViewMsg(CEnterViewMsg *msg) { + petSetRemoteTarget(); + return true; +} + +bool CNavHelmet::LeaveViewMsg(CLeaveViewMsg *msg) { + petClear(); + return true; +} + +bool CNavHelmet::PETHelmetOnOffMsg(CPETHelmetOnOffMsg *msg) { + CPetControl *pet = getPetControl(); + + if (_flag) { + _flag = false; + setVisible(true); + starFn1(1); + playMovie(61, 120, MOVIE_NOTIFY_OBJECT); + playSound("a#47.wav"); + playSound("a#48.wav"); + + if (pet) { + pet->decAreaLocks(); + pet->setArea(PET_REMOTE); + } + + dec54(); + } else { + inc54(); + _flag = true; + setVisible(true); + playMovie(0, 60, MOVIE_NOTIFY_OBJECT); + playSound("a#48.wav"); + playSound("a#47.wav"); + } + + return true; +} + +bool CNavHelmet::PETPhotoOnOffMsg(CPETPhotoOnOffMsg *msg) { + if (_flag) + starFn1(9); + + return true; +} + +bool CNavHelmet::PETStarFieldLockMsg(CPETStarFieldLockMsg *msg) { + if (_flag) { + if (msg->_value) { + playSound("a#6.wav"); + starFn1(17); + } else { + playSound("a#5.wav"); + starFn1(18); + } + } + + return true; +} + +bool CNavHelmet::PETSetStarDestinationMsg(CPETSetStarDestinationMsg *msg) { + CActMsg actMsg("SetDestin"); + actMsg.execute("CaptainsWheel"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/nav_helmet.h b/engines/titanic/game/nav_helmet.h new file mode 100644 index 0000000000..c408d05c97 --- /dev/null +++ b/engines/titanic/game/nav_helmet.h @@ -0,0 +1,59 @@ +/* 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_NAV_HELMET_H +#define TITANIC_NAV_HELMET_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CNavHelmet : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool PETHelmetOnOffMsg(CPETHelmetOnOffMsg *msg); + bool PETPhotoOnOffMsg(CPETPhotoOnOffMsg *msg); + bool PETStarFieldLockMsg(CPETStarFieldLockMsg *msg); + bool PETSetStarDestinationMsg(CPETSetStarDestinationMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CNavHelmet() : CGameObject(), _flag(false) {} + + /** + * 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_NAV_HELMET_H */ diff --git a/engines/titanic/game/nav_helmet_off.cpp b/engines/titanic/game/nav_helmet_off.cpp new file mode 100644 index 0000000000..289e9e3f55 --- /dev/null +++ b/engines/titanic/game/nav_helmet_off.cpp @@ -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. + * + */ + +#include "titanic/game/nav_helmet_off.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNavHelmetOff, CNavHelmet) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +void CNavHelmetOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_target, indent); +} + +void CNavHelmetOff::load(SimpleFile *file) { + file->readNumber(); + _target = file->readString(); +} + +bool CNavHelmetOff::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + CDoffNavHelmet doffMsg; + doffMsg.execute(_target); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/nav_helmet_off.h b/engines/titanic/game/nav_helmet_off.h new file mode 100644 index 0000000000..c9529fe8e9 --- /dev/null +++ b/engines/titanic/game/nav_helmet_off.h @@ -0,0 +1,53 @@ +/* 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_NAV_HELMET_OFF_H +#define TITANIC_NAV_HELMET_OFF_H + +#include "titanic/game/nav_helmet.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CNavHelmetOff : public CNavHelmet { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +private: + CString _target; +public: + CLASSDEF; + CNavHelmetOff() : CNavHelmet(), _target("NULL") {} + + /** + * 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_NAV_HELMET_OFF_H */ diff --git a/engines/titanic/game/nav_helmet_on.cpp b/engines/titanic/game/nav_helmet_on.cpp new file mode 100644 index 0000000000..59ceebc4ad --- /dev/null +++ b/engines/titanic/game/nav_helmet_on.cpp @@ -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. + * + */ + +#include "titanic/game/nav_helmet_on.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNavHelmetOn, CNavHelmet) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +void CNavHelmetOn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_target, indent); +} + +void CNavHelmetOn::load(SimpleFile *file) { + file->readNumber(); + _target = file->readString(); +} + +bool CNavHelmetOn::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + CDonNavHelmet donMsg; + donMsg.execute(_target); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/nav_helmet_on.h b/engines/titanic/game/nav_helmet_on.h new file mode 100644 index 0000000000..452637c48a --- /dev/null +++ b/engines/titanic/game/nav_helmet_on.h @@ -0,0 +1,53 @@ +/* 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_NAV_HELMET_ON_H +#define TITANIC_NAV_HELMET_ON_H + +#include "titanic/game/nav_helmet.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CNavHelmetOn : public CNavHelmet { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +private: + CString _target; +public: + CLASSDEF; + CNavHelmetOn() : CNavHelmet(), _target("NULL") {} + + /** + * 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_NAV_HELMET_ON_H */ diff --git a/engines/titanic/game/navigation_computer.cpp b/engines/titanic/game/navigation_computer.cpp new file mode 100644 index 0000000000..49bd252988 --- /dev/null +++ b/engines/titanic/game/navigation_computer.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/game/navigation_computer.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CNavigationComputer, CGameObject); + +void CNavigationComputer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CNavigationComputer::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/navigation_computer.h b/engines/titanic/game/navigation_computer.h new file mode 100644 index 0000000000..27d06c1f27 --- /dev/null +++ b/engines/titanic/game/navigation_computer.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_NAVIGATION_COMPUTER_H +#define TITANIC_NAVIGATION_COMPUTER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CNavigationComputer : 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_NAVIGATION_COMPUTER_H */ diff --git a/engines/titanic/game/no_nut_bowl.cpp b/engines/titanic/game/no_nut_bowl.cpp new file mode 100644 index 0000000000..8c0a95ac9a --- /dev/null +++ b/engines/titanic/game/no_nut_bowl.cpp @@ -0,0 +1,58 @@ +/* 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/game/no_nut_bowl.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNoNutBowl, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(ReplaceBowlAndNutsMsg) + ON_MESSAGE(NutPuzzleMsg) +END_MESSAGE_MAP() + +void CNoNutBowl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CNoNutBowl::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +bool CNoNutBowl::ActMsg(CActMsg *msg) { + return true; +} + +bool CNoNutBowl::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + setVisible(false); + return true; +} + +bool CNoNutBowl::NutPuzzleMsg(CNutPuzzleMsg *msg) { + if (msg->_value == "NutsGone") + setVisible(true); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/no_nut_bowl.h b/engines/titanic/game/no_nut_bowl.h new file mode 100644 index 0000000000..cd8bc65179 --- /dev/null +++ b/engines/titanic/game/no_nut_bowl.h @@ -0,0 +1,51 @@ +/* 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_NO_NUT_BOWL_H +#define TITANIC_NO_NUT_BOWL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CNoNutBowl : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg); + bool NutPuzzleMsg(CNutPuzzleMsg *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_NO_NUT_BOWL_H */ diff --git a/engines/titanic/game/nose_holder.cpp b/engines/titanic/game/nose_holder.cpp new file mode 100644 index 0000000000..ac6c10dafd --- /dev/null +++ b/engines/titanic/game/nose_holder.cpp @@ -0,0 +1,121 @@ +/* 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/game/nose_holder.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNoseHolder, CDropTarget) + ON_MESSAGE(ActMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CNoseHolder::CNoseHolder() : CDropTarget(), _dragObject(nullptr), + _field11C(0) { +} + +void CNoseHolder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field11C, indent); + + CDropTarget::save(file, indent); +} + +void CNoseHolder::load(SimpleFile *file) { + file->readNumber(); + _field11C = file->readNumber(); + + CDropTarget::load(file); +} + +bool CNoseHolder::ActMsg(CActMsg *msg) { + if (msg->_action == "Sneeze" && !_itemName.empty() && _fieldF4) { + CProximity prox; + prox._positioningMode = POSMODE_VECTOR; + playSound("z#35.wav", prox); + + if (getView() == findView()) { + setVisible(true); + playMovie(1, 13, MOVIE_NOTIFY_OBJECT); + } + } + + return true; +} + +bool CNoseHolder::FrameMsg(CFrameMsg *msg) { + if (!_dragObject) { + CGameObject *dragObj = getDraggingObject(); + if (!dragObj) + return false; + + if (!dragObj->isEquals("Feathers") || getView() != findView()) + return false; + + _dragObject = dragObj; + } + + if (_dragObject) { + if (!checkPoint(Point(_dragObject->_bounds.left, + _dragObject->_bounds.top))) { + _field11C = false; + } else if (!_field11C) { + CActMsg actMsg("Sneeze"); + actMsg.execute(this); + _field11C = true; + } + } + + return true; +} + +bool CNoseHolder::LeaveViewMsg(CLeaveViewMsg *msg) { + _field11C = false; + _dragObject = nullptr; + if (_fieldF4) { + loadFrame(_dropFrame); + setVisible(false); + } + + return true; +} + +bool CNoseHolder::MovieEndMsg(CMovieEndMsg *msg) { + if (_fieldF4) { + loadFrame(_dropFrame); + setVisible(false); + } + + return true; +} + +bool CNoseHolder::EnterViewMsg(CEnterViewMsg *msg) { + if (_fieldF4) + setVisible(false); + + return CDropTarget::EnterViewMsg(msg); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/nose_holder.h b/engines/titanic/game/nose_holder.h new file mode 100644 index 0000000000..7b3fbba625 --- /dev/null +++ b/engines/titanic/game/nose_holder.h @@ -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. + * + */ + +#ifndef TITANIC_NOSE_HOLDER_H +#define TITANIC_NOSE_HOLDER_H + +#include "titanic/core/drop_target.h" + +namespace Titanic { + +class CNoseHolder : public CDropTarget { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + CGameObject *_dragObject; + int _field11C; +public: + CLASSDEF; + CNoseHolder(); + + /** + * 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_NOSE_HOLDER_H */ diff --git a/engines/titanic/game/null_port_hole.cpp b/engines/titanic/game/null_port_hole.cpp new file mode 100644 index 0000000000..b1514c7cbf --- /dev/null +++ b/engines/titanic/game/null_port_hole.cpp @@ -0,0 +1,50 @@ +/* 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/game/null_port_hole.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CNullPortHole, CClickResponder); + +CNullPortHole::CNullPortHole() : CClickResponder() { + _message = "For a better view, why not visit the Promenade Deck?"; + _soundName = "b#48.wav"; +} + +void CNullPortHole::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_soundName, indent); + file->writeQuotedLine(_message, indent); + + CClickResponder::save(file, indent); +} + +void CNullPortHole::load(SimpleFile *file) { + file->readNumber(); + _soundName = file->readString(); + _message = file->readString(); + + CClickResponder::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/null_port_hole.h b/engines/titanic/game/null_port_hole.h new file mode 100644 index 0000000000..26564271b9 --- /dev/null +++ b/engines/titanic/game/null_port_hole.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_NULL_PORT_HOLE_H +#define TITANIC_NULL_PORT_HOLE_H + +#include "titanic/core/click_responder.h" + +namespace Titanic { + +class CNullPortHole : public CClickResponder { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CNullPortHole(); + + /** + * 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_NULL_PORT_HOLE_H */ diff --git a/engines/titanic/game/nut_replacer.cpp b/engines/titanic/game/nut_replacer.cpp new file mode 100644 index 0000000000..6b05d1d0e9 --- /dev/null +++ b/engines/titanic/game/nut_replacer.cpp @@ -0,0 +1,53 @@ +/* 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/game/nut_replacer.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNutReplacer, CGameObject) + ON_MESSAGE(ReplaceBowlAndNutsMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CNutReplacer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CNutReplacer::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CNutReplacer::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + setVisible(true); + playMovie(MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT); + return true; +} + +bool CNutReplacer::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/nut_replacer.h b/engines/titanic/game/nut_replacer.h new file mode 100644 index 0000000000..e2eed4e247 --- /dev/null +++ b/engines/titanic/game/nut_replacer.h @@ -0,0 +1,50 @@ +/* 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_NUT_REPLACER_H +#define TITANIC_NUT_REPLACER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CNutReplacer : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg); + bool MovieEndMsg(CMovieEndMsg *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_NUT_REPLACER_H */ diff --git a/engines/titanic/game/parrot/parrot_lobby_controller.cpp b/engines/titanic/game/parrot/parrot_lobby_controller.cpp new file mode 100644 index 0000000000..907e7519b8 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_controller.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/game/parrot/parrot_lobby_controller.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotLobbyController, CParrotLobbyObject) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +void CParrotLobbyController::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CParrotLobbyObject::save(file, indent); +} + +void CParrotLobbyController::load(SimpleFile *file) { + file->readNumber(); + CParrotLobbyObject::load(file); +} + +bool CParrotLobbyController::ActMsg(CActMsg *msg) { + if (msg->_action == "Refresh") + return false; + else if (msg->_action == "GainParrot") + _haveParrot = true; + else if (msg->_action == "LoseParrot") + _haveParrot = false; + else if (msg->_action == "GainPerch") + _havePerch = true; + else if (msg->_action == "LosePerch") + _havePerch = false; + else if (msg->_action == "GainStick") + _haveStick = true; + else if (msg->_action == "LoseStick") + _haveStick = false; + + _flags = 0; + if (_haveParrot) + _flags = 4; + if (_havePerch) + _flags |= 2; + if (_haveStick) + _flags |= 1; + + CActMsg actMsg("Refresh"); + actMsg.execute(findRoom(), CParrotLobbyObject::_type, MSGFLAG_CLASS_DEF | MSGFLAG_SCAN); + actMsg.execute("ParrotLobbyUpdater_TOW"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_lobby_controller.h b/engines/titanic/game/parrot/parrot_lobby_controller.h new file mode 100644 index 0000000000..896a4e19d2 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_controller.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_PARROT_LOBBY_CONTROLLER_H +#define TITANIC_PARROT_LOBBY_CONTROLLER_H + +#include "titanic/game/parrot/parrot_lobby_object.h" + +namespace Titanic { + +class CParrotLobbyController : public CParrotLobbyObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *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_PARROT_LOBBY_CONTROLLER_H */ diff --git a/engines/titanic/game/parrot/parrot_lobby_link_updater.cpp b/engines/titanic/game/parrot/parrot_lobby_link_updater.cpp new file mode 100644 index 0000000000..47311c31f5 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_link_updater.cpp @@ -0,0 +1,115 @@ +/* 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/game/parrot/parrot_lobby_link_updater.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotLobbyLinkUpdater, CParrotLobbyObject) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +/*------------------------------------------------------------------------*/ + +LinkUpdatorEntry::LinkUpdatorEntry() { + Common::fill(&_vals[0], &_vals[8], 0); +} + +void LinkUpdatorEntry::load(Common::SeekableReadStream *s) { + _linkStr = readStringFromStream(s); + for (int idx = 0; idx < 8; ++idx) + _vals[idx] = s->readByte(); +} + +/*------------------------------------------------------------------------*/ + +void LinkUpdatorEntries::load(Common::SeekableReadStream *s, int count) { + resize(count); + for (int idx = 0; idx < count; ++idx) + (*this)[idx].load(s); +} + +/*------------------------------------------------------------------------*/ + +CParrotLobbyLinkUpdater::CParrotLobbyLinkUpdater() : CParrotLobbyObject(), _fieldBC(1) { + Common::SeekableReadStream *s = g_vm->_filesManager->getResource("DATA/PARROT_LOBBY_LINK_UPDATOR"); + _entries[0].load(s, 7); + _entries[1].load(s, 5); + _entries[2].load(s, 6); + _entries[3].load(s, 9); + _entries[4].load(s, 1); + delete s; +} + +void CParrotLobbyLinkUpdater::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CParrotLobbyObject::save(file, indent); +} + +void CParrotLobbyLinkUpdater::load(SimpleFile *file) { + file->readNumber(); + CParrotLobbyObject::load(file); +} + +bool CParrotLobbyLinkUpdater::ActMsg(CActMsg *msg) { + if (msg->_action != "Refresh") + return false; + + CNodeItem *node = findNode(); + LinkUpdatorEntries *entriesP; + if (isEquals("ParrotLobbyUpdater_TOW")) { + entriesP = &_entries[4]; + } else { + if (node->_nodeNumber > 3) + return true; + entriesP = &_entries[node->_nodeNumber]; + } + int count = entriesP->size(); + + for (CTreeItem *item = node->getFirstChild(); item; item = item->scan(node)) { + CLinkItem *link = dynamic_cast<CLinkItem *>(item); + if (!link || count == 0) + continue; + + CString linkName = link->getName(); + char c = linkName.lastChar(); + if (c >= 'a' && c <= 'd') + linkName.deleteLastChar(); + + for (uint idx = 0; idx < entriesP->size(); ++idx) { + const LinkUpdatorEntry &entry = (*entriesP)[idx]; + if (entry._linkStr == linkName) { + int val = entry._vals[CParrotLobbyObject::_flags]; + if (val) + linkName += (char)(0x60 + val); + + link->_name = linkName; + break; + } + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_lobby_link_updater.h b/engines/titanic/game/parrot/parrot_lobby_link_updater.h new file mode 100644 index 0000000000..93db931a53 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_link_updater.h @@ -0,0 +1,68 @@ +/* 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_PARROT_LOBBY_LINK_UPDATER_H +#define TITANIC_PARROT_LOBBY_LINK_UPDATER_H + +#include "common/stream.h" +#include "titanic/game/parrot/parrot_lobby_object.h" + +namespace Titanic { + +struct LinkUpdatorEntry { + CString _linkStr; + int _vals[8]; + + LinkUpdatorEntry(); + void load(Common::SeekableReadStream *s); +}; + +class LinkUpdatorEntries : public Common::Array<LinkUpdatorEntry> { +public: + void load(Common::SeekableReadStream *s, int count); +}; + +class CParrotLobbyLinkUpdater : public CParrotLobbyObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); +private: + LinkUpdatorEntries _entries[5]; +public: + int _fieldBC; +public: + CLASSDEF; + CParrotLobbyLinkUpdater(); + + /** + * 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_PARROT_LOBBY_LINK_UPDATER_H */ diff --git a/engines/titanic/game/parrot/parrot_lobby_object.cpp b/engines/titanic/game/parrot/parrot_lobby_object.cpp new file mode 100644 index 0000000000..06222fd063 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_object.cpp @@ -0,0 +1,61 @@ +/* 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/game/parrot/parrot_lobby_object.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CParrotLobbyObject, CGameObject); + +bool CParrotLobbyObject::_haveParrot; +bool CParrotLobbyObject::_havePerch; +bool CParrotLobbyObject::_haveStick; +int CParrotLobbyObject::_flags; + +void CParrotLobbyObject::init() { + _haveParrot = true; + _havePerch = true; + _haveStick = true; + _flags = 7; +} + +void CParrotLobbyObject::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_haveParrot, indent); + file->writeNumberLine(_havePerch, indent); + file->writeNumberLine(_haveStick, indent); + file->writeNumberLine(_flags, indent); + + CGameObject::save(file, indent); +} + +void CParrotLobbyObject::load(SimpleFile *file) { + file->readNumber(); + _haveParrot = file->readNumber(); + _havePerch = file->readNumber(); + _haveStick = file->readNumber(); + _flags = file->readNumber(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_lobby_object.h b/engines/titanic/game/parrot/parrot_lobby_object.h new file mode 100644 index 0000000000..a210331399 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_object.h @@ -0,0 +1,55 @@ +/* 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_PARROT_LOBBY_OBJECT_H +#define TITANIC_PARROT_LOBBY_OBJECT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CParrotLobbyObject : public CGameObject { + DECLARE_MESSAGE_MAP; +public: + static bool _haveParrot; + static bool _havePerch; + static bool _haveStick; + static int _flags; + + static void init(); +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_PARROT_LOBBY_OBJECT_H */ diff --git a/engines/titanic/game/parrot/parrot_lobby_view_object.cpp b/engines/titanic/game/parrot/parrot_lobby_view_object.cpp new file mode 100644 index 0000000000..1151325676 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_view_object.cpp @@ -0,0 +1,51 @@ +/* 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/game/parrot/parrot_lobby_view_object.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotLobbyViewObject, CParrotLobbyObject) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +void CParrotLobbyViewObject::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CParrotLobbyObject::save(file, indent); +} + +void CParrotLobbyViewObject::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CParrotLobbyObject::load(file); +} + +bool CParrotLobbyViewObject::ActMsg(CActMsg *msg) { + if (msg->_action != "Refresh") + return false; + + setVisible(_flag ? _haveParrot : _haveStick); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_lobby_view_object.h b/engines/titanic/game/parrot/parrot_lobby_view_object.h new file mode 100644 index 0000000000..484d70908e --- /dev/null +++ b/engines/titanic/game/parrot/parrot_lobby_view_object.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_PARROT_LOBBY_VIEW_OBJECT_H +#define TITANIC_PARROT_LOBBY_VIEW_OBJECT_H + +#include "titanic/game/parrot/parrot_lobby_object.h" + +namespace Titanic { + +class CParrotLobbyViewObject : public CParrotLobbyObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); +public: + bool _flag; +public: + CLASSDEF; + CParrotLobbyViewObject() : CParrotLobbyObject(), _flag(true) {} + + /** + * 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_PARROT_LOBBY_VIEW_OBJECT_H */ diff --git a/engines/titanic/game/parrot/parrot_loser.cpp b/engines/titanic/game/parrot/parrot_loser.cpp new file mode 100644 index 0000000000..dc854ee9bd --- /dev/null +++ b/engines/titanic/game/parrot/parrot_loser.cpp @@ -0,0 +1,47 @@ +/* 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/game/parrot/parrot_loser.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotLoser, CGameObject) + ON_MESSAGE(LeaveRoomMsg) +END_MESSAGE_MAP() + +void CParrotLoser::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CParrotLoser::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CParrotLoser::LeaveRoomMsg(CLeaveRoomMsg *msg) { + CActMsg actMsg("FreeParrot"); + actMsg.execute("CarryParrot"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_loser.h b/engines/titanic/game/parrot/parrot_loser.h new file mode 100644 index 0000000000..e03bfb0727 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_loser.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_PARROT_LOSER_H +#define TITANIC_PARROT_LOSER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CParrotLoser : public CGameObject { + DECLARE_MESSAGE_MAP; + bool LeaveRoomMsg(CLeaveRoomMsg *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_PARROT_LOSER_H */ diff --git a/engines/titanic/game/parrot/parrot_nut_bowl_actor.cpp b/engines/titanic/game/parrot/parrot_nut_bowl_actor.cpp new file mode 100644 index 0000000000..9dfc866c0e --- /dev/null +++ b/engines/titanic/game/parrot/parrot_nut_bowl_actor.cpp @@ -0,0 +1,115 @@ +/* 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/game/parrot/parrot_nut_bowl_actor.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotNutBowlActor, CGameObject) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(BowlStateChangeMsg) + ON_MESSAGE(IsEarBowlPuzzleDone) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ReplaceBowlAndNutsMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(NutPuzzleMsg) +END_MESSAGE_MAP() + +CParrotNutBowlActor::CParrotNutBowlActor() : CGameObject(), + _puzzleDone(0), _state(0) { +} + +void CParrotNutBowlActor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_puzzleDone, indent); + file->writeNumberLine(_state, indent); + + CGameObject::save(file, indent); +} + +void CParrotNutBowlActor::load(SimpleFile *file) { + file->readNumber(); + _puzzleDone = file->readNumber(); + _state = file->readNumber(); + + CGameObject::load(file); +} + +bool CParrotNutBowlActor::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + if (!_state) { + CActMsg actMsg("Jiggle"); + actMsg.execute("BowlNutsRustler"); + } + + return true; +} + +bool CParrotNutBowlActor::BowlStateChangeMsg(CBowlStateChangeMsg *msg) { + _state = msg->_state; + if (msg->_state == 3) { + if (!_puzzleDone) { + CReplaceBowlAndNutsMsg replaceMsg; + replaceMsg.execute(findRoom(), nullptr, MSGFLAG_SCAN); + playSound("z#47.wav"); + } + + _puzzleDone = true; + } + + return true; +} + +bool CParrotNutBowlActor::CParrotNutBowlActor::IsEarBowlPuzzleDone(CIsEarBowlPuzzleDone *msg) { + msg->_value = _puzzleDone; + return true; +} + +bool CParrotNutBowlActor::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CParrotNutBowlActor::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + if (!_puzzleDone) + _state = 0; + return true; +} + +bool CParrotNutBowlActor::LeaveViewMsg(CLeaveViewMsg *msg) { + if (!_puzzleDone && _state) { + CReplaceBowlAndNutsMsg replaceMsg; + replaceMsg.execute(findRoom(), nullptr, MSGFLAG_SCAN); + } + + return true; +} + +bool CParrotNutBowlActor::NutPuzzleMsg(CNutPuzzleMsg *msg) { + if (msg->_value == "NutsGone") + _state = 1; + else if (msg->_value == "BowlUnlocked") + _state = 2; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_nut_bowl_actor.h b/engines/titanic/game/parrot/parrot_nut_bowl_actor.h new file mode 100644 index 0000000000..b228c0ea9e --- /dev/null +++ b/engines/titanic/game/parrot/parrot_nut_bowl_actor.h @@ -0,0 +1,59 @@ +/* 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_PARROT_NUT_BOWL_ACTOR_H +#define TITANIC_PARROT_NUT_BOWL_ACTOR_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CParrotNutBowlActor : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool BowlStateChangeMsg(CBowlStateChangeMsg *msg); + bool IsEarBowlPuzzleDone(CIsEarBowlPuzzleDone *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool NutPuzzleMsg(CNutPuzzleMsg *msg); +public: + bool _puzzleDone; + int _state; +public: + CLASSDEF; + CParrotNutBowlActor(); + + /** + * 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_PARROT_NUT_BOWL_ACTOR_H */ diff --git a/engines/titanic/game/parrot/parrot_nut_eater.cpp b/engines/titanic/game/parrot/parrot_nut_eater.cpp new file mode 100644 index 0000000000..751da931ac --- /dev/null +++ b/engines/titanic/game/parrot/parrot_nut_eater.cpp @@ -0,0 +1,97 @@ +/* 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/game/parrot/parrot_nut_eater.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotNutEater, CGameObject) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(ReplaceBowlAndNutsMsg) + ON_MESSAGE(NutPuzzleMsg) + ON_MESSAGE(MovieFrameMsg) +END_MESSAGE_MAP() + +CParrotNutEater::CParrotNutEater() : CGameObject(), _fieldBC(0), + _fieldC0(69), _fieldC4(132), _fieldC8(0), _fieldCC(68) { +} + +void CParrotNutEater::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + + CGameObject::save(file, indent); +} + +void CParrotNutEater::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + + CGameObject::load(file); +} + +bool CParrotNutEater::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(false); + CNutPuzzleMsg nutMsg("NutsGone"); + nutMsg.execute(getRoom(), nullptr, MSGFLAG_SCAN); + + playSound("z#47.wav"); + return true; +} + +bool CParrotNutEater::ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg) { + setVisible(false); + return true; +} + +bool CParrotNutEater::NutPuzzleMsg(CNutPuzzleMsg *msg) { + if (msg->_value == "Jiggle") { + playMovie(MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + movieEvent(68); + movieEvent(132); + playSound("z#215.wav"); + + CTrueTalkTriggerActionMsg triggerMsg; + triggerMsg._param1 = triggerMsg._param2 = 0; + triggerMsg.execute("PerchedParrot"); + } + + return true; +} + +bool CParrotNutEater::MovieFrameMsg(CMovieFrameMsg *msg) { + switch (msg->_frameNumber) { + case 68: + playSound("z#214.wav"); + break; + case 132: + playSound("z#216.wav"); + break; + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_nut_eater.h b/engines/titanic/game/parrot/parrot_nut_eater.h new file mode 100644 index 0000000000..e09ad63947 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_nut_eater.h @@ -0,0 +1,59 @@ +/* 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_PARROT_NUT_EATER_H +#define TITANIC_PARROT_NUT_EATER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CParrotNutEater : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MovieEndMsg(CMovieEndMsg *msg); + bool ReplaceBowlAndNutsMsg(CReplaceBowlAndNutsMsg *msg); + bool NutPuzzleMsg(CNutPuzzleMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); +public: + int _fieldBC; + int _fieldC0; + int _fieldC4; + int _fieldC8; + int _fieldCC; +public: + CLASSDEF; + CParrotNutEater(); + + /** + * 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_CREDITS_H */ diff --git a/engines/titanic/game/parrot/parrot_perch_holder.cpp b/engines/titanic/game/parrot/parrot_perch_holder.cpp new file mode 100644 index 0000000000..d594446219 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_perch_holder.cpp @@ -0,0 +1,82 @@ +/* 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/game/parrot/parrot_perch_holder.h" +#include "titanic/game/cage.h" +#include "titanic/core/project_item.h" +#include "titanic/npcs/parrot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotPerchHolder, CMultiDropTarget) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(DropObjectMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +void CParrotPerchHolder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMultiDropTarget::save(file, indent); +} + +void CParrotPerchHolder::load(SimpleFile *file) { + file->readNumber(); + CMultiDropTarget::load(file); +} + +bool CParrotPerchHolder::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (CParrot::_v1) { + if (CCage::_open) { + petDisplayMessage("You cannot take this because the cage is locked shut."); + } else if (!CParrot::_v4) { + CTrueTalkTriggerActionMsg triggerMsg(280252, 0, 0); + triggerMsg.execute(getRoot(), CParrot::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + } + } + + return true; +} + +bool CParrotPerchHolder::StatusChangeMsg(CStatusChangeMsg *msg) { + _fieldF4 = msg->_newStatus; + return true; +} + +bool CParrotPerchHolder::DropObjectMsg(CDropObjectMsg *msg) { + if (CCage::_open) + return false; + else + return CMultiDropTarget::DropObjectMsg(msg); +} + +bool CParrotPerchHolder::ActMsg(CActMsg *msg) { + if (msg->_action == "FlashCore") { + playMovie(2, 2, 0); + playMovie(1, 1, 0); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_perch_holder.h b/engines/titanic/game/parrot/parrot_perch_holder.h new file mode 100644 index 0000000000..c1fe243476 --- /dev/null +++ b/engines/titanic/game/parrot/parrot_perch_holder.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_PARROT_PERCH_HOLDER_H +#define TITANIC_PARROT_PERCH_HOLDER_H + +#include "titanic/core/multi_drop_target.h" + +namespace Titanic { + +class CParrotPerchHolder : public CMultiDropTarget { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool DropObjectMsg(CDropObjectMsg *msg); + bool ActMsg(CActMsg *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_PARROT_PERCH_HOLDER_H */ diff --git a/engines/titanic/game/parrot/parrot_trigger.cpp b/engines/titanic/game/parrot/parrot_trigger.cpp new file mode 100644 index 0000000000..b7287ebb6a --- /dev/null +++ b/engines/titanic/game/parrot/parrot_trigger.cpp @@ -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. + * + */ + +#include "titanic/game/parrot/parrot_trigger.h" +#include "titanic/npcs/parrot.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotTrigger, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CParrotTrigger::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CParrotTrigger::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +bool CParrotTrigger::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CTrueTalkTriggerActionMsg triggerMsg(_value, 0, 0); + triggerMsg.execute(getRoot(), CParrot::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/parrot_trigger.h b/engines/titanic/game/parrot/parrot_trigger.h new file mode 100644 index 0000000000..6fba77b56d --- /dev/null +++ b/engines/titanic/game/parrot/parrot_trigger.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_PARROT_TRIGGER_H +#define TITANIC_PARROT_TRIGGER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CParrotTrigger : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + int _value; +public: + CLASSDEF; + CParrotTrigger() : CGameObject(), _value(0x446AB) {} + + /** + * 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_PARROT_TRIGGER_H */ diff --git a/engines/titanic/game/parrot/player_meets_parrot.cpp b/engines/titanic/game/parrot/player_meets_parrot.cpp new file mode 100644 index 0000000000..cdb14516bf --- /dev/null +++ b/engines/titanic/game/parrot/player_meets_parrot.cpp @@ -0,0 +1,46 @@ +/* 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/game/parrot/player_meets_parrot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPlayerMeetsParrot, CGameObject) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +void CPlayerMeetsParrot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPlayerMeetsParrot::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CPlayerMeetsParrot::EnterRoomMsg(CEnterRoomMsg *msg) { + stateSet24(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/parrot/player_meets_parrot.h b/engines/titanic/game/parrot/player_meets_parrot.h new file mode 100644 index 0000000000..edae18801f --- /dev/null +++ b/engines/titanic/game/parrot/player_meets_parrot.h @@ -0,0 +1,51 @@ +/* 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_PLAYER_MEETS_PARROT_H +#define TITANIC_PLAYER_MEETS_PARROT_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CPlayerMeetsParrot : public CGameObject { + DECLARE_MESSAGE_MAP; +protected: + bool EnterRoomMsg(CEnterRoomMsg *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_PLAYER_MEETS_PARROT_H */ diff --git a/engines/titanic/game/pet/pet.cpp b/engines/titanic/game/pet/pet.cpp new file mode 100644 index 0000000000..99c9e01eb3 --- /dev/null +++ b/engines/titanic/game/pet/pet.cpp @@ -0,0 +1,69 @@ +/* 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/game/pet/pet.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPET, CGameObject) + ON_MESSAGE(ShowTextMsg) +END_MESSAGE_MAP() + +CPET::CPET() : CGameObject(), _fieldBC(0), _fieldC0(3), + _fieldC4(0), _fieldC8(0), _fieldD8(0), _fieldDC(0) { +} + +void CPET::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeQuotedLine(_string1, indent); + file->writeNumberLine(_fieldD8, indent); + file->writeNumberLine(_fieldDC, indent); + + CGameObject::save(file, indent); +} + +void CPET::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + _fieldC4 = file->readNumber(); + _fieldC8 = file->readNumber(); + _string1 = file->readString(); + _fieldD8 = file->readNumber(); + _fieldDC = file->readNumber(); + + CGameObject::load(file); +} + +bool CPET::ShowTextMsg(CShowTextMsg *msg) { + CPetControl *pet = getPetControl(); + if (pet) + pet->petDisplayMessage(1, msg->_value); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet.h b/engines/titanic/game/pet/pet.h new file mode 100644 index 0000000000..de31a423d0 --- /dev/null +++ b/engines/titanic/game/pet/pet.h @@ -0,0 +1,58 @@ +/* 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_H +#define TITANIC_PET_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPET : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ShowTextMsg(CShowTextMsg *msg); +public: + int _fieldBC; + int _fieldC0; + int _fieldC4; + int _fieldC8; + CString _string1; + int _fieldD8; + int _fieldDC; +public: + CLASSDEF; + CPET(); + + /** + * 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_H */ diff --git a/engines/titanic/game/pet/pet_class1.cpp b/engines/titanic/game/pet/pet_class1.cpp new file mode 100644 index 0000000000..651a8f9ed3 --- /dev/null +++ b/engines/titanic/game/pet/pet_class1.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/game/pet/pet_class1.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPETClass1, CGameObject); + +void CPETClass1::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETClass1::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_class1.h b/engines/titanic/game/pet/pet_class1.h new file mode 100644 index 0000000000..fb7a48b927 --- /dev/null +++ b/engines/titanic/game/pet/pet_class1.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_CLASS1_H +#define TITANIC_PET_CLASS1_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPETClass1 : 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_CLASS1_H */ diff --git a/engines/titanic/game/pet/pet_class2.cpp b/engines/titanic/game/pet/pet_class2.cpp new file mode 100644 index 0000000000..e3e23f62ed --- /dev/null +++ b/engines/titanic/game/pet/pet_class2.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/game/pet/pet_class2.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPETClass2, CGameObject); + +void CPETClass2::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETClass2::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_class2.h b/engines/titanic/game/pet/pet_class2.h new file mode 100644 index 0000000000..c8855c82f3 --- /dev/null +++ b/engines/titanic/game/pet/pet_class2.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_CLASS2_H +#define TITANIC_PET_CLASS2_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPETClass2 : 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_CLASS2_H */ diff --git a/engines/titanic/game/pet/pet_class3.cpp b/engines/titanic/game/pet/pet_class3.cpp new file mode 100644 index 0000000000..7751b994ab --- /dev/null +++ b/engines/titanic/game/pet/pet_class3.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/game/pet/pet_class3.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CPETClass3, CGameObject); + +void CPETClass3::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETClass3::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_class3.h b/engines/titanic/game/pet/pet_class3.h new file mode 100644 index 0000000000..59d8389665 --- /dev/null +++ b/engines/titanic/game/pet/pet_class3.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_CLASS3_H +#define TITANIC_PET_CLASS3_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPETClass3 : 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_CLASS3_H */ diff --git a/engines/titanic/game/pet/pet_lift.cpp b/engines/titanic/game/pet/pet_lift.cpp new file mode 100644 index 0000000000..afa9dd04cd --- /dev/null +++ b/engines/titanic/game/pet/pet_lift.cpp @@ -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. + * + */ + +#include "titanic/game/pet/pet_lift.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETLift, CPETTransport) + ON_MESSAGE(TransportMsg) +END_MESSAGE_MAP() + +void CPETLift::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPETTransport::save(file, indent); +} + +void CPETLift::load(SimpleFile *file) { + file->readNumber(); + CPETTransport::load(file); +} + +bool CPETLift::TransportMsg(CTransportMsg *msg) { + CPetControl *pet = getPetControl(); + if (msg->_value1 != 1) + return false; + + int floorNum = -1; + if (msg->_roomName == "TopOfWell") { + floorNum = 1; + } else if (msg->_roomName == "BottomOfWell") { + floorNum = 39; + } else if (msg->_roomName == "PlayersRoom" && pet) { + int assignedFloor = pet->getAssignedFloorNum(); + if (assignedFloor < 1 || assignedFloor > 39) { + pet->petDisplayMessage("You have not assigned a room to go to."); + floorNum = -1; + } + } + + if (floorNum != -1) { + int elevatorNum = pet ? pet->getRoomsElevatorNum() : 0; + + if ((elevatorNum == 2 || elevatorNum == 4) && floorNum > 27) { + petDisplayMessage("Sorry, this elevator does not go below floor 27."); + } else { + CTrueTalkTriggerActionMsg triggerMsg(2, floorNum, 0); + triggerMsg.execute("Liftbot"); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_lift.h b/engines/titanic/game/pet/pet_lift.h new file mode 100644 index 0000000000..ce3aace1a6 --- /dev/null +++ b/engines/titanic/game/pet/pet_lift.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_LIFT_H +#define TITANIC_PET_LIFT_H + +#include "titanic/game/pet/pet_transport.h" + +namespace Titanic { + +class CPETLift : public CPETTransport { + DECLARE_MESSAGE_MAP; + bool TransportMsg(CTransportMsg *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_LIFT_H */ diff --git a/engines/titanic/game/pet/pet_monitor.cpp b/engines/titanic/game/pet/pet_monitor.cpp new file mode 100644 index 0000000000..2716a81fa8 --- /dev/null +++ b/engines/titanic/game/pet/pet_monitor.cpp @@ -0,0 +1,64 @@ +/* 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/game/pet/pet_monitor.h" +#include "titanic/core/room_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETMonitor, CGameObject) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +void CPETMonitor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETMonitor::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CPETMonitor::EnterRoomMsg(CEnterRoomMsg *msg) { + bool flag = true; + if (msg->_newRoom && msg->_oldRoom) { + CString oldRoomName = msg->_oldRoom->getName(); + CString newRoomName = msg->_newRoom->getName(); + + if (newRoomName == "SgtLobby" && oldRoomName == "SGTState") + flag = false; + } + + if (flag) { + CPetControl *pet = getPetControl(); + if (pet) { + pet->setRoomsRoomNum(0); + pet->resetRoomsHighlight(); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_monitor.h b/engines/titanic/game/pet/pet_monitor.h new file mode 100644 index 0000000000..61d1ba8ab6 --- /dev/null +++ b/engines/titanic/game/pet/pet_monitor.h @@ -0,0 +1,50 @@ +/* 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_MONITOR_H +#define TITANIC_PET_MONITOR_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CPETMonitor : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *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_MONITOR_H */ diff --git a/engines/titanic/game/pet/pet_pellerator.cpp b/engines/titanic/game/pet/pet_pellerator.cpp new file mode 100644 index 0000000000..59516ebcde --- /dev/null +++ b/engines/titanic/game/pet/pet_pellerator.cpp @@ -0,0 +1,61 @@ +/* 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/game/pet/pet_pellerator.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETPellerator, CPETTransport) + ON_MESSAGE(PETActivateMsg) +END_MESSAGE_MAP() + +void CPETPellerator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPETTransport::save(file, indent); +} + +void CPETPellerator::load(SimpleFile *file) { + file->readNumber(); + CPETTransport::load(file); +} + +bool CPETPellerator::PETActivateMsg(CPETActivateMsg *msg) { + CStatusChangeMsg statusMsg; + + if (msg->_name == "PromenadeDeck") + statusMsg._newStatus = 0; + else if (msg->_name == "MusicRoom") + statusMsg._newStatus = 1; + else if (msg->_name == "Bar") + statusMsg._newStatus = 2; + else if (msg->_name == "TopOfWell") + statusMsg._newStatus = 4; + else if (msg->_name == "1stClassRestaurant") + statusMsg._newStatus = 5; + else if (msg->_name == "Arboretum") + statusMsg._newStatus = 6; + + statusMsg.execute("PelleratorObject"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_pellerator.h b/engines/titanic/game/pet/pet_pellerator.h new file mode 100644 index 0000000000..51af6f1bcd --- /dev/null +++ b/engines/titanic/game/pet/pet_pellerator.h @@ -0,0 +1,50 @@ +/* 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_PELLERATOR_H +#define TITANIC_PET_PELLERATOR_H + +#include "titanic/game/pet/pet_transport.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CPETPellerator : public CPETTransport { + DECLARE_MESSAGE_MAP; + bool PETActivateMsg(CPETActivateMsg *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_PELLERATOR_H */ diff --git a/engines/titanic/game/pet/pet_position.cpp b/engines/titanic/game/pet/pet_position.cpp new file mode 100644 index 0000000000..d3d030eb16 --- /dev/null +++ b/engines/titanic/game/pet/pet_position.cpp @@ -0,0 +1,264 @@ +/* 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/game/pet/pet_position.h" +#include "titanic/core/view_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETPosition, CGameObject) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CPETPosition::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETPosition::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CPETPosition::EnterRoomMsg(CEnterRoomMsg *msg) { + if (msg->_newRoom->getName() == "EmbLobby") { + CPetControl *pet = getPetControl(); + if (pet) + pet->setRoomsFloorNum(1); + } + + return true; +} + +bool CPETPosition::EnterViewMsg(CEnterViewMsg *msg) { + CPetControl *pet = getPetControl(); + CString viewStr = msg->_newView->getNodeViewName(); + CString tempStr; + + if (compareRoomNameTo("TopOfWell")) { + tempStr = msg->_newView->getNodeViewName(); + int wellEntry = 0; + + if (tempStr == "Node 25.N") + wellEntry = 1; + else if (tempStr == "Node 24.SE") + wellEntry = 2; + else if (tempStr == "Node 26.N") + wellEntry = 3; + else if (tempStr == "Node 27.N") + wellEntry = 4; + + if (wellEntry != 0) + petSetRoomsWellEntry(wellEntry); + } else if (compareRoomNameTo("1stClassLobby")) { + int roomNum = 0; + + if (viewStr == "Node 2.N") + roomNum = 1; + else if (viewStr == "Node 3.N") + roomNum = 2; + else if (viewStr == "Node 4.N") + roomNum = 3; + else if (viewStr == "Node 5.N") + roomNum = 1; + else if (viewStr == "Node 6.N") + roomNum = 2; + else if (viewStr == "Node 7.N") + roomNum = 3; + + if (pet) { + pet->setRoomsRoomNum(roomNum); + pet->resetRoomsHighlight(); + + int elevatorNum = pet->getRoomsElevatorNum(); + int wellEntry = 0; + + if (viewStr == "Node 10.S") + wellEntry = (elevatorNum == 1 || elevatorNum == 2) ? 1 : 3; + else if (viewStr == "Node 9.S") + wellEntry = (elevatorNum == 1 || elevatorNum == 2) ? 2 : 4; + + if (wellEntry) + petSetRoomsWellEntry(wellEntry); + } + } else if (compareRoomNameTo("2ndClassLobby")) { + int roomNum = 0; + + if (viewStr == "Node 3.N") + roomNum = 1; + else if (viewStr == "Node 4.N") + roomNum = 2; + else if (viewStr == "Node 5.N") + roomNum = 3; + else if (viewStr == "Node 6.N") + roomNum = 4; + + if (pet) { + pet->setRoomsRoomNum(roomNum); + pet->resetRoomsHighlight(); + + int elevatorNum = pet->getRoomsElevatorNum(); + int wellEntry = 0; + + if (viewStr == "Node 8.S") + wellEntry = (elevatorNum == 1 || elevatorNum == 2) ? 1 : 3; + else if (viewStr == "Node 1.S") + wellEntry = (elevatorNum == 1 || elevatorNum == 2) ? 2 : 4; + + if (wellEntry) + petSetRoomsWellEntry(wellEntry); + } + } else if (compareRoomNameTo("SecClassLittleLift")) { + if (pet && viewStr == "Node 1.N") + pet->resetRoomsHighlight(); + } else if (compareRoomNameTo("SGTLittleLift")) { + if (pet && viewStr == "Node 1.N") + pet->resetRoomsHighlight(); + } else if (compareRoomNameTo("SgtLobby")) { + int roomNum = 0; + + if (viewStr == "Node 4.N") + roomNum = 1; + else if (viewStr == "Node 5.N") + roomNum = 2; + else if (viewStr == "Node 6.N") + roomNum = 3; + else if (viewStr == "Node 7.N") + roomNum = 4; + else if (viewStr == "Node 8.N") + roomNum = 5; + else if (viewStr == "Node 9.N") + roomNum = 6; + + if (pet) { + pet->setRooms1CC(1); + pet->setRoomsRoomNum(roomNum); + + if (viewStr == "Node 1.S") + pet->setRoomsWellEntry(pet->getRoomsElevatorNum()); + } + } else if (compareRoomNameTo("BottomOfWell")) { + if (viewStr == "Node 10.E") + petSetRoomsWellEntry(3); + else if (viewStr == "Node 11.W") + petSetRoomsWellEntry(1); + } + + return true; +} + +bool CPETPosition::LeaveViewMsg(CLeaveViewMsg *msg) { + CPetControl *pet = getPetControl(); + CString oldView = msg->_oldView->getName(); + CString newView = msg->_newView->getName(); + + if (pet && newView == "Lift.Node 1.N") { + int elevatorNum = pet->getRoomsElevatorNum(); + + if (oldView == "TopOfWell.Node 25.N") { + pet->setRoomsFloorNum(1); + pet->setRoomsElevatorNum(1); + return true; + } else if (oldView == "TopOfWell.Node 24.SE") { + pet->setRoomsFloorNum(1); + pet->setRoomsElevatorNum(2); + return true; + } else if (oldView == "TopOfWell.Node 26.N") { + pet->setRoomsFloorNum(1); + pet->setRoomsElevatorNum(3); + return true; + } else if (oldView == "TopOfWell.Node 27.N") { + pet->setRoomsFloorNum(1); + pet->setRoomsElevatorNum(4); + return true; + } else if (oldView == "1stClassLobby.Node 10.S") { + switch (elevatorNum) { + case 1: + pet->setRoomsFloorNum(1); + pet->setRoomsElevatorNum(1); + break; + case 2: + pet->setRoomsElevatorNum(1); + break; + default: + pet->setRoomsElevatorNum(3); + break; + } + return true; + } else if (oldView == "1stClassLobby.Node 9.S") { + switch (elevatorNum) { + case 1: + case 2: + pet->setRoomsElevatorNum(2); + break; + default: + pet->setRoomsElevatorNum(4); + break; + } + return true; + } else if (oldView == "2ndClassLobby.Node 8.S") { + switch (elevatorNum) { + case 1: + case 2: + pet->setRoomsElevatorNum(1); + break; + default: + pet->setRoomsElevatorNum(3); + break; + } + return true; + } else if (oldView == "2ndClassLobby.Node 1.S") { + switch (elevatorNum) { + case 1: + case 2: + pet->setRoomsElevatorNum(2); + break; + default: + pet->setRoomsElevatorNum(4); + break; + } + return true; + } else if (oldView == "SgtLobby.Node 1.S") { + return true; + } else if (oldView == "BottomOfWell.Node 10.E" || oldView == "BottomOfWell.Node 11.W") { + pet->setRoomsElevatorNum(1); + return true; + } + } + + CRoomItem *newRoom = msg->_newView->findRoom(); + if (newRoom) { + CString roomName = newRoom->getName(); + if (roomName == "1stClassLobby" || roomName == "2ndClassLobby" || roomName == "SgtLobby") { + if (pet) + pet->resetRoomsHighlight(); + } + } + + return true; +} + + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_position.h b/engines/titanic/game/pet/pet_position.h new file mode 100644 index 0000000000..0cf835f23f --- /dev/null +++ b/engines/titanic/game/pet/pet_position.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_POSITION_H +#define TITANIC_PET_POSITION_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CPETPosition : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *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_POSITION_H */ diff --git a/engines/titanic/game/pet/pet_sentinal.cpp b/engines/titanic/game/pet/pet_sentinal.cpp new file mode 100644 index 0000000000..ac4cbc8418 --- /dev/null +++ b/engines/titanic/game/pet/pet_sentinal.cpp @@ -0,0 +1,66 @@ +/* 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/game/pet/pet_sentinal.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETSentinal, CGameObject) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CPETSentinal::CPETSentinal() : CGameObject(), _elevatorNum(0), + _wellEntry(0), _resetHighlight(0) { +} + +void CPETSentinal::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_elevatorNum, indent); + file->writeNumberLine(_wellEntry, indent); + file->writeNumberLine(_resetHighlight, indent); + CGameObject::save(file, indent); +} + +void CPETSentinal::load(SimpleFile *file) { + file->readNumber(); + _elevatorNum = file->readNumber(); + _wellEntry = file->readNumber(); + _resetHighlight = file->readNumber(); + CGameObject::load(file); +} + +bool CPETSentinal::EnterViewMsg(CEnterViewMsg *msg) { + CPetControl *pet = getPetControl(); + if (pet) { + if (_elevatorNum != -1) + pet->setRoomsElevatorNum(_elevatorNum); + if (_wellEntry) + pet->setRoomsWellEntry(_wellEntry); + if (_resetHighlight) + pet->resetRoomsHighlight(); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_sentinal.h b/engines/titanic/game/pet/pet_sentinal.h new file mode 100644 index 0000000000..150fe4a87e --- /dev/null +++ b/engines/titanic/game/pet/pet_sentinal.h @@ -0,0 +1,54 @@ +/* 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_SENTINAL_H +#define TITANIC_PET_SENTINAL_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPETSentinal : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); +private: + int _elevatorNum; + int _wellEntry; + bool _resetHighlight; +public: + CLASSDEF; + CPETSentinal(); + + /** + * 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_SENTINAL_H */ diff --git a/engines/titanic/game/pet/pet_sounds.cpp b/engines/titanic/game/pet/pet_sounds.cpp new file mode 100644 index 0000000000..c7f3cd3bf8 --- /dev/null +++ b/engines/titanic/game/pet/pet_sounds.cpp @@ -0,0 +1,63 @@ +/* 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/game/pet/pet_sounds.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETSounds, CGameObject) + ON_MESSAGE(PETPlaySoundMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +void CPETSounds::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_ticks, indent); + CGameObject::save(file, indent); +} + +void CPETSounds::load(SimpleFile *file) { + file->readNumber(); + _ticks = file->readNumber(); + CGameObject::load(file); +} + +bool CPETSounds::PETPlaySoundMsg(CPETPlaySoundMsg *msg) { + if (msg->_soundNum == 1) { + playSound("z#65.wav"); + } else if (msg->_soundNum == 2 && stateGet24()) { + uint ticks = getTicksCount(); + if (!_ticks || ticks > (_ticks + 12000)) { + playSound("z#36.wav"); + _ticks = ticks; + } + } + + return true; +} + +bool CPETSounds::LoadSuccessMsg(CLoadSuccessMsg *msg) { + _ticks = 0; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_sounds.h b/engines/titanic/game/pet/pet_sounds.h new file mode 100644 index 0000000000..2262fde916 --- /dev/null +++ b/engines/titanic/game/pet/pet_sounds.h @@ -0,0 +1,54 @@ +/* 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_SOUNDS_H +#define TITANIC_PET_SOUNDS_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CPETSounds : public CGameObject { + DECLARE_MESSAGE_MAP; + bool PETPlaySoundMsg(CPETPlaySoundMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +public: + uint _ticks; +public: + CLASSDEF; + CPETSounds() : CGameObject(), _ticks(0) {} + + /** + * 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_SOUNDS_H */ diff --git a/engines/titanic/game/pet/pet_transition.cpp b/engines/titanic/game/pet/pet_transition.cpp new file mode 100644 index 0000000000..ec10569236 --- /dev/null +++ b/engines/titanic/game/pet/pet_transition.cpp @@ -0,0 +1,60 @@ +/* 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/game/pet/pet_transition.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETTransition, CGameObject) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CPETTransition::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETTransition::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CPETTransition::EnterViewMsg(CEnterViewMsg *msg) { + CPetControl *pet = getPetControl(); + + if (compareRoomNameTo("1stClassLobby") && pet) { + int elevatorNum = pet->getRoomsElevatorNum(); + CString nodeView = msg->_newView->getNodeViewName(); + + if (nodeView == "Node 1.E") { + pet->setRoomsElevatorNum((elevatorNum == 1 || elevatorNum == 2) ? 1 : 3); + } else if (nodeView == "Node 1.W") { + pet->setRoomsElevatorNum((elevatorNum == 1 || elevatorNum == 2) ? 2 : 4); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_transition.h b/engines/titanic/game/pet/pet_transition.h new file mode 100644 index 0000000000..d0fa20ccc5 --- /dev/null +++ b/engines/titanic/game/pet/pet_transition.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_TRANSITION_H +#define TITANIC_PET_TRANSITION_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPETTransition : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *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_TRANSITION_H */ diff --git a/engines/titanic/game/pet/pet_transport.cpp b/engines/titanic/game/pet/pet_transport.cpp new file mode 100644 index 0000000000..a48e70ed01 --- /dev/null +++ b/engines/titanic/game/pet/pet_transport.cpp @@ -0,0 +1,46 @@ +/* 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/game/pet/pet_transport.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPETTransport, CGameObject) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +void CPETTransport::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPETTransport::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CPETTransport::EnterRoomMsg(CEnterRoomMsg *msg) { + petClear(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_transport.h b/engines/titanic/game/pet/pet_transport.h new file mode 100644 index 0000000000..58aefe6743 --- /dev/null +++ b/engines/titanic/game/pet/pet_transport.h @@ -0,0 +1,50 @@ +/* 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_TRANSPORT_H +#define TITANIC_PET_TRANSPORT_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CPETTransport : public CGameObject { + DECLARE_MESSAGE_MAP; + virtual bool EnterRoomMsg(CEnterRoomMsg *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_TRANSPORT_H */ diff --git a/engines/titanic/game/pet/pet_val_base.cpp b/engines/titanic/game/pet/pet_val_base.cpp new file mode 100644 index 0000000000..d77f366436 --- /dev/null +++ b/engines/titanic/game/pet/pet_val_base.cpp @@ -0,0 +1,31 @@ +/* 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/game/pet/pet_val_base.h" + +namespace Titanic { + +CPetValBase::CPetValBase() : _field4(0), _field8(0), + _fieldC(0), _field10(0), _field14(0) { +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet/pet_val_base.h b/engines/titanic/game/pet/pet_val_base.h new file mode 100644 index 0000000000..cdb2808108 --- /dev/null +++ b/engines/titanic/game/pet/pet_val_base.h @@ -0,0 +1,61 @@ +/* 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 + +namespace Titanic { + +class CPetElement { +protected: + int _field4; + int _field8; + int _fieldC; + int _field10; + int _field14; +public: + CPetElement(); + + virtual void proc1() {} + virtual void proc2() {} + virtual void proc3() {} + virtual void proc4() {} + + virtual void proc5() {} + + virtual void proc6() {} + virtual void proc7() {} + virtual void proc8() {} + virtual void proc9() {} + virtual void proc10() {} + virtual void proc11() {} + virtual void proc12() {} + virtual void proc13() {} + virtual void proc14() {} + virtual void proc15() {} + virtual void proc16() {} + virtual void proc17() {} +}; + +} // End of namespace Titanic + +#endif /* TITANIC_pet_element_H */ diff --git a/engines/titanic/game/pet_disabler.cpp b/engines/titanic/game/pet_disabler.cpp new file mode 100644 index 0000000000..c4946fe39f --- /dev/null +++ b/engines/titanic/game/pet_disabler.cpp @@ -0,0 +1,54 @@ +/* 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/game/pet_disabler.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPetDisabler, CGameObject) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CPetDisabler::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_value, indent); + CGameObject::save(file, indent); +} + +void CPetDisabler::load(SimpleFile *file) { + file->readNumber(); + _value = file->readString(); + CGameObject::load(file); +} + +bool CPetDisabler::EnterViewMsg(CEnterViewMsg *msg) { + petLockInput(); + return true; +} + +bool CPetDisabler::LeaveViewMsg(CLeaveViewMsg *msg) { + petUnlockInput(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pet_disabler.h b/engines/titanic/game/pet_disabler.h new file mode 100644 index 0000000000..06e99be49e --- /dev/null +++ b/engines/titanic/game/pet_disabler.h @@ -0,0 +1,53 @@ +/* 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_DISABLER_H +#define TITANIC_PET_DISABLER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPetDisabler : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +public: + CString _value; +public: + CLASSDEF; + CPetDisabler() : CGameObject() {} + + /** + * 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_DISABLER_H */ diff --git a/engines/titanic/game/phonograph.cpp b/engines/titanic/game/phonograph.cpp new file mode 100644 index 0000000000..408cfa3413 --- /dev/null +++ b/engines/titanic/game/phonograph.cpp @@ -0,0 +1,177 @@ +/* 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/game/phonograph.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPhonograph, CMusicPlayer) + ON_MESSAGE(PhonographPlayMsg) + ON_MESSAGE(PhonographStopMsg) + ON_MESSAGE(PhonographRecordMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(MusicHasStartedMsg) +END_MESSAGE_MAP() + +CPhonograph::CPhonograph() : CMusicPlayer(), + _fieldE0(false), _fieldE4(0), _fieldE8(0), _fieldEC(0), + _fieldF0(0), _fieldF4(0) { +} + +void CPhonograph::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_fieldF4, indent); + + CMusicPlayer::save(file, indent); +} + +void CPhonograph::load(SimpleFile *file) { + file->readNumber(); + _string2 = file->readString(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + _fieldF4 = file->readNumber(); + + CMusicPlayer::load(file); +} + +bool CPhonograph::PhonographPlayMsg(CPhonographPlayMsg *msg) { + CQueryCylinderHolderMsg holderMsg; + holderMsg.execute(this); + if (!holderMsg._value2) { + _fieldE0 = false; + return true; + } + + CQueryCylinderMsg cylinderMsg; + cylinderMsg.execute(holderMsg._target); + + if (cylinderMsg._name.empty()) { + _fieldE0 = false; + } else if (cylinderMsg._name.hasPrefix("STMusic")) { + CStartMusicMsg startMsg(this); + startMsg.execute(this); + _fieldE0 = true; + msg->_value = 1; + } else { + stopGlobalSound(0, -1); + playGlobalSound(cylinderMsg._name, -2, true, true, 0); + _fieldE0 = true; + msg->_value = 1; + } + + return true; +} + +bool CPhonograph::PhonographStopMsg(CPhonographStopMsg *msg) { + CQueryCylinderHolderMsg holderMsg; + holderMsg.execute(this); + if (!holderMsg._value2) + return true; + + _fieldE0 = false; + CQueryCylinderMsg cylinderMsg; + cylinderMsg.execute(holderMsg._target); + + if (_fieldE0) { + if (!cylinderMsg._name.empty()) { + if (cylinderMsg._name.hasPrefix("STMusic")) { + CStopMusicMsg stopMsg; + stopMsg.execute(this); + } else { + stopGlobalSound(msg->_value1, -1); + } + msg->_value2 = 1; + } + + if (!msg->_value3) + _fieldE0 = false; + } else if (_fieldE4) { + _fieldE4 = false; + msg->_value2 = 1; + } + + return true; +} + +bool CPhonograph::PhonographRecordMsg(CPhonographRecordMsg *msg) { + if (!_fieldE0 && !_fieldE4 && !_fieldE8) { + CQueryCylinderHolderMsg holderMsg; + holderMsg.execute(this); + + if (holderMsg._value2) { + _fieldE4 = true; + CErasePhonographCylinderMsg eraseMsg; + eraseMsg.execute(holderMsg._target); + } else { + _fieldE4 = false; + } + } + + return true; +} + +bool CPhonograph::EnterRoomMsg(CEnterRoomMsg *msg) { + if (_fieldE0) { + CPhonographPlayMsg playMsg; + playMsg.execute(this); + } + + return true; +} + +bool CPhonograph::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (_fieldE0) { + CPhonographStopMsg stopMsg; + stopMsg._value1 = 1; + stopMsg.execute(this); + } + + return true; +} + +bool CPhonograph::MusicHasStartedMsg(CMusicHasStartedMsg *msg) { + if (_fieldE4) { + CQueryCylinderHolderMsg holderMsg; + holderMsg.execute(this); + if (holderMsg._value2) { + CRecordOntoCylinderMsg recordMsg; + recordMsg.execute(holderMsg._target); + } else { + _fieldE4 = false; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/phonograph.h b/engines/titanic/game/phonograph.h new file mode 100644 index 0000000000..b13a5ea910 --- /dev/null +++ b/engines/titanic/game/phonograph.h @@ -0,0 +1,64 @@ +/* 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_PHONOGRAPH_H +#define TITANIC_PHONOGRAPH_H + +#include "titanic/sound/music_player.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CPhonograph : public CMusicPlayer { + DECLARE_MESSAGE_MAP; + bool PhonographPlayMsg(CPhonographPlayMsg *msg); + bool PhonographStopMsg(CPhonographStopMsg *msg); + bool PhonographRecordMsg(CPhonographRecordMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool MusicHasStartedMsg(CMusicHasStartedMsg *msg); +protected: + CString _string2; + bool _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _fieldF0; + int _fieldF4; +public: + CLASSDEF; + CPhonograph(); + + /** + * 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_MUSIC_CONSOLE_BUTTON_H */ diff --git a/engines/titanic/game/phonograph_lid.cpp b/engines/titanic/game/phonograph_lid.cpp new file mode 100644 index 0000000000..3741749fbf --- /dev/null +++ b/engines/titanic/game/phonograph_lid.cpp @@ -0,0 +1,86 @@ +/* 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/game/phonograph_lid.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPhonographLid, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(LockPhonographMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CPhonographLid::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_open, indent); + CGameObject::save(file, indent); +} + +void CPhonographLid::load(SimpleFile *file) { + file->readNumber(); + _open = file->readNumber(); + CGameObject::load(file); +} + +bool CPhonographLid::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CQueryPhonographState stateMsg; + stateMsg.execute(getParent(), nullptr, MSGFLAG_SCAN); + if (stateMsg._value) { + if (_open) { + CGameObject *lock = dynamic_cast<CGameObject *>(findByName("Music System Lock")); + if (lock) + lock->setVisible(false); + playMovie(0, 27, 0); + } else { + playMovie(27, 55, 0); + } + + _open = !_open; + } else { + petDisplayMessage(0, "This is the restaurant music system. It appears to be locked."); + } + + return true; +} + +bool CPhonographLid::MovieEndMsg(CMovieEndMsg *msg) { + // WORKAROUND: Redundant code in original not included + return true; +} + +bool CPhonographLid::LockPhonographMsg(CLockPhonographMsg *msg) { + _cursorId = msg->_value ? CURSOR_INVALID : CURSOR_ARROW; + return true; +} + +bool CPhonographLid::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_open) { + playMovie(27, 55, MOVIE_GAMESTATE); + _open = false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/phonograph_lid.h b/engines/titanic/game/phonograph_lid.h new file mode 100644 index 0000000000..4e71d70ec2 --- /dev/null +++ b/engines/titanic/game/phonograph_lid.h @@ -0,0 +1,55 @@ +/* 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_PHONOGRAPH_LID_H +#define TITANIC_PHONOGRAPH_LID_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPhonographLid : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool LockPhonographMsg(CLockPhonographMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +private: + bool _open; +public: + CLASSDEF; + CPhonographLid() : CGameObject(), _open(false) {} + + /** + * 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_PHONOGRAPH_LID_H */ diff --git a/engines/titanic/game/pickup/pick_up.cpp b/engines/titanic/game/pickup/pick_up.cpp new file mode 100644 index 0000000000..64d2d1d0d2 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up.cpp @@ -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. + * + */ + +#include "titanic/game/pickup/pick_up.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPickUp, CGameObject) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +void CPickUp::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_enabled, indent); + CGameObject::save(file, indent); +} + +void CPickUp::load(SimpleFile *file) { + file->readNumber(); + _enabled = file->readNumber(); + CGameObject::load(file); +} + +bool CPickUp::StatusChangeMsg(CStatusChangeMsg *msg) { + _enabled = msg->_newStatus == 1; + setVisible(_enabled); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pickup/pick_up.h b/engines/titanic/game/pickup/pick_up.h new file mode 100644 index 0000000000..f5ee06fd32 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up.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_PICK_UP_H +#define TITANIC_PICK_UP_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPickUp : public CGameObject { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); +protected: + bool _enabled; +public: + CLASSDEF; + CPickUp() : CGameObject(), _enabled(false) {} + + /** + * 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_ANNOY_BARBOT_H */ diff --git a/engines/titanic/game/pickup/pick_up_bar_glass.cpp b/engines/titanic/game/pickup/pick_up_bar_glass.cpp new file mode 100644 index 0000000000..9da17b139e --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_bar_glass.cpp @@ -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. + * + */ + +#include "titanic/game/pickup/pick_up_bar_glass.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPickUpBarGlass, CPickUp) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CPickUpBarGlass::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPickUp::save(file, indent); +} + +void CPickUpBarGlass::load(SimpleFile *file) { + file->readNumber(); + CPickUp::load(file); +} + +bool CPickUpBarGlass::StatusChangeMsg(CStatusChangeMsg *msg) { + switch (msg->_newStatus) { + case 0: + setVisible(false); + _enabled = false; + break; + case 1: + setVisible(true); + _enabled = true; + break; + case 2: + setVisible(true); + _enabled = false; + break; + default: + break; + } + + return true; +} + +bool CPickUpBarGlass::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkStartDragging(msg) && _enabled) { + CTurnOn onMsg; + onMsg.execute("BeerGlass"); + CVisibleMsg visibleMsg; + visibleMsg.execute("BeerGlass"); + CPassOnDragStartMsg passMsg(msg->_mousePos, 1, 3); + passMsg.execute("BeerGlass"); + + msg->_dragItem = getRoot()->findByName("BeerGlass"); + + CActMsg actMsg("PlayerTakesGlass"); + actMsg.execute("Barbot"); + return true; + } else { + return false; + } +} + +bool CPickUpBarGlass::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pickup/pick_up_bar_glass.h b/engines/titanic/game/pickup/pick_up_bar_glass.h new file mode 100644 index 0000000000..d273d96170 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_bar_glass.h @@ -0,0 +1,51 @@ +/* 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_PICK_UP_BAR_GLASS_H +#define TITANIC_PICK_UP_BAR_GLASS_H + +#include "titanic/game/pickup/pick_up.h" + +namespace Titanic { + +class CPickUpBarGlass : public CPickUp { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *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_PICK_UP_BAR_GLASS_H */ diff --git a/engines/titanic/game/pickup/pick_up_hose.cpp b/engines/titanic/game/pickup/pick_up_hose.cpp new file mode 100644 index 0000000000..d07088cefd --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_hose.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 "titanic/game/pickup/pick_up_hose.h" +#include "titanic/core/project_item.h" +#include "titanic/core/room_item.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPickUpHose, CPickUp) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +bool CPickUpHose::_v1; + +void CPickUpHose::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_target, indent); + file->writeNumberLine(_v1, indent); + + CPickUp::save(file, indent); +} + +void CPickUpHose::load(SimpleFile *file) { + file->readNumber(); + _target = file->readString(); + _v1 = file->readNumber(); + + CPickUp::load(file); +} + +bool CPickUpHose::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) + return true; + if (_v1 || !_enabled) + return false; + + CViewItem *view = getView(); + if (view) { + _v1 = true; + CRoomItem *room = locateRoom("Arboretum"); + CTreeItem *hose = room ? room->findByName("Hose") : nullptr; + + if (!hose) { + room = locateRoom("FrozenArboretum"); + if (room) + hose = room->findByName("Hose"); + } + + if (hose) { + CVisibleMsg visibleMsg; + visibleMsg.execute(this); + moveUnder(view); + + CPassOnDragStartMsg passMsg(msg->_mousePos, 1); + passMsg.execute("Hose"); + + msg->_dragItem = getRoot()->findByName("Hose"); + _cursorId = CURSOR_IGNORE; + + CActMsg actMsg("PlayerGetsHose"); + actMsg.execute(_target); + } + } + + return true; +} + +bool CPickUpHose::StatusChangeMsg(CStatusChangeMsg *msg) { + _cursorId = msg->_newStatus == 1 ? CURSOR_HAND : CURSOR_IGNORE; + return true; +} + +bool CPickUpHose::EnterViewMsg(CEnterViewMsg *msg) { + _cursorId = CURSOR_IGNORE; + return true; +} + +bool CPickUpHose::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return _enabled; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pickup/pick_up_hose.h b/engines/titanic/game/pickup/pick_up_hose.h new file mode 100644 index 0000000000..2ad7c2a583 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_hose.h @@ -0,0 +1,56 @@ +/* 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_PICK_UP_HOSE_H +#define TITANIC_PICK_UP_HOSE_H + +#include "titanic/game/pickup/pick_up.h" + +namespace Titanic { + +class CPickUpHose : public CPickUp { + DECLARE_MESSAGE_MAP; + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + static bool _v1; + + CString _target; +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_PICK_UP_HOSE_H */ diff --git a/engines/titanic/game/pickup/pick_up_lemon.cpp b/engines/titanic/game/pickup/pick_up_lemon.cpp new file mode 100644 index 0000000000..5109c36304 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_lemon.cpp @@ -0,0 +1,62 @@ +/* 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/game/pickup/pick_up_lemon.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPickUpLemon, CPickUp) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CPickUpLemon::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPickUp::save(file, indent); +} + +void CPickUpLemon::load(SimpleFile *file) { + file->readNumber(); + CPickUp::load(file); +} + +bool CPickUpLemon::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CPickUpLemon::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg)) + return true; + if (!_enabled) + return false; + + CVisibleMsg visibleMsg; + visibleMsg.execute("Lemon"); + CPassOnDragStartMsg passMsg(msg->_mousePos, 1); + passMsg.execute("Lemon"); + + msg->_dragItem = getRoot()->findByName("Lemon"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pickup/pick_up_lemon.h b/engines/titanic/game/pickup/pick_up_lemon.h new file mode 100644 index 0000000000..c196acdeaf --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_lemon.h @@ -0,0 +1,50 @@ +/* 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_PICK_UP_LEMON_H +#define TITANIC_PICK_UP_LEMON_H + +#include "titanic/game/pickup/pick_up.h" + +namespace Titanic { + +class CPickUpLemon : public CPickUp { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *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_PICK_UP_LEMON_H */ diff --git a/engines/titanic/game/pickup/pick_up_speech_centre.cpp b/engines/titanic/game/pickup/pick_up_speech_centre.cpp new file mode 100644 index 0000000000..5e99c0a3b7 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_speech_centre.cpp @@ -0,0 +1,73 @@ +/* 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/game/pickup/pick_up_speech_centre.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPickUpSpeechCentre, CPickUp) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CPickUpSpeechCentre::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPickUp::save(file, indent); +} + +void CPickUpSpeechCentre::load(SimpleFile *file) { + file->readNumber(); + CPickUp::load(file); +} + +bool CPickUpSpeechCentre::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CPickUpSpeechCentre::StatusChangeMsg(CStatusChangeMsg *msg) { + _enabled = msg->_newStatus == 1; + return true; +} + +bool CPickUpSpeechCentre::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (checkStartDragging(msg)) { + if (_enabled) { + CVisibleMsg visibleMsg; + visibleMsg.execute("SpeechCentre"); + CPassOnDragStartMsg passMsg(msg->_mousePos, 1); + passMsg.execute("SpeechCentre"); + + msg->_dragItem = getRoot()->findByName("SpeechCentre"); + + CActMsg actMsg("PlayerGetsSpeechCentre"); + actMsg.execute("SeasonalAdjust"); + } else { + petDisplayMessage("You can't pick this up on account of it being stuck to the branch."); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pickup/pick_up_speech_centre.h b/engines/titanic/game/pickup/pick_up_speech_centre.h new file mode 100644 index 0000000000..81ee0b5d77 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_speech_centre.h @@ -0,0 +1,51 @@ +/* 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_PICK_UP_SPEECH_CENTRE_H +#define TITANIC_PICK_UP_SPEECH_CENTRE_H + +#include "titanic/game/pickup/pick_up.h" + +namespace Titanic { + +class CPickUpSpeechCentre : public CPickUp { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *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_PICK_UP_SPEECH_CENTRE_H */ diff --git a/engines/titanic/game/pickup/pick_up_vis_centre.cpp b/engines/titanic/game/pickup/pick_up_vis_centre.cpp new file mode 100644 index 0000000000..baf1763d09 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_vis_centre.cpp @@ -0,0 +1,60 @@ +/* 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/game/pickup/pick_up_vis_centre.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPickUpVisCentre, CPickUp) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +void CPickUpVisCentre::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPickUp::save(file, indent); +} + +void CPickUpVisCentre::load(SimpleFile *file) { + file->readNumber(); + CPickUp::load(file); +} + + +bool CPickUpVisCentre::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +bool CPickUpVisCentre::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (!checkStartDragging(msg) || !_enabled) + return false; + + setVisible(false); + CVisibleMsg visibleMsg; + visibleMsg.execute("VisionCentre"); + msg->execute("VisionCentre"); + CActMsg actMsg("PlayerTakesVisCentre"); + actMsg.execute("Barbot"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/pickup/pick_up_vis_centre.h b/engines/titanic/game/pickup/pick_up_vis_centre.h new file mode 100644 index 0000000000..a5f59211d3 --- /dev/null +++ b/engines/titanic/game/pickup/pick_up_vis_centre.h @@ -0,0 +1,50 @@ +/* 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_PICK_UP_VIS_CENTRE_H +#define TITANIC_PICK_UP_VIS_CENTRE_H + +#include "titanic/game/pickup/pick_up.h" + +namespace Titanic { + +class CPickUpVisCentre : public CPickUp { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *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_PICK_UP_VIS_CENTRE_H */ diff --git a/engines/titanic/game/placeholder/bar_shelf_vis_centre.cpp b/engines/titanic/game/placeholder/bar_shelf_vis_centre.cpp new file mode 100644 index 0000000000..6e5037f237 --- /dev/null +++ b/engines/titanic/game/placeholder/bar_shelf_vis_centre.cpp @@ -0,0 +1,67 @@ +/* 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/game/placeholder/bar_shelf_vis_centre.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBarShelfVisCentre, CPlaceHolder) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CBarShelfVisCentre::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CPlaceHolder::save(file, indent); +} + +void CBarShelfVisCentre::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CPlaceHolder::load(file); +} + +bool CBarShelfVisCentre::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_flag) { + CActMsg actMsg("ClickOnVision"); + actMsg.execute("Barbot"); + addTimer(3000); + _flag = true; + } + + return true; +} + +bool CBarShelfVisCentre::TimerMsg(CTimerMsg *msg) { + _flag = false; + return true; +} + +bool CBarShelfVisCentre::EnterViewMsg(CEnterViewMsg *msg) { + _flag = false; + return true; +} + + +} // End of namespace Titanic diff --git a/engines/titanic/game/placeholder/bar_shelf_vis_centre.h b/engines/titanic/game/placeholder/bar_shelf_vis_centre.h new file mode 100644 index 0000000000..8ad3dcb8d1 --- /dev/null +++ b/engines/titanic/game/placeholder/bar_shelf_vis_centre.h @@ -0,0 +1,54 @@ +/* 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_BAR_SHELF_VIS_CENTRE_H +#define TITANIC_BAR_SHELF_VIS_CENTRE_H + +#include "titanic/game/placeholder/place_holder.h" + +namespace Titanic { + +class CBarShelfVisCentre : public CPlaceHolder { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CBarShelfVisCentre() : CPlaceHolder(), _flag(false) {} + + /** + * 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_BAR_SHELF_VIS_CENTRE_H */ diff --git a/engines/titanic/game/placeholder/lemon_on_bar.cpp b/engines/titanic/game/placeholder/lemon_on_bar.cpp new file mode 100644 index 0000000000..e9cf6a309a --- /dev/null +++ b/engines/titanic/game/placeholder/lemon_on_bar.cpp @@ -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. + * + */ + +#include "titanic/game/placeholder/lemon_on_bar.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLemonOnBar, CPlaceHolder) + ON_MESSAGE(VisibleMsg) +END_MESSAGE_MAP() + +void CLemonOnBar::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_lemonPos, indent); + CPlaceHolder::save(file, indent); +} + +void CLemonOnBar::load(SimpleFile *file) { + file->readNumber(); + _lemonPos = file->readPoint(); + CPlaceHolder::load(file); +} + +bool CLemonOnBar::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + if (msg->_visible) + setPosition(_lemonPos); + else + setPosition(Point(0, 0)); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/placeholder/lemon_on_bar.h b/engines/titanic/game/placeholder/lemon_on_bar.h new file mode 100644 index 0000000000..c6512ced67 --- /dev/null +++ b/engines/titanic/game/placeholder/lemon_on_bar.h @@ -0,0 +1,51 @@ +/* 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_LEMON_ON_BAR_H +#define TITANIC_LEMON_ON_BAR_H + +#include "titanic/game/placeholder/place_holder.h" + +namespace Titanic { + +class CLemonOnBar : public CPlaceHolder { + DECLARE_MESSAGE_MAP; + bool VisibleMsg(CVisibleMsg *msg); +private: + Point _lemonPos; +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_LEMON_ON_BAR_H */ diff --git a/engines/titanic/game/placeholder/place_holder.cpp b/engines/titanic/game/placeholder/place_holder.cpp new file mode 100644 index 0000000000..ae42cabc29 --- /dev/null +++ b/engines/titanic/game/placeholder/place_holder.cpp @@ -0,0 +1,46 @@ +/* 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/game/placeholder/place_holder.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPlaceHolder, CGameObject) + ON_MESSAGE(VisibleMsg) +END_MESSAGE_MAP() + +void CPlaceHolder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CPlaceHolder::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CPlaceHolder::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/placeholder/place_holder.h b/engines/titanic/game/placeholder/place_holder.h new file mode 100644 index 0000000000..b1aa041710 --- /dev/null +++ b/engines/titanic/game/placeholder/place_holder.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_PLACE_HOLDER_H +#define TITANIC_PLACE_HOLDER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPlaceHolder : public CGameObject { + DECLARE_MESSAGE_MAP; + bool VisibleMsg(CVisibleMsg *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_PLACE_HOLDER_H */ diff --git a/engines/titanic/game/placeholder/tv_on_bar.cpp b/engines/titanic/game/placeholder/tv_on_bar.cpp new file mode 100644 index 0000000000..e17fb7833d --- /dev/null +++ b/engines/titanic/game/placeholder/tv_on_bar.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/game/placeholder/tv_on_bar.h" + +namespace Titanic { + +void CTVOnBar::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_pos1, indent); + CPlaceHolder::save(file, indent); +} + +void CTVOnBar::load(SimpleFile *file) { + file->readNumber(); + _pos1 = file->readPoint(); + CPlaceHolder::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/placeholder/tv_on_bar.h b/engines/titanic/game/placeholder/tv_on_bar.h new file mode 100644 index 0000000000..bb5381fb5d --- /dev/null +++ b/engines/titanic/game/placeholder/tv_on_bar.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_TV_ON_BAR_H +#define TITANIC_TV_ON_BAR_H + +#include "titanic/game/placeholder/place_holder.h" + +namespace Titanic { + +class CTVOnBar : public CPlaceHolder { +private: + Point _pos1; +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_TV_ON_BAR_H */ diff --git a/engines/titanic/game/play_music_button.cpp b/engines/titanic/game/play_music_button.cpp new file mode 100644 index 0000000000..93416911b8 --- /dev/null +++ b/engines/titanic/game/play_music_button.cpp @@ -0,0 +1,78 @@ +/* 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/game/play_music_button.h" +#include "titanic/sound/music_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPlayMusicButton, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +void CPlayMusicButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + file->writeNumberLine(_ticks, indent); + + CBackground::save(file, indent); +} + +void CPlayMusicButton::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + _ticks = file->readNumber(); + + CBackground::load(file); +} + +bool CPlayMusicButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CMusicRoom *musicRoom = getMusicRoom(); + if (_flag) { + musicRoom->stopMusic(); + stopMovie(); + loadFrame(0); + _flag = false; + } else { + musicRoom->startMusic(100); + playMovie(MOVIE_REPEAT); + _ticks = getTicksCount(); + _flag = true; + } + + return true; +} + +bool CPlayMusicButton::FrameMsg(CFrameMsg *msg) { + if (_flag && !CMusicRoom::_musicHandler->isBusy()) { + CMusicRoom *musicRoom = getMusicRoom(); + musicRoom->stopMusic(); + stopMovie(); + loadFrame(0); + _flag = false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/play_music_button.h b/engines/titanic/game/play_music_button.h new file mode 100644 index 0000000000..824b372bf9 --- /dev/null +++ b/engines/titanic/game/play_music_button.h @@ -0,0 +1,54 @@ +/* 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_PLAY_MUSIC_BUTTON_H +#define TITANIC_PLAY_MUSIC_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CPlayMusicButton : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool FrameMsg(CFrameMsg *msg); +public: + bool _flag; + uint _ticks; +public: + CLASSDEF; + CPlayMusicButton() : CBackground(), _flag(false), _ticks(0) {} + + /** + * 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_PLAY_MUSIC_BUTTON_H */ diff --git a/engines/titanic/game/play_on_act.cpp b/engines/titanic/game/play_on_act.cpp new file mode 100644 index 0000000000..9c368c335d --- /dev/null +++ b/engines/titanic/game/play_on_act.cpp @@ -0,0 +1,58 @@ +/* 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/game/play_on_act.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPlayOnAct, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CPlayOnAct::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CPlayOnAct::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +bool CPlayOnAct::ActMsg(CActMsg *msg) { + if (msg->_action == "PlayMovie") { + setVisible(true); + playMovie(0); + } else if (msg->_action == "PlayToEnd") { + setVisible(true); + playMovie(MOVIE_GAMESTATE); + } + + return true; +} + +bool CPlayOnAct::LeaveViewMsg(CLeaveViewMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/play_on_act.h b/engines/titanic/game/play_on_act.h new file mode 100644 index 0000000000..72615f2fc4 --- /dev/null +++ b/engines/titanic/game/play_on_act.h @@ -0,0 +1,50 @@ +/* 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_PLAY_ON_ACT_H +#define TITANIC_PLAY_ON_ACT_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CPlayOnAct : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *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_PLAY_ON_ACT_H */ diff --git a/engines/titanic/game/port_hole.cpp b/engines/titanic/game/port_hole.cpp new file mode 100644 index 0000000000..25807b1b1d --- /dev/null +++ b/engines/titanic/game/port_hole.cpp @@ -0,0 +1,95 @@ +/* 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/game/port_hole.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPortHole, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CPortHole::CPortHole() : CGameObject(), _open(false), + _closeSoundName("b#47.wav"), _openSoundName("b#46.wav") { +} + +void CPortHole::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_open, indent); + file->writeQuotedLine(_closeSoundName, indent); + file->writeQuotedLine(_openSoundName, indent); + + CGameObject::save(file, indent); +} + +void CPortHole::load(SimpleFile *file) { + file->readNumber(); + _open = file->readNumber(); + _closeSoundName = file->readString(); + _openSoundName = file->readString(); + + CGameObject::load(file); +} + +bool CPortHole::ActMsg(CActMsg *msg) { + if (msg->_action == "TogglePortHole") { + if (_open) { + playMovie(14, 26, MOVIE_NOTIFY_OBJECT); + playSound(_closeSoundName); + _open = false; + } else { + setVisible(true); + playMovie(1, 13, 0); + playSound(_openSoundName); + _open = true; + } + } + + return true; +} + +bool CPortHole::MovieEndMsg(CMovieEndMsg *msg) { + _open = false; + setVisible(false); + return true; +} + +bool CPortHole::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_open) { + playSound(_closeSoundName); + playMovie(14, 26, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _open = false; + } + + return true; +} + +bool CPortHole::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(false); + _open = false; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/port_hole.h b/engines/titanic/game/port_hole.h new file mode 100644 index 0000000000..9f1997a517 --- /dev/null +++ b/engines/titanic/game/port_hole.h @@ -0,0 +1,56 @@ +/* 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_PORT_HOLE_H +#define TITANIC_PORT_HOLE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CPortHole : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + bool _open; + CString _closeSoundName, _openSoundName; +public: + CLASSDEF; + CPortHole(); + + /** + * 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_PORT_HOLE_H */ diff --git a/engines/titanic/game/record_phonograph_button.cpp b/engines/titanic/game/record_phonograph_button.cpp new file mode 100644 index 0000000000..f022957dbb --- /dev/null +++ b/engines/titanic/game/record_phonograph_button.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/game/record_phonograph_button.h" + +namespace Titanic { + +void CRecordPhonographButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CBackground::save(file, indent); +} + +void CRecordPhonographButton::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/record_phonograph_button.h b/engines/titanic/game/record_phonograph_button.h new file mode 100644 index 0000000000..3383c01e31 --- /dev/null +++ b/engines/titanic/game/record_phonograph_button.h @@ -0,0 +1,50 @@ +/* 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_RECORD_PHONOGRAPH_BUTTON_H +#define TITANIC_RECORD_PHONOGRAPH_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CRecordPhonographButton : public CBackground { +public: + int _value; +public: + CLASSDEF; + CRecordPhonographButton() : CBackground(), _value(0) {} + + /** + * 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_RECORD_PHONOGRAPH_BUTTON_H */ diff --git a/engines/titanic/game/replacement_ear.cpp b/engines/titanic/game/replacement_ear.cpp new file mode 100644 index 0000000000..1f9960365d --- /dev/null +++ b/engines/titanic/game/replacement_ear.cpp @@ -0,0 +1,37 @@ +/* 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/game/replacement_ear.h" + +namespace Titanic { + +void CReplacementEar::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CReplacementEar::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/replacement_ear.h b/engines/titanic/game/replacement_ear.h new file mode 100644 index 0000000000..0d282b7fb4 --- /dev/null +++ b/engines/titanic/game/replacement_ear.h @@ -0,0 +1,47 @@ +/* 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_REPLACEMENT_EAR_H +#define TITANIC_REPLACEMENT_EAR_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CReplacementEar : public CBackground { +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_REPLACEMENT_EAR_H */ diff --git a/engines/titanic/game/reserved_table.cpp b/engines/titanic/game/reserved_table.cpp new file mode 100644 index 0000000000..a600190709 --- /dev/null +++ b/engines/titanic/game/reserved_table.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/game/reserved_table.h" + +namespace Titanic { + +void CReservedTable::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CReservedTable::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _value2 = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/reserved_table.h b/engines/titanic/game/reserved_table.h new file mode 100644 index 0000000000..a3532c7d14 --- /dev/null +++ b/engines/titanic/game/reserved_table.h @@ -0,0 +1,50 @@ +/* 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_RESERVED_TABLE_H +#define TITANIC_RESERVED_TABLE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CReservedTable : public CGameObject { +public: + int _value1, _value2; +public: + CLASSDEF; + CReservedTable() : CGameObject(), _value1(0), _value2(0) {} + + /** + * 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_RESERVED_TABLE_H */ diff --git a/engines/titanic/game/restaurant_cylinder_holder.cpp b/engines/titanic/game/restaurant_cylinder_holder.cpp new file mode 100644 index 0000000000..d70009f151 --- /dev/null +++ b/engines/titanic/game/restaurant_cylinder_holder.cpp @@ -0,0 +1,58 @@ +/* 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/game/restaurant_cylinder_holder.h" + +namespace Titanic { + +CRestaurantCylinderHolder::CRestaurantCylinderHolder() : CDropTarget(), + _field118(0), _field11C(0), _field12C(0), _field130(0), + _string6("z#61.wav"), _field140(1) { +} + +void CRestaurantCylinderHolder::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field118, indent); + file->writeNumberLine(_field11C, indent); + file->writeQuotedLine(_string5, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_field130, indent); + file->writeQuotedLine(_string6, indent); + file->writeNumberLine(_field140, indent); + + CDropTarget::save(file, indent); +} + +void CRestaurantCylinderHolder::load(SimpleFile *file) { + file->readNumber(); + _field118 = file->readNumber(); + _field11C = file->readNumber(); + _string5 = file->readString(); + _field12C = file->readNumber(); + _field130 = file->readNumber(); + _string6 = file->readString(); + _field140 = file->readNumber(); + + CDropTarget::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/restaurant_cylinder_holder.h b/engines/titanic/game/restaurant_cylinder_holder.h new file mode 100644 index 0000000000..3aa979b0a5 --- /dev/null +++ b/engines/titanic/game/restaurant_cylinder_holder.h @@ -0,0 +1,56 @@ +/* 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_RESTAURANT_CYLINDER_HOLDER_H +#define TITANIC_RESTAURANT_CYLINDER_HOLDER_H + +#include "titanic/core/drop_target.h" + +namespace Titanic { + +class CRestaurantCylinderHolder : public CDropTarget { +private: + int _field118; + int _field11C; + CString _string5; + int _field12C; + int _field130; + CString _string6; + int _field140; +public: + CLASSDEF; + CRestaurantCylinderHolder(); + + /** + * 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_RESTAURANT_CYLINDER_HOLDER_H */ diff --git a/engines/titanic/game/restaurant_phonograph.cpp b/engines/titanic/game/restaurant_phonograph.cpp new file mode 100644 index 0000000000..83a4ac3e71 --- /dev/null +++ b/engines/titanic/game/restaurant_phonograph.cpp @@ -0,0 +1,51 @@ +/* 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/game/restaurant_phonograph.h" + +namespace Titanic { + +CRestaurantPhonograph::CRestaurantPhonograph() : CPhonograph(), + _fieldF8(1), _field114(0) {} + +void CRestaurantPhonograph::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeQuotedLine(_string2, indent); + file->writeQuotedLine(_string3, indent); + + file->writeNumberLine(_field114, indent); + + CPhonograph::save(file, indent); +} + +void CRestaurantPhonograph::load(SimpleFile *file) { + file->readNumber(); + _fieldF8 = file->readNumber(); + _string2 = file->readString(); + _string3 = file->readString(); + _field114 = file->readNumber(); + + CPhonograph::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/restaurant_phonograph.h b/engines/titanic/game/restaurant_phonograph.h new file mode 100644 index 0000000000..710a2edd73 --- /dev/null +++ b/engines/titanic/game/restaurant_phonograph.h @@ -0,0 +1,53 @@ +/* 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_RESTAURANT_PHONOGRAPH_H +#define TITANIC_RESTAURANT_PHONOGRAPH_H + +#include "titanic/game/phonograph.h" + +namespace Titanic { + +class CRestaurantPhonograph : public CPhonograph { +private: + int _fieldF8; + CString _string2; + CString _string3; + int _field114; +public: + CLASSDEF; + CRestaurantPhonograph(); + + /** + * 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_RESTAURANT_PHONOGRAPH_H */ diff --git a/engines/titanic/game/sauce_dispensor.cpp b/engines/titanic/game/sauce_dispensor.cpp new file mode 100644 index 0000000000..8dc818d917 --- /dev/null +++ b/engines/titanic/game/sauce_dispensor.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/game/sauce_dispensor.h" + +namespace Titanic { + +CSauceDispensor::CSauceDispensor() : CBackground(), + _fieldEC(0), _fieldF0(0), _field104(0), _field108(0) { +} + +void CSauceDispensor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string3, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + file->writePoint(_pos1, indent); + file->writePoint(_pos2, indent); + file->writeNumberLine(_field104, indent); + file->writeNumberLine(_field108, indent); + + CBackground::save(file, indent); +} + +void CSauceDispensor::load(SimpleFile *file) { + file->readNumber(); + _string3 = file->readString(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + _pos1 = file->readPoint(); + _pos2 = file->readPoint(); + _field104 = file->readNumber(); + _field108 = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sauce_dispensor.h b/engines/titanic/game/sauce_dispensor.h new file mode 100644 index 0000000000..aa177050d5 --- /dev/null +++ b/engines/titanic/game/sauce_dispensor.h @@ -0,0 +1,56 @@ +/* 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_SAUCE_DISPENSOR_H +#define TITANIC_SAUCE_DISPENSOR_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CSauceDispensor : public CBackground { +public: + CString _string3; + int _fieldEC; + int _fieldF0; + Point _pos1; + Point _pos2; + int _field104; + int _field108; +public: + CLASSDEF; + CSauceDispensor(); + + /** + * 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_SAUCE_DISPENSOR_H */ diff --git a/engines/titanic/game/search_point.cpp b/engines/titanic/game/search_point.cpp new file mode 100644 index 0000000000..f60a3132b7 --- /dev/null +++ b/engines/titanic/game/search_point.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/game/search_point.h" + +namespace Titanic { + +void CSearchPoint::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CSearchPoint::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/search_point.h b/engines/titanic/game/search_point.h new file mode 100644 index 0000000000..3c5639b104 --- /dev/null +++ b/engines/titanic/game/search_point.h @@ -0,0 +1,50 @@ +/* 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_SEARCH_POINT_H +#define TITANIC_SEARCH_POINT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSearchPoint : public CGameObject { +public: + int _value; +public: + CLASSDEF; + CSearchPoint() : CGameObject(), _value(2) {} + + /** + * 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_SEARCH_POINT_H */ diff --git a/engines/titanic/game/season_background.cpp b/engines/titanic/game/season_background.cpp new file mode 100644 index 0000000000..1c63f3d892 --- /dev/null +++ b/engines/titanic/game/season_background.cpp @@ -0,0 +1,51 @@ +/* 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/game/season_background.h" + +namespace Titanic { + +CSeasonBackground::CSeasonBackground() : CBackground(), + _fieldE0(0), _fieldE4(0), _fieldE8(46), _fieldEC(0) { +} + +void CSeasonBackground::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + + CBackground::save(file, indent); +} + +void CSeasonBackground::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/season_background.h b/engines/titanic/game/season_background.h new file mode 100644 index 0000000000..f0fd2cdc63 --- /dev/null +++ b/engines/titanic/game/season_background.h @@ -0,0 +1,53 @@ +/* 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_SEASON_BACKGROUND_H +#define TITANIC_SEASON_BACKGROUND_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CSeasonBackground : public CBackground { +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; +public: + CLASSDEF; + CSeasonBackground(); + + /** + * 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_SEASON_BACKGROUND_H */ diff --git a/engines/titanic/game/season_barrel.cpp b/engines/titanic/game/season_barrel.cpp new file mode 100644 index 0000000000..9594396885 --- /dev/null +++ b/engines/titanic/game/season_barrel.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/game/season_barrel.h" + +namespace Titanic { + +void CSeasonBarrel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + + CBackground::save(file, indent); +} + +void CSeasonBarrel::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/season_barrel.h b/engines/titanic/game/season_barrel.h new file mode 100644 index 0000000000..f77864599d --- /dev/null +++ b/engines/titanic/game/season_barrel.h @@ -0,0 +1,51 @@ +/* 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_SEASON_BARREL_H +#define TITANIC_SEASON_BARREL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CSeasonBarrel : public CBackground { +public: + int _fieldE0; + int _fieldE4; +public: + CLASSDEF; + CSeasonBarrel() : CBackground(), _fieldE0(0), _fieldE4(7) {} + + /** + * 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_SEASON_BARREL_H */ diff --git a/engines/titanic/game/seasonal_adjustment.cpp b/engines/titanic/game/seasonal_adjustment.cpp new file mode 100644 index 0000000000..33a0ae89c5 --- /dev/null +++ b/engines/titanic/game/seasonal_adjustment.cpp @@ -0,0 +1,43 @@ +/* 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/game/seasonal_adjustment.h" + +namespace Titanic { + +void CSeasonalAdjustment::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + + CBackground::save(file, indent); +} + +void CSeasonalAdjustment::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/seasonal_adjustment.h b/engines/titanic/game/seasonal_adjustment.h new file mode 100644 index 0000000000..f96c13619d --- /dev/null +++ b/engines/titanic/game/seasonal_adjustment.h @@ -0,0 +1,58 @@ +/* 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_SEASONAL_ADJUSTMENT_H +#define TITANIC_SEASONAL_ADJUSTMENT_H + +#include "titanic/core/background.h" + +namespace Titanic { + +enum Season { + SPRING = 0, + SUMMER = 1, + AUTUMN = 2, + WINTER = 3 +}; + +class CSeasonalAdjustment : public CBackground { +public: + int _fieldE0; + int _fieldE4; +public: + CLASSDEF; + CSeasonalAdjustment() : CBackground(), _fieldE0(0), _fieldE4(0) {} + + /** + * 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_SEASONAL_ADJUSTMENT_H */ diff --git a/engines/titanic/game/service_elevator_window.cpp b/engines/titanic/game/service_elevator_window.cpp new file mode 100644 index 0000000000..95b2735b37 --- /dev/null +++ b/engines/titanic/game/service_elevator_window.cpp @@ -0,0 +1,51 @@ +/* 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/game/service_elevator_window.h" + +namespace Titanic { + +CServiceElevatorWindow::CServiceElevatorWindow() : CBackground(), + _fieldE0(0), _fieldE4(0), _fieldE8(0), _fieldEC(0) { +} + +void CServiceElevatorWindow::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + + CBackground::save(file, indent); +} + +void CServiceElevatorWindow::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/service_elevator_window.h b/engines/titanic/game/service_elevator_window.h new file mode 100644 index 0000000000..4233b8405a --- /dev/null +++ b/engines/titanic/game/service_elevator_window.h @@ -0,0 +1,53 @@ +/* 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_SERVICE_ELEVATOR_WINDOW_H +#define TITANIC_SERVICE_ELEVATOR_WINDOW_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CServiceElevatorWindow : public CBackground { +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; +public: + CLASSDEF; + CServiceElevatorWindow(); + + /** + * 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_SERVICE_ELEVATOR_WINDOW_H */ diff --git a/engines/titanic/game/sgt/armchair.cpp b/engines/titanic/game/sgt/armchair.cpp new file mode 100644 index 0000000000..f547c3ef9a --- /dev/null +++ b/engines/titanic/game/sgt/armchair.cpp @@ -0,0 +1,87 @@ +/* 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/game/sgt/armchair.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CArmchair, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CArmchair::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CArmchair::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CArmchair::TurnOn(CTurnOn *msg) { + if (_statics->_v8 == "Closed" && _statics->_v12 == "Closed") { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("Deskchair"); + + if (_statics->_v9 == "Open") { + CActMsg actMsg("Squash"); + actMsg.execute("Deskchair"); + _startFrame = 22; + _endFrame = 31; + } else { + _startFrame = 0; + _endFrame = 10; + } + + playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE); + playSound("b#0.wav"); + _statics->_v8 = "Open"; + _fieldE0 = 0; + } + + return true; +} + +bool CArmchair::TurnOff(CTurnOff *msg) { + if (_statics->_v8 == "Open") { + _statics->_v8 = "Closed"; + _startFrame = 11; + _endFrame = 21; + _fieldE0 = 1; + playMovie(11, 21, MOVIE_GAMESTATE | MOVIE_NOTIFY_OBJECT); + playSound("b#0.wav"); + } + + return true; +} + +bool CArmchair::MovieEndMsg(CMovieEndMsg *msg) { + if (_statics->_v8 == "Closed") + loadFrame(0); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/armchair.h b/engines/titanic/game/sgt/armchair.h new file mode 100644 index 0000000000..169b9b4aa0 --- /dev/null +++ b/engines/titanic/game/sgt/armchair.h @@ -0,0 +1,51 @@ +/* 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_ARMCHAIR_H +#define TITANIC_ARMCHAIR_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CArmchair : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool MovieEndMsg(CMovieEndMsg *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_ARMCHAIR_H */ diff --git a/engines/titanic/game/sgt/basin.cpp b/engines/titanic/game/sgt/basin.cpp new file mode 100644 index 0000000000..775c67deca --- /dev/null +++ b/engines/titanic/game/sgt/basin.cpp @@ -0,0 +1,78 @@ +/* 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/game/sgt/basin.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBasin, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CBasin::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CBasin::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CBasin::TurnOn(CTurnOn *msg) { + if (_statics->_v10 == "Open" && _statics->_v11 == "Closed" + && _statics->_v2 == "Closed") { + setVisible(true); + _statics->_v11 = "Open"; + _fieldE0 = 0; + _startFrame = 0; + _endFrame = 6; + playMovie(0, 6, MOVIE_GAMESTATE); + playSound("b#13.wav"); + } + + return true; +} + +bool CBasin::TurnOff(CTurnOff *msg) { + if (_statics->_v11 == "Open") { + _statics->_v11 = "Closed"; + _fieldE0 = 1; + _startFrame = 8; + _endFrame = 14; + playMovie(8, 14, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#13.wav"); + } + + return true; +} + +bool CBasin::MovieEndMsg(CMovieEndMsg *msg) { + if (_statics->_v11 == "Closed") + setVisible(false); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/basin.h b/engines/titanic/game/sgt/basin.h new file mode 100644 index 0000000000..1fcb469824 --- /dev/null +++ b/engines/titanic/game/sgt/basin.h @@ -0,0 +1,51 @@ +/* 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_BASIN_H +#define TITANIC_BASIN_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CBasin : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool MovieEndMsg(CMovieEndMsg *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_BASIN_H */ diff --git a/engines/titanic/game/sgt/bedfoot.cpp b/engines/titanic/game/sgt/bedfoot.cpp new file mode 100644 index 0000000000..ff7d64569a --- /dev/null +++ b/engines/titanic/game/sgt/bedfoot.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/game/sgt/bedfoot.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBedfoot, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +void CBedfoot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CBedfoot::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CBedfoot::TurnOn(CTurnOn *msg) { + if (_statics->_v2 == "Closed" && _statics->_v11 == "Closed") { + _fieldE0 = 0; + _startFrame = 0; + if (_statics->_v10 == "Open") { + _endFrame = 13; + _statics->_v2 = "Open"; + playSound("b#7.wav"); + } else { + _endFrame = 17; + _statics->_v2 = "NotOnWashstand"; + playSound("b#4.wav"); + } + + playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE); + } else if (_statics->_v2 == "RestingUnderTV") { + _fieldE0 = 0; + _startFrame = 8; + if (_statics->_v10 == "Open") { + _statics->_v2 = "Open"; + playSound("189_436_bed down 1.wav"); + } else { + _statics->_v2 = "NotOnWashstand"; + playSound("192_436_bed hits floor.wav"); + } + + playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE); + } + + if (_statics->_v2 == "Open") + _statics->_v1 = "Closed"; + else if (_statics->_v2 == "NotOnWashstand") + _statics->_v1 = "ClosedWrong"; + + return true; +} + +bool CBedfoot::TurnOff(CTurnOff *msg) { + if (_statics->_v1 == "Closed" || _statics->_v1 == "ClosedWrong") { + setVisible(true); + CVisibleMsg visibleMsg(false); + visibleMsg.execute("Bedhead"); + } + + if (_statics->_v2 == "Open" && _statics->_v1 == "Closed") { + _fieldE0 = 0; + _startFrame = 20; + if (_statics->_v4 == "Closed") { + _statics->_v2 = "Closed"; + _endFrame = 30; + } else { + _statics->_v2 = "RestingUnderTV"; + _endFrame = 25; + } + + playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE); + playSound("b#7.wav"); + + } else if (_statics->_v2 == "NotOnWashstand" && _statics->_v1 == "ClosedWrong") { + _fieldE0 = 0; + _startFrame = 17; + + if (_statics->_v4 == "Closed") { + _statics->_v2 = "Closed"; + _endFrame = 30; + } else { + _statics->_v2 = "RestingUnderTV"; + _endFrame = 25; + } + + playMovie(_startFrame, _endFrame, MOVIE_GAMESTATE); + playSound("b#7.wav"); + + } else if (_statics->_v2 == "RestingUTV" && _statics->_v4 == "Closed") { + _statics->_v2 = "Closed"; + _startFrame = 25; + _endFrame = 30; + playMovie(25, 30, MOVIE_GAMESTATE); + playSound("b#7.wav"); + } + + if (_statics->_v2 == "Closed") + _statics->_v1 = "Closed"; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/bedfoot.h b/engines/titanic/game/sgt/bedfoot.h new file mode 100644 index 0000000000..cc7b82b075 --- /dev/null +++ b/engines/titanic/game/sgt/bedfoot.h @@ -0,0 +1,50 @@ +/* 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_BEDFOOT_H +#define TITANIC_BEDFOOT_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CBedfoot : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *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_BEDFOOT_H */ diff --git a/engines/titanic/game/sgt/bedhead.cpp b/engines/titanic/game/sgt/bedhead.cpp new file mode 100644 index 0000000000..f911a83ae3 --- /dev/null +++ b/engines/titanic/game/sgt/bedhead.cpp @@ -0,0 +1,170 @@ +/* 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/game/sgt/bedhead.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBedhead, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +void BedheadEntry::load(Common::SeekableReadStream *s) { + _name1 = readStringFromStream(s); + _name2 = readStringFromStream(s); + _name3 = readStringFromStream(s); + _name4 = readStringFromStream(s); + _startFrame = s->readUint32LE(); + _endFrame = s->readUint32LE(); +} + +/*------------------------------------------------------------------------*/ + +void BedheadEntries::load(Common::SeekableReadStream *s, int count) { + resize(count); + for (uint idx = 0; idx < count; ++idx) + (*this)[idx].load(s); +} + +/*------------------------------------------------------------------------*/ + +void TurnOnEntries::load(Common::SeekableReadStream *s) { + _closed.load(s, 4); + _restingTV.load(s, 2); + _restingUV.load(s, 2); + _closedWrong.load(s, 2); +} + +/*------------------------------------------------------------------------*/ + +void TurnOffEntries::load(Common::SeekableReadStream *s) { + _open.load(s, 3); + _restingUTV.load(s, 1); + _restingV.load(s, 1); + _restingG.load(s, 3); + _openWrong.load(s, 1); + _restingDWrong.load(s, 1); +} + +/*------------------------------------------------------------------------*/ + +CBedhead::CBedhead() : CSGTStateRoom() { + Common::SeekableReadStream *s = g_vm->_filesManager->getResource("DATA/BEDHEAD"); + _on.load(s); + _off.load(s); + delete s; +} + +void CBedhead::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CBedhead::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CBedhead::TurnOn(CTurnOn *msg) { + if (_statics->_v2 == "Closed" || _statics->_v2 == "RestingUnderTV") + return true; + + const BedheadEntries *data = nullptr; + if (_statics->_v1 == "Closed") + data = &_on._closed; + else if (_statics->_v1 == "RestingTV") + data = &_on._restingTV; + else if (_statics->_v1 == "RestingUV") + data = &_on._restingUV; + else if (_statics->_v1 == "ClosedWrong") + data = &_on._closedWrong; + else + return true; + + for (uint idx = 0; idx < data->size(); ++idx) { + const BedheadEntry &entry = (*data)[idx]; + if ((entry._name1 == _statics->_v4 || entry._name1 == "Any") + && (entry._name2 == _statics->_v3 || entry._name2 == "Any") + && (entry._name3 == _statics->_v5 || entry._name3 == "Any")) { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("Bedfoot"); + setVisible(true); + + _statics->_v1 = entry._name4; + playMovie(entry._startFrame, entry._endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#6.wav"); + _fieldE0 = false; + } + } + + if (_statics->_v1 == "Open") { + playMovie(71, 78, 0); + playSound("196_436 bed inflate 2.wav"); + } + + return true; +} + +bool CBedhead::TurnOff(CTurnOff *msg) { + if (_statics->_v1 == "Open") { + playMovie(78, 85, 0); + playSound("191_436_bed inflate deflate.wav"); + } + + BedheadEntries *data = nullptr; + if (_statics->_v1 == "Open") + data = &_off._open; + else if (_statics->_v1 == "RestingUTV") + data = &_off._restingUTV; + else if (_statics->_v1 == "RestingV") + data = &_off._restingV; + else if (_statics->_v1 == "RestingG") + data = &_off._restingG; + else if (_statics->_v1 == "OpenWrong") + data = &_off._openWrong; + else if (_statics->_v1 == "RestingDWrong") + data = &_off._restingDWrong; + else + return true; + + for (uint idx = 0; idx < data->size(); ++idx) { + const BedheadEntry &entry = (*data)[idx]; + if ((entry._name1 == _statics->_v4 || entry._name1 == "Any") + && (entry._name2 == _statics->_v3 || entry._name2 == "Any") + && (entry._name3 == _statics->_v5 || entry._name3 == "Any")) { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("Bedfoot"); + setVisible(true); + + _statics->_v1 = entry._name4; + playMovie(entry._startFrame, entry._endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("193_436_bed fold up 1.wav"); + _fieldE0 = false; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/bedhead.h b/engines/titanic/game/sgt/bedhead.h new file mode 100644 index 0000000000..7784cb8caf --- /dev/null +++ b/engines/titanic/game/sgt/bedhead.h @@ -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. + * + */ + +#ifndef TITANIC_BEDHEAD_H +#define TITANIC_BEDHEAD_H + +#include "common/array.h" +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +struct BedheadEntry { + CString _name1; + CString _name2; + CString _name3; + CString _name4; + int _startFrame; + int _endFrame; + + void load(Common::SeekableReadStream *s); +}; +class BedheadEntries : public Common::Array<BedheadEntry> { +public: + void load(Common::SeekableReadStream *s, int count); +}; + +struct TurnOnEntries { + BedheadEntries _closed; + BedheadEntries _restingTV; + BedheadEntries _restingUV; + BedheadEntries _closedWrong; + + void load(Common::SeekableReadStream *s); +}; + +struct TurnOffEntries { + BedheadEntries _open; + BedheadEntries _restingUTV; + BedheadEntries _restingV; + BedheadEntries _restingG; + BedheadEntries _openWrong; + BedheadEntries _restingDWrong; + + void load(Common::SeekableReadStream *s); +}; + +class CBedhead : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); +private: + TurnOnEntries _on; + TurnOffEntries _off; +public: + CLASSDEF; + CBedhead(); + + /** + * 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_BEDHEAD_H */ diff --git a/engines/titanic/game/sgt/chest_of_drawers.cpp b/engines/titanic/game/sgt/chest_of_drawers.cpp new file mode 100644 index 0000000000..d9c72d3021 --- /dev/null +++ b/engines/titanic/game/sgt/chest_of_drawers.cpp @@ -0,0 +1,80 @@ +/* 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/game/sgt/chest_of_drawers.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChestOfDrawers, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CChestOfDrawers::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CChestOfDrawers::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CChestOfDrawers::TurnOn(CTurnOn *msg) { + if (_statics->_v6 == "Closed" && _statics->_v5 == "Open") { + _fieldE0 = false; + _statics->_v6 = "Open"; + _startFrame = 1; + _endFrame = 14; + playSound("b#11.wav"); + } + + return true; +} + +bool CChestOfDrawers::TurnOff(CTurnOff *msg) { + if (_statics->_v6 == "Open" && _statics->_v5 == "Closed") { + CVisibleMsg visibleMsg; + visibleMsg.execute("Drawer"); + _statics->_v6 = "Closed"; + _fieldE0 = true; + + _startFrame = 14; + _endFrame = 27; + playMovie(14, 27, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#11.wav"); + } + + return true; +} + +bool CChestOfDrawers::MovieEndMsg(CMovieEndMsg *msg) { + if (_statics->_v6 == "Open") { + CVisibleMsg visibleMsg; + visibleMsg.execute("Drawer"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/chest_of_drawers.h b/engines/titanic/game/sgt/chest_of_drawers.h new file mode 100644 index 0000000000..5bf852902b --- /dev/null +++ b/engines/titanic/game/sgt/chest_of_drawers.h @@ -0,0 +1,51 @@ +/* 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_CHEST_OF_DRAWERS_H +#define TITANIC_CHEST_OF_DRAWERS_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CChestOfDrawers : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool MovieEndMsg(CMovieEndMsg *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_CHEST_OF_DRAWERS_H */ diff --git a/engines/titanic/game/sgt/desk.cpp b/engines/titanic/game/sgt/desk.cpp new file mode 100644 index 0000000000..09ff66f134 --- /dev/null +++ b/engines/titanic/game/sgt/desk.cpp @@ -0,0 +1,83 @@ +/* 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/game/sgt/desk.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDesk, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CDesk::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CDesk::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CDesk::TurnOn(CTurnOn *msg) { + if (_statics->_v5 == "Closed" && _statics->_v1 != "RestingG" + && _statics->_v1 != "OpenWrong") { + _statics->_v5 = "Open"; + _fieldE0 = false; + _startFrame = 1; + _endFrame = 26; + playMovie(1, 26, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#12.wav"); + } + + return true; +} + +bool CDesk::TurnOff(CTurnOff *msg) { + if (_statics->_v5 == "Open" && _statics->_v6 == "Closed" + && _statics->_v1 == "Open") { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("ChestOfDrawers"); + + _statics->_v5 = "Closed"; + _fieldE0 = true; + _startFrame = 26; + _endFrame = 51; + playMovie(26, 51, MOVIE_GAMESTATE); + playSound("b#9.wav"); + } + + return true; +} + +bool CDesk::MovieEndMsg(CMovieEndMsg *msg) { + if (_statics->_v5 == "Open") { + CVisibleMsg visibleMsg(true); + visibleMsg.execute("ChestOfDrawers"); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/desk.h b/engines/titanic/game/sgt/desk.h new file mode 100644 index 0000000000..8b9e1fe841 --- /dev/null +++ b/engines/titanic/game/sgt/desk.h @@ -0,0 +1,51 @@ +/* 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_DESK_H +#define TITANIC_DESK_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CDesk : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool MovieEndMsg(CMovieEndMsg *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_DESK_H */ diff --git a/engines/titanic/game/sgt/deskchair.cpp b/engines/titanic/game/sgt/deskchair.cpp new file mode 100644 index 0000000000..7f64c2ee34 --- /dev/null +++ b/engines/titanic/game/sgt/deskchair.cpp @@ -0,0 +1,89 @@ +/* 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/game/sgt/deskchair.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDeskchair, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CDeskchair::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CDeskchair::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CDeskchair::TurnOn(CTurnOn *msg) { + if (_statics->_v8 == "Closed" && _statics->_v9 == "Closed") { + setVisible(true); + _statics->_v9 = "Open"; + _fieldE0 = false; + _startFrame = 0; + _endFrame = 16; + playMovie(0, 16, MOVIE_GAMESTATE); + playSound("b#8.wav"); + } + + return true; +} + +bool CDeskchair::TurnOff(CTurnOff *msg) { + if (_statics->_v9 == "Open") { + _statics->_v9 = "Closed"; + _fieldE0 = true; + _startFrame = 16; + _endFrame = 32; + playMovie(16, 32, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#2.wav"); + } + + return true; +} + +bool CDeskchair::ActMsg(CActMsg *msg) { + if (msg->_action == "Smash") { + setVisible(false); + _statics->_v9 = "Closed"; + _fieldE0 = true; + loadFrame(0); + return true; + } else { + return CSGTStateRoom::ActMsg(msg); + } +} + +bool CDeskchair::MovieEndMsg(CMovieEndMsg *msg) { + if (_statics->_v9 == "Closed") + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/deskchair.h b/engines/titanic/game/sgt/deskchair.h new file mode 100644 index 0000000000..6e7bbe4169 --- /dev/null +++ b/engines/titanic/game/sgt/deskchair.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_DESKCHAIR_H +#define TITANIC_DESKCHAIR_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CDeskchair : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *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_DESKCHAIR_H */ diff --git a/engines/titanic/game/sgt/drawer.cpp b/engines/titanic/game/sgt/drawer.cpp new file mode 100644 index 0000000000..b8e93c37a6 --- /dev/null +++ b/engines/titanic/game/sgt/drawer.cpp @@ -0,0 +1,83 @@ +/* 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/game/sgt/drawer.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDrawer, CSGTStateRoom) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +CDrawer::CDrawer() : CSGTStateRoom(), _fieldF4(0) { +} + +void CDrawer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldF4, indent); + CSGTStateRoom::save(file, indent); +} + +void CDrawer::load(SimpleFile *file) { + file->readNumber(); + _fieldF4 = file->readNumber(); + CSGTStateRoom::load(file); +} + +bool CDrawer::TurnOn(CTurnOn *msg) { + if (_statics->_v7 == "Closed" && _statics->_v6 == "Open") { + _statics->_v7 = "Open"; + _fieldE0 = false; + _startFrame = 50; + _endFrame = 75; + setVisible(true); + _statics->_v7 = "Open"; + playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#10.wav"); + } + + return true; +} + +bool CDrawer::TurnOff(CTurnOff *msg) { + if (_statics->_v7 == "Open") { + _statics->_v7 = "Closed"; + _startFrame = 75; + _endFrame = 100; + _fieldE0 = true; + playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playSound("b#10.wav"); + } + + return true; +} + +bool CDrawer::MovieEndMsg(CMovieEndMsg *msg) { + if (_statics->_v7 == "Closed") + setVisible(false); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/drawer.h b/engines/titanic/game/sgt/drawer.h new file mode 100644 index 0000000000..e8afe66068 --- /dev/null +++ b/engines/titanic/game/sgt/drawer.h @@ -0,0 +1,54 @@ +/* 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_DRAWER_H +#define TITANIC_DRAWER_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CDrawer : public CSGTStateRoom { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +private: + int _fieldF4; +public: + CLASSDEF; + CDrawer(); + + /** + * 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_DRAWER_H */ diff --git a/engines/titanic/game/sgt/sgt_doors.cpp b/engines/titanic/game/sgt/sgt_doors.cpp new file mode 100644 index 0000000000..516b0f1351 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_doors.cpp @@ -0,0 +1,43 @@ +/* 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/game/sgt/sgt_doors.h" + +namespace Titanic { + +void CSGTDoors::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CSGTDoors::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _value2 = file->readNumber(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_doors.h b/engines/titanic/game/sgt/sgt_doors.h new file mode 100644 index 0000000000..4b4f4a3153 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_doors.h @@ -0,0 +1,50 @@ +/* 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_SGT_DOORS_H +#define TITANIC_SGT_DOORS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSGTDoors : public CGameObject { +public: + int _value1, _value2; +public: + CLASSDEF; + CSGTDoors() : CGameObject(), _value1(0), _value2(0) {} + + /** + * 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_SGT_DOORS_H */ diff --git a/engines/titanic/game/sgt/sgt_nav.cpp b/engines/titanic/game/sgt/sgt_nav.cpp new file mode 100644 index 0000000000..f98e486fd0 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_nav.cpp @@ -0,0 +1,37 @@ +/* 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/game/sgt/sgt_nav.h" + +namespace Titanic { + +void SGTNav::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void SGTNav::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_nav.h b/engines/titanic/game/sgt/sgt_nav.h new file mode 100644 index 0000000000..40fdc4eff1 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_nav.h @@ -0,0 +1,47 @@ +/* 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_SGT_NAV_H +#define TITANIC_SGT_NAV_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class SGTNav : public CSGTStateRoom { +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_SGT_NAV_H */ diff --git a/engines/titanic/game/sgt/sgt_navigation.cpp b/engines/titanic/game/sgt/sgt_navigation.cpp new file mode 100644 index 0000000000..7bb64f934d --- /dev/null +++ b/engines/titanic/game/sgt/sgt_navigation.cpp @@ -0,0 +1,55 @@ +/* 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/game/sgt/sgt_navigation.h" + +namespace Titanic { + +CSGTNavigationStatics *CSGTNavigation::_statics; + +void CSGTNavigation::init() { + _statics = new CSGTNavigationStatics(); +} + +void CSGTNavigation::deinit() { + delete _statics; +} + +void CSGTNavigation::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_statics->_changeViewFlag, indent); + file->writeQuotedLine(_statics->_destView, indent); + file->writeQuotedLine(_statics->_destRoom, indent); + + CGameObject::save(file, indent); +} + +void CSGTNavigation::load(SimpleFile *file) { + file->readNumber(); + _statics->_changeViewFlag = file->readNumber(); + _statics->_destView = file->readString(); + _statics->_destRoom = file->readString(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_navigation.h b/engines/titanic/game/sgt/sgt_navigation.h new file mode 100644 index 0000000000..ed58d918e9 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_navigation.h @@ -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. + * + */ + +#ifndef TITANIC_SGT_NAVIGATION_H +#define TITANIC_SGT_NAVIGATION_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +struct CSGTNavigationStatics { + bool _changeViewFlag; + CString _destView; + CString _destRoom; +}; + +class CSGTNavigation : public CGameObject { +protected: + static CSGTNavigationStatics *_statics; +public: + CLASSDEF; + static void init(); + static void deinit(); + + /** + * 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_SGT_NAVIGATION_H */ diff --git a/engines/titanic/game/sgt/sgt_restaurant_doors.cpp b/engines/titanic/game/sgt/sgt_restaurant_doors.cpp new file mode 100644 index 0000000000..74a71e75b2 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_restaurant_doors.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/game/sgt/sgt_restaurant_doors.h" + +namespace Titanic { + +void CSGTRestaurantDoors::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + CGameObject::save(file, indent); +} + +void CSGTRestaurantDoors::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_restaurant_doors.h b/engines/titanic/game/sgt/sgt_restaurant_doors.h new file mode 100644 index 0000000000..2a10d8f059 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_restaurant_doors.h @@ -0,0 +1,50 @@ +/* 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_SGT_RESTAURANT_DOORS_H +#define TITANIC_SGT_RESTAURANT_DOORS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSGTRestaurantDoors : public CGameObject { +private: + int _fieldBC; +public: + CLASSDEF; + CSGTRestaurantDoors() : CGameObject(), _fieldBC(0) {} + + /** + * 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_SGT_RESTAURANT_DOORS_H */ diff --git a/engines/titanic/game/sgt/sgt_state_control.cpp b/engines/titanic/game/sgt/sgt_state_control.cpp new file mode 100644 index 0000000000..07c1f5efc0 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_state_control.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/game/sgt/sgt_state_control.h" + +namespace Titanic { + +void CSGTStateControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + CBackground::save(file, indent); +} + +void CSGTStateControl::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_state_control.h b/engines/titanic/game/sgt/sgt_state_control.h new file mode 100644 index 0000000000..49fd5113cd --- /dev/null +++ b/engines/titanic/game/sgt/sgt_state_control.h @@ -0,0 +1,50 @@ +/* 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_SGT_STATE_CONTROL_H +#define TITANIC_SGT_STATE_CONTROL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CSGTStateControl : public CBackground { +private: + int _fieldE0; +public: + CLASSDEF; + CSGTStateControl() : CBackground(), _fieldE0(1) {} + + /** + * 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_SGT_STATE_CONTROL_H */ diff --git a/engines/titanic/game/sgt/sgt_state_room.cpp b/engines/titanic/game/sgt/sgt_state_room.cpp new file mode 100644 index 0000000000..c089e401b8 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_state_room.cpp @@ -0,0 +1,179 @@ +/* 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/game/sgt/sgt_state_room.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSGTStateRoom, CBackground) + ON_MESSAGE(ActMsg) + ON_MESSAGE(VisibleMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) +END_MESSAGE_MAP() + +CSGTStateRoomStatics *CSGTStateRoom::_statics; + +void CSGTStateRoom::init() { + _statics = new CSGTStateRoomStatics(); + _statics->_v1 = "Closed"; +} + +void CSGTStateRoom::deinit() { + delete _statics; +} + +CSGTStateRoom::CSGTStateRoom() : CBackground(), _fieldE0(1), + _fieldE4(1), _fieldE8(0), _fieldEC(1), _fieldF0(1) { +} + +void CSGTStateRoom::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_statics->_v1, indent); + file->writeQuotedLine(_statics->_v2, indent); + file->writeQuotedLine(_statics->_v3, indent); + file->writeQuotedLine(_statics->_v4, indent); + file->writeQuotedLine(_statics->_v5, indent); + file->writeQuotedLine(_statics->_v6, indent); + file->writeQuotedLine(_statics->_v7, indent); + file->writeQuotedLine(_statics->_v8, indent); + file->writeQuotedLine(_statics->_v9, indent); + file->writeQuotedLine(_statics->_v10, indent); + file->writeQuotedLine(_statics->_v11, indent); + file->writeQuotedLine(_statics->_v12, indent); + + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_statics->_v13, indent); + file->writeNumberLine(_statics->_v14, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + + CBackground::save(file, indent); +} + +void CSGTStateRoom::load(SimpleFile *file) { + file->readNumber(); + _statics->_v1 = file->readString(); + _statics->_v2 = file->readString(); + _statics->_v3 = file->readString(); + _statics->_v4 = file->readString(); + _statics->_v5 = file->readString(); + _statics->_v6 = file->readString(); + _statics->_v7 = file->readString(); + _statics->_v8 = file->readString(); + _statics->_v9 = file->readString(); + _statics->_v10 = file->readString(); + _statics->_v11 = file->readString(); + _statics->_v12 = file->readString(); + + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _statics->_v13 = file->readNumber(); + _statics->_v14 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + + CBackground::load(file); +} + +bool CSGTStateRoom::ActMsg(CActMsg *msg) { + CPetControl *pet = getPetControl(); + uint roomFlags = pet->getRoomFlags(); + uint assignedRoom = pet->getAssignedRoomFlags(); + + if (roomFlags != assignedRoom) { + petDisplayMessage("This is not your assigned room. Please do not enjoy."); + } else if (_fieldE0) { + CTurnOn onMsg; + onMsg.execute(this); + } else { + CTurnOff offMsg; + offMsg.execute(this); + } + + return true; +} + +bool CSGTStateRoom::VisibleMsg(CVisibleMsg *msg) { + setVisible(msg->_visible); + return true; +} + +bool CSGTStateRoom::EnterRoomMsg(CEnterRoomMsg *msg) { + CPetControl *pet = getPetControl(); + uint roomFlags = pet->getRoomFlags(); + uint assignedRoom = pet->getAssignedRoomFlags(); + + if (roomFlags == assignedRoom) { + loadFrame(_fieldE8); + _fieldE0 = _fieldEC; + setVisible(_fieldF0); + + if (isEquals("Desk") && _statics->_v5 == "Closed") + loadFrame(1); + } + + if (isEquals("Drawer")) { + petSetArea(PET_REMOTE); + if (roomFlags == assignedRoom && getPassengerClass() == 3 + && _statics->_v13) { + playSound("b#21.wav"); + _statics->_v13 = 0; + } + + _statics->_v7 = "Closed"; + setVisible(false); + _fieldE0 = true; + } else if (roomFlags != assignedRoom) { + loadFrame(0); + if (_fieldE4) { + setVisible(true); + if (isEquals("Desk")) + loadFrame(1); + } else { + setVisible(false); + } + } + + return true; +} + +bool CSGTStateRoom::LeaveRoomMsg(CLeaveRoomMsg *msg) { + CPetControl *pet = getPetControl(); + uint roomFlags = pet->getRoomFlags(); + uint assignedRoom = pet->getAssignedRoomFlags(); + + if (roomFlags == assignedRoom) { + _fieldE8 = getMovieFrame(); + _fieldEC = _fieldE0; + _fieldF0 = _visible; + } + + _statics->_v14 = roomFlags; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_state_room.h b/engines/titanic/game/sgt/sgt_state_room.h new file mode 100644 index 0000000000..3975f7b59b --- /dev/null +++ b/engines/titanic/game/sgt/sgt_state_room.h @@ -0,0 +1,81 @@ +/* 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_SGT_STATE_ROOM_H +#define TITANIC_SGT_STATE_ROOM_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +struct CSGTStateRoomStatics { + CString _v1; + CString _v2; + CString _v3; + CString _v4; + CString _v5; + CString _v6; + CString _v7; + CString _v8; + CString _v9; + CString _v10; + CString _v11; + CString _v12; + int _v13; + int _v14; +}; + +class CSGTStateRoom : public CBackground { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool VisibleMsg(CVisibleMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); +protected: + static CSGTStateRoomStatics *_statics; +protected: + bool _fieldE0; + int _fieldE4; + int _fieldE8; + bool _fieldEC; + bool _fieldF0; +public: + CLASSDEF; + CSGTStateRoom(); + static void init(); + static void deinit(); + + /** + * 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_SGT_STATE_ROOM_H */ diff --git a/engines/titanic/game/sgt/sgt_tv.cpp b/engines/titanic/game/sgt/sgt_tv.cpp new file mode 100644 index 0000000000..ae4c59e2f9 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_tv.cpp @@ -0,0 +1,37 @@ +/* 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/game/sgt/sgt_tv.h" + +namespace Titanic { + +void CSGTTV::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CSGTTV::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_tv.h b/engines/titanic/game/sgt/sgt_tv.h new file mode 100644 index 0000000000..90fed90efe --- /dev/null +++ b/engines/titanic/game/sgt/sgt_tv.h @@ -0,0 +1,47 @@ +/* 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_SGT_TV_H +#define TITANIC_SGT_TV_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CSGTTV : public CSGTStateRoom { +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_SGT_TV_H */ diff --git a/engines/titanic/game/sgt/sgt_upper_doors_sound.cpp b/engines/titanic/game/sgt/sgt_upper_doors_sound.cpp new file mode 100644 index 0000000000..72cd7f9037 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_upper_doors_sound.cpp @@ -0,0 +1,45 @@ +/* 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/game/sgt/sgt_upper_doors_sound.h" + +namespace Titanic { + +CSGTUpperDoorsSound::CSGTUpperDoorsSound() { + _soundName = "b#53.wav"; +} + +void CSGTUpperDoorsSound::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_soundName, indent); + + CClickResponder::save(file, indent); +} + +void CSGTUpperDoorsSound::load(SimpleFile *file) { + file->readNumber(); + _soundName = file->readString(); + + CClickResponder::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/sgt_upper_doors_sound.h b/engines/titanic/game/sgt/sgt_upper_doors_sound.h new file mode 100644 index 0000000000..fc8c6c2bf1 --- /dev/null +++ b/engines/titanic/game/sgt/sgt_upper_doors_sound.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_SGT_UPPER_DOORS_SOUND_H +#define TITANIC_SGT_UPPER_DOORS_SOUND_H + +#include "titanic/core/click_responder.h" + +namespace Titanic { + +class CSGTUpperDoorsSound : public CClickResponder { +public: + CLASSDEF; + CSGTUpperDoorsSound(); + + /** + * 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_SGT_UPPER_DOORS_SOUND_H */ diff --git a/engines/titanic/game/sgt/toilet.cpp b/engines/titanic/game/sgt/toilet.cpp new file mode 100644 index 0000000000..799abd6c76 --- /dev/null +++ b/engines/titanic/game/sgt/toilet.cpp @@ -0,0 +1,37 @@ +/* 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/game/sgt/toilet.h" + +namespace Titanic { + +void CToilet::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CToilet::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/toilet.h b/engines/titanic/game/sgt/toilet.h new file mode 100644 index 0000000000..d87531ad7a --- /dev/null +++ b/engines/titanic/game/sgt/toilet.h @@ -0,0 +1,47 @@ +/* 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_TOILET_H +#define TITANIC_TOILET_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CToilet : public CSGTStateRoom { +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_TOILET_H */ diff --git a/engines/titanic/game/sgt/vase.cpp b/engines/titanic/game/sgt/vase.cpp new file mode 100644 index 0000000000..3e04b5db9e --- /dev/null +++ b/engines/titanic/game/sgt/vase.cpp @@ -0,0 +1,37 @@ +/* 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/game/sgt/vase.h" + +namespace Titanic { + +void CVase::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CVase::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/vase.h b/engines/titanic/game/sgt/vase.h new file mode 100644 index 0000000000..8aa35acdf5 --- /dev/null +++ b/engines/titanic/game/sgt/vase.h @@ -0,0 +1,47 @@ +/* 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_VASE_H +#define TITANIC_VASE_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CVase : public CSGTStateRoom { +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_VASE_H */ diff --git a/engines/titanic/game/sgt/washstand.cpp b/engines/titanic/game/sgt/washstand.cpp new file mode 100644 index 0000000000..8127a59a59 --- /dev/null +++ b/engines/titanic/game/sgt/washstand.cpp @@ -0,0 +1,37 @@ +/* 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/game/sgt/washstand.h" + +namespace Titanic { + +void CWashstand::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSGTStateRoom::save(file, indent); +} + +void CWashstand::load(SimpleFile *file) { + file->readNumber(); + CSGTStateRoom::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sgt/washstand.h b/engines/titanic/game/sgt/washstand.h new file mode 100644 index 0000000000..f140b17f49 --- /dev/null +++ b/engines/titanic/game/sgt/washstand.h @@ -0,0 +1,47 @@ +/* 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_WASHSTAND_H +#define TITANIC_WASHSTAND_H + +#include "titanic/game/sgt/sgt_state_room.h" + +namespace Titanic { + +class CWashstand : public CSGTStateRoom { +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_WASHSTAND_H */ diff --git a/engines/titanic/game/ship_setting.cpp b/engines/titanic/game/ship_setting.cpp new file mode 100644 index 0000000000..462f396501 --- /dev/null +++ b/engines/titanic/game/ship_setting.cpp @@ -0,0 +1,56 @@ +/* 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/game/ship_setting.h" + +namespace Titanic { + +CShipSetting::CShipSetting() : CBackground(), + _string4("NULL"), _string5("NULL") { +} + +void CShipSetting::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string3, indent); + file->writePoint(_pos1, indent); + file->writeQuotedLine(_string4, indent); + file->writeQuotedLine(_string5, indent); + + CBackground::save(file, indent); +} + +void CShipSetting::load(SimpleFile *file) { + file->readNumber(); + _string3 = file->readString(); + _pos1 = file->readPoint(); + _string4 = file->readString(); + _string5 = file->readString(); + + CBackground::load(file); +} + +bool CShipSetting::EnterRoomMsg(CEnterRoomMsg *msg) { + warning("CShipSetting::handleEvent"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/ship_setting.h b/engines/titanic/game/ship_setting.h new file mode 100644 index 0000000000..4fcc10a424 --- /dev/null +++ b/engines/titanic/game/ship_setting.h @@ -0,0 +1,55 @@ +/* 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_SHIP_SETTING_H +#define TITANIC_SHIP_SETTING_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CShipSetting : public CBackground { + bool EnterRoomMsg(CEnterRoomMsg *msg); +public: + CString _string3; + Point _pos1; + CString _string4; + CString _string5; +public: + CLASSDEF; + CShipSetting(); + + /** + * 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_SHIP_SETTING_H */ diff --git a/engines/titanic/game/ship_setting_button.cpp b/engines/titanic/game/ship_setting_button.cpp new file mode 100644 index 0000000000..7dc2cabac0 --- /dev/null +++ b/engines/titanic/game/ship_setting_button.cpp @@ -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. + * + */ + +#include "titanic/game/ship_setting_button.h" + +namespace Titanic { + +CShipSettingButton::CShipSettingButton() : CGameObject(), _fieldC8(0), _fieldCC(0) { +} + +void CShipSettingButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string1, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_fieldCC, indent); + + CGameObject::save(file, indent); +} + +void CShipSettingButton::load(SimpleFile *file) { + file->readNumber(); + _string1 = file->readString(); + _fieldC8 = file->readNumber(); + _fieldCC = file->readNumber(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/ship_setting_button.h b/engines/titanic/game/ship_setting_button.h new file mode 100644 index 0000000000..e152e8e2c3 --- /dev/null +++ b/engines/titanic/game/ship_setting_button.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_SHIP_SETTING_BUTTON_H +#define TITANIC_SHIP_SETTING_BUTTON_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CShipSettingButton : public CGameObject { +private: + CString _string1; + int _fieldC8; + int _fieldCC; +public: + CLASSDEF; + CShipSettingButton(); + + /** + * 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_SHIP_SETTING_BUTTON_H */ diff --git a/engines/titanic/game/show_cell_points.cpp b/engines/titanic/game/show_cell_points.cpp new file mode 100644 index 0000000000..7d54401a02 --- /dev/null +++ b/engines/titanic/game/show_cell_points.cpp @@ -0,0 +1,41 @@ +/* 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/game/show_cell_points.h" + +namespace Titanic { + +void CShowCellpoints::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_strValue, indent); + file->writeNumberLine(_numValue, indent); + CGameObject::save(file, indent); +} + +void CShowCellpoints::load(SimpleFile *file) { + file->readNumber(); + _strValue = file->readString(); + _numValue = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/show_cell_points.h b/engines/titanic/game/show_cell_points.h new file mode 100644 index 0000000000..9de2e06dca --- /dev/null +++ b/engines/titanic/game/show_cell_points.h @@ -0,0 +1,51 @@ +/* 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 SHOW_CELL_POINTS_H +#define SHOW_CELL_POINTS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CShowCellpoints : public CGameObject { +public: + CString _strValue; + int _numValue; +public: + CLASSDEF; + CShowCellpoints() : CGameObject(), _numValue(0) {} + + /** + * 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 /* SHOW_CELL_POINTS_H */ diff --git a/engines/titanic/game/speech_dispensor.cpp b/engines/titanic/game/speech_dispensor.cpp new file mode 100644 index 0000000000..f9cc019672 --- /dev/null +++ b/engines/titanic/game/speech_dispensor.cpp @@ -0,0 +1,53 @@ +/* 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/game/speech_dispensor.h" + +namespace Titanic { + +void CSpeechDispensor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_fieldF4, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_fieldFC, indent); + + CBackground::save(file, indent); +} + +void CSpeechDispensor::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldEC = file->readNumber(); + _fieldF0 = file->readNumber(); + _fieldF4 = file->readNumber(); + _fieldF8 = file->readNumber(); + _fieldFC = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/speech_dispensor.h b/engines/titanic/game/speech_dispensor.h new file mode 100644 index 0000000000..3b877e8d99 --- /dev/null +++ b/engines/titanic/game/speech_dispensor.h @@ -0,0 +1,56 @@ +/* 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_SPEECH_DISPENSOR_H +#define TITANIC_SPEECH_DISPENSOR_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CSpeechDispensor : public CBackground { +private: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; + int _fieldF0; + int _fieldF4; + int _fieldF8; + int _fieldFC; +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_SPEECH_DISPENSOR_H */ diff --git a/engines/titanic/game/splash_animation.cpp b/engines/titanic/game/splash_animation.cpp new file mode 100644 index 0000000000..2094ec14fa --- /dev/null +++ b/engines/titanic/game/splash_animation.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/game/splash_animation.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSplashAnimation, CGameObject); + +void CSplashAnimation::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CSplashAnimation::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/splash_animation.h b/engines/titanic/game/splash_animation.h new file mode 100644 index 0000000000..11715b4d73 --- /dev/null +++ b/engines/titanic/game/splash_animation.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_SPLASH_ANIMATION_H +#define TITANIC_SPLASH_ANIMATION_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSplashAnimation : 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_SPLASH_ANIMATION_H */ diff --git a/engines/titanic/game/starling_puret.cpp b/engines/titanic/game/starling_puret.cpp new file mode 100644 index 0000000000..359ad774df --- /dev/null +++ b/engines/titanic/game/starling_puret.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/game/starling_puret.h" + +namespace Titanic { + +void CStarlingPuret::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CStarlingPuret::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/starling_puret.h b/engines/titanic/game/starling_puret.h new file mode 100644 index 0000000000..fcd3319958 --- /dev/null +++ b/engines/titanic/game/starling_puret.h @@ -0,0 +1,50 @@ +/* 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_STARLING_PURET_H +#define TITANIC_STARLING_PURET_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CStarlingPuret : public CGameObject { +private: + int _value; +public: + CLASSDEF; + CStarlingPuret() : CGameObject(), _value(0) {} + + /** + * 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_STARLING_PURET_H */ diff --git a/engines/titanic/game/start_action.cpp b/engines/titanic/game/start_action.cpp new file mode 100644 index 0000000000..ab356ea1f4 --- /dev/null +++ b/engines/titanic/game/start_action.cpp @@ -0,0 +1,64 @@ +/* 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/game/start_action.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CStartAction, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +CStartAction::CStartAction() : CBackground() { +} + +void CStartAction::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_msgTarget, indent); + file->writeQuotedLine(_msgAction, indent); + + CBackground::save(file, indent); +} + +void CStartAction::load(SimpleFile *file) { + file->readNumber(); + _msgTarget = file->readString(); + _msgAction = file->readString(); + + CBackground::load(file); +} + +bool CStartAction::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + // Dispatch the desired action to the desired target + CActMsg actMsg(_msgAction); + actMsg.execute(_msgTarget); + + return true; +} + +bool CStartAction::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/start_action.h b/engines/titanic/game/start_action.h new file mode 100644 index 0000000000..60381bad2f --- /dev/null +++ b/engines/titanic/game/start_action.h @@ -0,0 +1,55 @@ +/* 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_START_ACTION_H +#define TITANIC_START_ACTION_H + +#include "titanic/core/background.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CStartAction : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +protected: + CString _msgTarget; + CString _msgAction; +public: + CLASSDEF; + CStartAction(); + + /** + * 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_START_ACTION_H */ diff --git a/engines/titanic/game/stop_phonograph_button.cpp b/engines/titanic/game/stop_phonograph_button.cpp new file mode 100644 index 0000000000..d18f4713ac --- /dev/null +++ b/engines/titanic/game/stop_phonograph_button.cpp @@ -0,0 +1,37 @@ +/* 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/game/stop_phonograph_button.h" + +namespace Titanic { + +void CStopPhonographButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CStopPhonographButton::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/stop_phonograph_button.h b/engines/titanic/game/stop_phonograph_button.h new file mode 100644 index 0000000000..b469375e20 --- /dev/null +++ b/engines/titanic/game/stop_phonograph_button.h @@ -0,0 +1,47 @@ +/* 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_STOP_PHONOGRAPH_BUTTON_H +#define TITANIC_STOP_PHONOGRAPH_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CStopPhonographButton : public CBackground { +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_STOP_PHONOGRAPH_BUTTON_H */ diff --git a/engines/titanic/game/sub_glass.cpp b/engines/titanic/game/sub_glass.cpp new file mode 100644 index 0000000000..f1349f06ea --- /dev/null +++ b/engines/titanic/game/sub_glass.cpp @@ -0,0 +1,54 @@ +/* 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/game/sub_glass.h" + +namespace Titanic { + +CSUBGlass::CSUBGlass() : _fieldBC(0), _fieldC0(0), _fieldC4(1), _fieldC8(0) { +} + +void CSUBGlass::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_fieldC0, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_fieldCC, indent); + file->writeQuotedLine(_string, indent); + + CGameObject::save(file, indent); +} + +void CSUBGlass::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _fieldC0 = file->readNumber(); + _fieldC4 = file->readNumber(); + _fieldC8 = file->readNumber(); + _fieldCC = file->readNumber(); + _string = file->readString(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sub_glass.h b/engines/titanic/game/sub_glass.h new file mode 100644 index 0000000000..aab5c8400e --- /dev/null +++ b/engines/titanic/game/sub_glass.h @@ -0,0 +1,55 @@ +/* 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_SUB_GLASS_H +#define TITANIC_SUB_GLASS_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSUBGlass : public CGameObject { +private: + int _fieldBC; + int _fieldC0; + int _fieldC4; + int _fieldC8; + int _fieldCC; + CString _string; +public: + CLASSDEF; + CSUBGlass(); + + /** + * 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_ROOM_ITEM_H */ diff --git a/engines/titanic/game/sub_wrapper.cpp b/engines/titanic/game/sub_wrapper.cpp new file mode 100644 index 0000000000..dcc489316b --- /dev/null +++ b/engines/titanic/game/sub_wrapper.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/game/sub_wrapper.h" + +namespace Titanic { + +void CSUBWrapper::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CSUBWrapper::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sub_wrapper.h b/engines/titanic/game/sub_wrapper.h new file mode 100644 index 0000000000..81f8fdc941 --- /dev/null +++ b/engines/titanic/game/sub_wrapper.h @@ -0,0 +1,50 @@ +/* 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_SUB_WRAPPER_H +#define TITANIC_SUB_WRAPPER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSUBWrapper : public CGameObject { +public: + int _value; +public: + CLASSDEF; + CSUBWrapper() : CGameObject(), _value(0) {} + + /** + * 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_SUB_WRAPPER_H */ diff --git a/engines/titanic/game/sweet_bowl.cpp b/engines/titanic/game/sweet_bowl.cpp new file mode 100644 index 0000000000..e14f900e77 --- /dev/null +++ b/engines/titanic/game/sweet_bowl.cpp @@ -0,0 +1,37 @@ +/* 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/game/sweet_bowl.h" + +namespace Titanic { + +void CSweetBowl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CSweetBowl::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/sweet_bowl.h b/engines/titanic/game/sweet_bowl.h new file mode 100644 index 0000000000..cf3d0023a4 --- /dev/null +++ b/engines/titanic/game/sweet_bowl.h @@ -0,0 +1,47 @@ +/* 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_SWEET_BOWL_H +#define TITANIC_SWEET_BOWL_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CSweetBowl : public CGameObject { +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_CREDITS_H */ diff --git a/engines/titanic/game/television.cpp b/engines/titanic/game/television.cpp new file mode 100644 index 0000000000..ba30fbe281 --- /dev/null +++ b/engines/titanic/game/television.cpp @@ -0,0 +1,298 @@ +/* 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/game/television.h" +#include "titanic/game/get_lift_eye2.h" +#include "titanic/core/project_item.h" +#include "titanic/carry/magazine.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CTelevision, CGameObject) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(PETUpMsg) + ON_MESSAGE(PETDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(PETActivateMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(ShipSettingMsg) + ON_MESSAGE(TurnOff) + ON_MESSAGE(TurnOn) + ON_MESSAGE(LightsMsg) +END_MESSAGE_MAP() + +int CTelevision::_v1; +bool CTelevision::_turnOn; +int CTelevision::_v3; +int CTelevision::_v4; +int CTelevision::_v5; +int CTelevision::_v6; + +CTelevision::CTelevision() : CBackground(), _fieldE0(1), + _fieldE4(7), _isOn(false), _fieldEC(0), _soundHandle(0) { +} + +void CTelevision::init() { + _v1 = 531; + _turnOn = true; + _v3 = 0; + _v4 = 27; + _v5 = 1; + _v6 = 1; +} + +void CTelevision::deinit() { +} + +void CTelevision::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_turnOn, indent); + file->writeNumberLine(_isOn, indent); + file->writeNumberLine(_v3, indent); + file->writeNumberLine(_fieldEC, indent); + file->writeNumberLine(_v4, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_v5, indent); + file->writeNumberLine(_v6, indent); + + CBackground::save(file, indent); +} + +void CTelevision::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _v1 = file->readNumber(); + _fieldE4 = file->readNumber(); + _turnOn = file->readNumber() != 0; + _isOn = file->readNumber() != 0; + _v3 = file->readNumber(); + _fieldEC = file->readNumber(); + _v4 = file->readNumber(); + _soundHandle = file->readNumber(); + _v5 = file->readNumber(); + _v6 = file->readNumber(); + + CBackground::load(file); +} + +bool CTelevision::LeaveViewMsg(CLeaveViewMsg *msg) { + petClear(); + if (_isOn) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 0); + + loadFrame(622); + stopMovie(); + setVisible(0); + _isOn = false; + + if (compareRoomNameTo("CSGState")) { + CVisibleMsg visibleMsg(true); + visibleMsg.execute("Tellypic"); + } + } + + return true; +} + +bool CTelevision::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + if (msg->_season == "Autumn") { + _v1 = 545; + _v3 = 0; + } else if (msg->_season == "Winter") { + _v1 = 503; + _v3 = 0; + } else if (msg->_season == "Spring") { + _v1 = 517; + _v3 = 0; + } else if (msg->_season == "Summer") { + _v1 = 531; + _v3 = 0; + } + + return true; +} + +bool CTelevision::EnterViewMsg(CEnterViewMsg *msg) { + petSetArea(PET_REMOTE); + petHighlightGlyph(GLYPH_TELEVISION_CONTROL); + petSetRemoteTarget(); + setVisible(0); + _fieldE0 = 1; + + return true; +} + +static const int START_FRAMES[9] = { 0, 0, 56, 112, 168, 224, 280, 336, 392 }; +static const int END_FRAMES[8] = { 0, 55, 111, 167, 223, 279, 335, 391 }; + +bool CTelevision::PETUpMsg(CPETUpMsg *msg) { + if (msg->_name == "Television" && _isOn) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 0); + + _fieldE0 = _fieldE0 % _fieldE4 + 1; + stopMovie(); + playMovie(START_FRAMES[_fieldE0], END_FRAMES[_fieldE0], 4); + } + + return true; +} + +bool CTelevision::PETDownMsg(CPETDownMsg *msg) { + if (msg->_name == "Television" && _isOn) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 0); + if (--_fieldE0 < 1) + _fieldE0 += _fieldE4; + + _fieldE0 = _fieldE0 % _fieldE4 + 1; + stopMovie(); + playMovie(START_FRAMES[_fieldE0], END_FRAMES[_fieldE0], 4); + } + + return true; +} + +bool CTelevision::StatusChangeMsg(CStatusChangeMsg *msg) { + if (_isOn) { + stopMovie(); + playMovie(0); + } + + return true; +} + +bool CTelevision::ActMsg(CActMsg *msg) { + if (msg->_action == "TurnTVOnOff") { + _isOn = !_isOn; + if (_isOn) { + setVisible(true); + CStatusChangeMsg changeMsg; + changeMsg.execute(this); + } else { + setVisible(_isOn); + stopMovie(); + } + } + + return true; +} + +bool CTelevision::PETActivateMsg(CPETActivateMsg *msg) { + if (msg->_name == "Television") { + CVisibleMsg visibleMsg(_isOn); + _isOn = !_isOn; + + if (_isOn) { + setVisible(true); + playMovie(0, 55, 0); + _fieldE0 = 1; + } else { + stopMovie(); + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, 0); + + setVisible(false); + } + + if (compareRoomNameTo("SGTState")) + visibleMsg.execute("Tellypic"); + } + + return true; +} + +bool CTelevision::MovieEndMsg(CMovieEndMsg *msg) { + if (getRandomNumber(6) == 0) { + CParrotSpeakMsg parrotMsg("Television", ""); + parrotMsg.execute("PerchedParrot"); + } + + if (_fieldE0 == 3 && compareRoomNameTo("SGTState") && !getPassengerClass()) { + playSound("z#47.wav", 100, 0, 0); + _soundHandle = playSound("b#20.wav", 100, 0, 0); + CMagazine *magazine = dynamic_cast<CMagazine *>(getRoot()->findByName("Magazine")); + + if (magazine) { + CPetControl *pet = getPetControl(); + uint roomFlags = pet->getRoomFlags(); + + debugC(kDebugScripts, "Assigned room - %d", roomFlags); + magazine->addMail(roomFlags); + magazine->removeMail(roomFlags, roomFlags); + } + + loadFrame(561); + } else if (_fieldE0 == 2) { + loadFrame(_v1); + } else if (_fieldE0 == 4 && _v5) { + if (_turnOn) + loadFrame(502); + else + warning("There is currently nothing available for your viewing pleasure on this channel."); + } else if (_fieldE0 == 5 && *CGetLiftEye2::_destObject != "NULL") { + loadFrame(393 + _v4); + } else { + warning("There is currently nothing available for your viewing pleasure on this channel."); + } + + return true; +} + +bool CTelevision::ShipSettingMsg(CShipSettingMsg *msg) { + _v4 = msg->_value; + return true; +} + +bool CTelevision::TurnOff(CTurnOff *msg) { + _turnOn = false; + return true; +} + +bool CTelevision::TurnOn(CTurnOn *msg) { + _turnOn = true; + return true; +} + +bool CTelevision::LightsMsg(CLightsMsg *msg) { + CPetControl *pet = getPetControl(); + bool flag = false; + + if (pet) + flag = pet->isRoom59706(); + + if (msg->_flag2 || !flag) + _turnOn = true; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/television.h b/engines/titanic/game/television.h new file mode 100644 index 0000000000..2e8d469bde --- /dev/null +++ b/engines/titanic/game/television.h @@ -0,0 +1,79 @@ +/* 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_TELEVISION_H +#define TITANIC_TELEVISION_H + +#include "titanic/core/background.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CTelevision : public CBackground { + DECLARE_MESSAGE_MAP; + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool PETUpMsg(CPETUpMsg *msg); + bool PETDownMsg(CPETDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool ActMsg(CActMsg *msg); + bool PETActivateMsg(CPETActivateMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool ShipSettingMsg(CShipSettingMsg *msg); + bool TurnOff(CTurnOff *msg); + bool TurnOn(CTurnOn *msg); + bool LightsMsg(CLightsMsg *msg); +private: + int _fieldE0; + int _fieldE4; + bool _isOn; + int _fieldEC; + int _soundHandle; +public: + static int _v1; + static bool _turnOn; + static int _v3; + static int _v4; + static int _v5; + static int _v6; +public: + CLASSDEF; + CTelevision(); + static void init(); + static void deinit(); + + /** + * 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_TELEVISION_H */ diff --git a/engines/titanic/game/third_class_canal.cpp b/engines/titanic/game/third_class_canal.cpp new file mode 100644 index 0000000000..6b0a101f7b --- /dev/null +++ b/engines/titanic/game/third_class_canal.cpp @@ -0,0 +1,37 @@ +/* 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/game/third_class_canal.h" + +namespace Titanic { + +void CThirdClassCanal::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CBackground::save(file, indent); +} + +void CThirdClassCanal::load(SimpleFile *file) { + file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/third_class_canal.h b/engines/titanic/game/third_class_canal.h new file mode 100644 index 0000000000..f6fc471444 --- /dev/null +++ b/engines/titanic/game/third_class_canal.h @@ -0,0 +1,47 @@ +/* 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_THIRD_CLASS_CANAL_H +#define TITANIC_THIRD_CLASS_CANAL_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CThirdClassCanal : public CBackground { +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_THIRD_CLASS_CANAL_H */ diff --git a/engines/titanic/game/throw_tv_down_well.cpp b/engines/titanic/game/throw_tv_down_well.cpp new file mode 100644 index 0000000000..c8a9fc7c9e --- /dev/null +++ b/engines/titanic/game/throw_tv_down_well.cpp @@ -0,0 +1,41 @@ +/* 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/game/throw_tv_down_well.h" + +namespace Titanic { + +void CThrowTVDownWell::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_strValue, indent); + file->writeNumberLine(_numValue, indent); + CGameObject::save(file, indent); +} + +void CThrowTVDownWell::load(SimpleFile *file) { + file->readNumber(); + _strValue = file->readString(); + _numValue = file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/throw_tv_down_well.h b/engines/titanic/game/throw_tv_down_well.h new file mode 100644 index 0000000000..b6003aa3ef --- /dev/null +++ b/engines/titanic/game/throw_tv_down_well.h @@ -0,0 +1,51 @@ +/* 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_THROW_TV_DOWN_WELL_H +#define TITANIC_THROW_TV_DOWN_WELL_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CThrowTVDownWell : public CGameObject { +public: + CString _strValue; + int _numValue; +public: + CLASSDEF; + CThrowTVDownWell() : CGameObject(), _numValue(0) {} + + /** + * 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_THROW_TV_DOWN_WELL_H */ diff --git a/engines/titanic/game/titania_still_control.cpp b/engines/titanic/game/titania_still_control.cpp new file mode 100644 index 0000000000..67866ecdcb --- /dev/null +++ b/engines/titanic/game/titania_still_control.cpp @@ -0,0 +1,37 @@ +/* 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/game/titania_still_control.h" + +namespace Titanic { + +void CTitaniaStillControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CTitaniaStillControl::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/titania_still_control.h b/engines/titanic/game/titania_still_control.h new file mode 100644 index 0000000000..66c3045187 --- /dev/null +++ b/engines/titanic/game/titania_still_control.h @@ -0,0 +1,47 @@ +/* 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_TITANIA_STILL_CONTROL_H +#define TITANIC_TITANIA_STILL_CONTROL_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CTitaniaStillControl : public CGameObject { +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_TITANIA_STILL_CONTROL_H */ diff --git a/engines/titanic/game/tow_parrot_nav.cpp b/engines/titanic/game/tow_parrot_nav.cpp new file mode 100644 index 0000000000..9361808870 --- /dev/null +++ b/engines/titanic/game/tow_parrot_nav.cpp @@ -0,0 +1,37 @@ +/* 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/game/tow_parrot_nav.h" + +namespace Titanic { + +void CTOWParrotNav::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CTOWParrotNav::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/tow_parrot_nav.h b/engines/titanic/game/tow_parrot_nav.h new file mode 100644 index 0000000000..17618ff6de --- /dev/null +++ b/engines/titanic/game/tow_parrot_nav.h @@ -0,0 +1,47 @@ +/* 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_TOW_PARROT_NAV_H +#define TITANIC_TOW_PARROT_NAV_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CTOWParrotNav : public CGameObject { +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_TOW_PARROT_NAV_H */ diff --git a/engines/titanic/game/transport/exit_pellerator.cpp b/engines/titanic/game/transport/exit_pellerator.cpp new file mode 100644 index 0000000000..400214a140 --- /dev/null +++ b/engines/titanic/game/transport/exit_pellerator.cpp @@ -0,0 +1,46 @@ +/* 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/game/transport/pellerator.h" + +namespace Titanic { + +int CPellerator::_v1; +int CPellerator::_v2; + +void CPellerator::save(SimpleFile *file, int indent) const { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + + CTransport::save(file, indent); +} + +void CPellerator::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + + CTransport::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/exit_pellerator.h b/engines/titanic/game/transport/exit_pellerator.h new file mode 100644 index 0000000000..53056c7417 --- /dev/null +++ b/engines/titanic/game/transport/exit_pellerator.h @@ -0,0 +1,50 @@ +/* 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_PELLERATOR_H +#define TITANIC_PELLERATOR_H + +#include "titanic/game/transport/transport.h" + +namespace Titanic { + +class CPellerator : public CTransport { +private: + static int _v1; + static int _v2; +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_PELLERATOR_H */ diff --git a/engines/titanic/game/transport/gondolier.cpp b/engines/titanic/game/transport/gondolier.cpp new file mode 100644 index 0000000000..8c28ff9b66 --- /dev/null +++ b/engines/titanic/game/transport/gondolier.cpp @@ -0,0 +1,54 @@ +/* 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/game/transport/gondolier.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGondolier, CTransport) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +int CGondolier::_v1; +int CGondolier::_v2; + +void CGondolier::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + CTransport::save(file, indent); +} + +void CGondolier::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + CTransport::load(file); +} + +bool CGondolier::StatusChangeMsg(CStatusChangeMsg *msg) { + CShowTextMsg textMsg("Only First Class passengers are allowed to use the Gondoliers."); + textMsg.execute("PET"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/gondolier.h b/engines/titanic/game/transport/gondolier.h new file mode 100644 index 0000000000..3b1e6d5a8a --- /dev/null +++ b/engines/titanic/game/transport/gondolier.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_GONDOLIER_H +#define TITANIC_GONDOLIER_H + +#include "titanic/game/transport/transport.h" + +namespace Titanic { + +class CGondolier : public CTransport { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); +private: + static int _v1; + static int _v2; +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_GONDOLIER_H */ diff --git a/engines/titanic/game/transport/lift.cpp b/engines/titanic/game/transport/lift.cpp new file mode 100644 index 0000000000..114e840007 --- /dev/null +++ b/engines/titanic/game/transport/lift.cpp @@ -0,0 +1,318 @@ +/* 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/game/transport/lift.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLift, CTransport) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +int CLift::_v1; +int CLift::_elevator1Floor; +int CLift::_elevator2Floor; +int CLift::_elevator3Floor; +int CLift::_elevator4Floor; +int CLift::_v6; + +void CLift::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_elevator1Floor, indent); + file->writeNumberLine(_elevator2Floor, indent); + file->writeNumberLine(_elevator3Floor, indent); + file->writeNumberLine(_elevator4Floor, indent); + file->writeNumberLine(_liftNum, indent); + file->writeNumberLine(_v6, indent); + + CTransport::save(file, indent); +} + +void CLift::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _elevator1Floor = file->readNumber(); + _elevator2Floor = file->readNumber(); + _elevator3Floor = file->readNumber(); + _elevator4Floor = file->readNumber(); + _liftNum = file->readNumber(); + _v6 = file->readNumber(); + + CTransport::load(file); +} + +bool CLift::StatusChangeMsg(CStatusChangeMsg *msg) { + CPetControl *pet = getPetControl(); + if ((!_v1 && pet->getRoomsElevatorNum() == 4) || + (!_v6 && pet->getRoomsElevatorNum() == 4)) + return true; + + int oldFloorNum = msg->_oldStatus; + int floorNum = msg->_newStatus; + int oldClass = 0, newClass = 0; + if (oldFloorNum == 19) + oldClass = 2; + if (oldFloorNum == 27) + oldClass = 3; + if (floorNum == 19) + newClass = 2; + if (floorNum == 27) + newClass = 3; + + static const int UP_FRAME_NUMBERS[40] = { + 0, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, + 63, 68, 73, 78, 83, 88, 93, 118, 123, 128, 133, + 138, 143, 148, 153, 228, 233, 238, 243, 248, 253, + 258, 263, 268, 273, 278, 298, 299 + }; + static const int DOWN_FRAME_NUMBERS[39] = { + 598, 589, 584, 579, 574, 569, 564, 559, 554, 549, + 544, 539, 534, 529, 524, 519, 514, 509, 504, 479, + 474, 469, 464, 459, 454, 449, 444, 369, 364, 359, + 354, 349, 344, 339, 334, 329, 324, 319 + }; + + if (pet) + pet->setRoomsFloorNum(floorNum); + if (pet->getRoomsElevatorNum() == 2 || pet->getRoomsElevatorNum() == 4) { + if (floorNum > 27) + floorNum = 27; + if (oldFloorNum > 27) + oldFloorNum = 27; + } + + changeView("Lift.Node 1.N"); + CTurnOn onMsg; + onMsg.execute("LiftHood"); + + CString debugStr; + if (floorNum > oldFloorNum) { + // Animate lift going up + _startFrame = UP_FRAME_NUMBERS[oldFloorNum - 1]; + _endFrame = UP_FRAME_NUMBERS[floorNum - 1]; + + if (oldClass == newClass) { + debugStr = CString::format("Same (%d-%d)", _startFrame, _endFrame); + playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else if (oldClass == 1 && newClass == 2) { + debugStr = CString::format("1 to 2 (%d-108, 108-%d)", _startFrame, _endFrame); + playMovie(_startFrame, 108, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(108, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else if (oldClass == 1 && newClass == 3) { + debugStr = CString::format("1 to 3 (%d-108, 108-190, 190-%d)", _startFrame, _endFrame); + playMovie(_startFrame, 108, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(108, 190, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(190, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else { + debugStr = CString::format("2 to 3 (%d-190, 190-%d)", _startFrame, _endFrame); + playMovie(_startFrame, 190, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(190, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } + + if (floorNum < oldFloorNum) { + // Animate lift going down + _startFrame = DOWN_FRAME_NUMBERS[floorNum - 1]; + _endFrame = DOWN_FRAME_NUMBERS[oldFloorNum - 1]; + + if (oldClass == newClass) { + debugStr = CString::format("Same (%d-%d)", _startFrame, _endFrame); + playMovie(_startFrame, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else if (oldClass == 3 && newClass == 2) { + debugStr = CString::format("3 to 2 (%d-407, 407-%d)", _startFrame, _endFrame); + playMovie(_startFrame, 407, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(407, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else if (oldClass == 3 && newClass == 1) { + debugStr = CString::format("3 to 1 (%d-407, 407-489, 489-%d)", _startFrame, _endFrame); + playMovie(_startFrame, 407, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(407, 489, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(489, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else { + debugStr = CString::format("2 to 1 (%d-489, 489-%d)", _startFrame, _endFrame); + playMovie(_startFrame, 489, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(489, _endFrame, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } + + CShipSettingMsg settingMsg; + switch (pet->getRoomsElevatorNum()) { + case 1: + _elevator1Floor = floorNum; + break; + case 2: + _elevator2Floor = floorNum; + _elevator4Floor = oldFloorNum; + settingMsg._value = oldFloorNum; + settingMsg.execute("SGTStateroomTV"); + break; + case 3: + _elevator3Floor = floorNum; + break; + case 4: + _elevator4Floor = floorNum; + break; + default: + break; + } + + debugC(1, kDebugScripts, "%s", debugStr.c_str()); + return true; +} + +bool CLift::MovieEndMsg(CMovieEndMsg *msg) { + switch (msg->_endFrame) { + case 108: + setGlobalSoundVolume(-4, 1, 2); + setGlobalSoundVolume(-2, 1, 1); + break; + + case 190: + setGlobalSoundVolume(-4, 1, 1); + setGlobalSoundVolume(-2, 1, 2); + break; + + case 407: + setGlobalSoundVolume(-4, 1, 0); + setGlobalSoundVolume(-2, 1, 1); + break; + + case 489: + setGlobalSoundVolume(-4, 1, 1); + setGlobalSoundVolume(-2, 1, 0); + break; + + default: { + CActMsg actMsg("LiftArrive"); + actMsg.execute("Liftbot"); + sleep(500); + playSound("352 gp button 1.wav"); + + CTurnOff offMsg; + offMsg.execute("LiftHood"); + changeView("Lift.Node 1.W"); + break; + } + } + + return true; +} + +bool CLift::EnterViewMsg(CEnterViewMsg *msg) { + static const int FRAME_NUMBERS[40] = { + 0, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73, + 78, 83, 88, 93, 118, 123, 128, 133, 138, 143, 148, 153, + 228, 233, 238, 243, 248, 253, 258, 263, 268, 273, 278, 298 + }; + + CPetControl *pet = getPetControl(); + loadFrame(FRAME_NUMBERS[pet->getRoomsFloorNum() - 1]); + return true; +} + +bool CLift::EnterRoomMsg(CEnterRoomMsg *msg) { + if (isEquals("Well")) { + CPetControl *pet = getPetControl(); + int floorNum = pet->getRoomsFloorNum(); + int elevNum = pet->getRoomsElevatorNum(); + loadSound("z#520.wav"); + loadSound("z#519.wav"); + loadSound("z#518.wav"); + + if (elevNum == 4 && _v1 == 1 && !_v6) { + CVisibleMsg visibleMsg; + visibleMsg.execute("GetLiftEye"); + } + + if (floorNum < 20) { + playGlobalSound("z#520.wav", -2, true, true, 0); + playGlobalSound("z#519.wav", -4, false, true, 1); + playGlobalSound("z#518.wav", -4, false, true, 2); + } else if (floorNum < 28) { + playGlobalSound("z#520.wav", -4, false, true, 0); + playGlobalSound("z#519.wav", -2, true, true, 1); + playGlobalSound("z#518.wav", -4, false, true, 2); + } else { + playGlobalSound("z#520.wav", -4, false, true, 0); + playGlobalSound("z#519.wav", -4, false, true, 1); + playGlobalSound("z#518.wav", -2, true, true, 2); + } + } + + return true; +} + +bool CLift::LeaveRoomMsg(CLeaveRoomMsg *msg) { + stopGlobalSound(true, -1); + + CPetControl *pet = getPetControl(); + if (pet->getRoomsElevatorNum() == 4 && _v1 == 1 && !_v6) { + CVisibleMsg visibleMsg; + visibleMsg.execute("Eye2"); + } + + return true; +} + +bool CLift::ActMsg(CActMsg *msg) { + if (msg->_action == "LoseHead") { + _v1 = 0; + _v6 = 0; + + CActMsg actMsg1("Lift.Node 2.N"); + actMsg1.execute("RPanInLiftW"); + CActMsg actMsg2("Lift.Node 2.S"); + actMsg2.execute("LPanInLiftW"); + } else if (msg->_action == "AddWrongHead") { + _v1 = 1; + _v6 = 0; + + CActMsg actMsg1("Lift.Node 1.N"); + actMsg1.execute("RPanInLiftW"); + CActMsg actMsg2("Lift.Node 1.S"); + actMsg2.execute("LPanInLiftW"); + } else if (msg->_action == "AddRightHead") { + _v1 = 1; + _v6 = 1; + petSetRooms1D4(0); + + CActMsg actMsg1("Lift.Node 1.N"); + actMsg1.execute("RPanInLiftW"); + CActMsg actMsg2("Lift.Node 1.S"); + actMsg2.execute("LPanInLiftW"); + CActMsg actMsg3("ActivateLift"); + actMsg3.execute("Liftbot"); + } + + CVisibleMsg visibleMsg; + visibleMsg.execute("LiftbotWithoutHead"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/lift.h b/engines/titanic/game/transport/lift.h new file mode 100644 index 0000000000..c45d2b64d0 --- /dev/null +++ b/engines/titanic/game/transport/lift.h @@ -0,0 +1,65 @@ +/* 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_LIFT_H +#define TITANIC_LIFT_H + +#include "titanic/game/transport/transport.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CLift : public CTransport { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool ActMsg(CActMsg *msg); +public: + static int _v1; + static int _elevator1Floor; + static int _elevator2Floor; + static int _elevator3Floor; + static int _elevator4Floor; + static int _v6; + + int _liftNum; +public: + CLASSDEF; + CLift() : CTransport(), _liftNum(1) {} + + /** + * 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_LIFT_H */ diff --git a/engines/titanic/game/transport/lift_indicator.cpp b/engines/titanic/game/transport/lift_indicator.cpp new file mode 100644 index 0000000000..7471affc36 --- /dev/null +++ b/engines/titanic/game/transport/lift_indicator.cpp @@ -0,0 +1,237 @@ +/* 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/game/transport/lift_indicator.h" +#include "titanic/game/transport/lift.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/titanic.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLiftindicator, CLift) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(PETActivateMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CLiftindicator::CLiftindicator() : CLift(), + _fieldFC(0), _start(0), _end(0) { +} + +void CLiftindicator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldFC, indent); + file->writePoint(_indicatorPos, indent); + file->writeNumberLine(_start, indent); + file->writeNumberLine(_end, indent); + + CLift::save(file, indent); +} + +void CLiftindicator::load(SimpleFile *file) { + file->readNumber(); + _fieldFC = file->readNumber(); + _indicatorPos = file->readPoint(); + _start = file->readNumber(); + _end = file->readNumber(); + + CLift::load(file); +} + +bool CLiftindicator::EnterViewMsg(CEnterViewMsg *msg) { + double multiplier = _fieldFC * 0.037037037; + CPetControl *pet = getPetControl(); + int floorNum = pet->getRoomsFloorNum(); + debugC(kDebugScripts, "Lifts = %d,%d,%d,%d, %d", + CLift::_elevator1Floor, CLift::_elevator2Floor, + CLift::_elevator3Floor, CLift::_elevator4Floor, + floorNum); + + if ((pet->petGetRoomsWellEntry() & 1) == (_fieldFC & 1)) { + petSetRemoteTarget(); + petSetArea(PET_REMOTE); + + CString str = CString::format("You are standing outside Elevator %d", + petGetRoomsWellEntry()); + petDisplayMessage(-1, str); + + debugC(kDebugScripts, "Claiming PET - %d, Multiplier = %f", + _liftNum, multiplier); + } + + switch (_liftNum) { + case 0: + loadFrame(pet->getRoomsFloorNum()); + break; + + case 1: + case 3: + switch (petGetRoomsWellEntry()) { + case 1: + case 2: + setPosition(Point(_bounds.left, _indicatorPos.y + + (int)(multiplier * CLift::_elevator1Floor))); + _startFrame = CLift::_elevator1Floor; + break; + + case 3: + case 4: + setPosition(Point(_bounds.left, _indicatorPos.y + + (int)(multiplier * CLift::_elevator3Floor))); + _startFrame = CLift::_elevator3Floor; + break; + + default: + break; + } + break; + + case 2: + case 4: + switch (petGetRoomsWellEntry()) { + case 1: + case 2: + setPosition(Point(_bounds.left, _indicatorPos.y + + (int)(multiplier * CLift::_elevator2Floor))); + _startFrame = CLift::_elevator2Floor; + break; + + case 3: + case 4: + setPosition(Point(_bounds.left, _indicatorPos.y + + (int)(multiplier * CLift::_elevator4Floor))); + _startFrame = CLift::_elevator4Floor; + break; + + default: + break; + } + break; + + default: + break; + } + + return true; +} + +bool CLiftindicator::LeaveViewMsg(CLeaveViewMsg *msg) { + petClear(); + return true; +} + +bool CLiftindicator::PETActivateMsg(CPETActivateMsg *msg) { + double multiplier = _fieldFC * 0.037037037; + CPetControl *pet = getPetControl(); + + if (msg->_name == "Lift") { + if (petDoorOrBellbotPresent()) { + petDisplayMessage(1, "I'm sorry, you cannot enter this elevator at present " + "as a bot is in the way."); + } else { + _endFrame = pet->getRoomsFloorNum(); + + if (petGetRoomsWellEntry() == 4 && !CLift::_v6 + && pet->getRoomsFloorNum() != CLift::_elevator4Floor) { + petDisplayMessage(1, "This elevator is currently in an advanced state of non-functionality."); + } else { + _start = _indicatorPos.y + (int)(_startFrame * multiplier); + _end = _indicatorPos.y + (int)(_endFrame * multiplier); + lockMouse(); + addTimer(100); + + if (petGetRoomsWellEntry() == 2) { + CLift::_elevator4Floor = CLift::_elevator2Floor; + CShipSettingMsg settingMsg; + settingMsg._value = CLift::_elevator4Floor; + settingMsg.execute("SGTStateroomTV"); + } + + switch (petGetRoomsWellEntry()) { + case 1: + CLift::_elevator1Floor = pet->getRoomsFloorNum(); + break; + case 2: + CLift::_elevator2Floor = pet->getRoomsFloorNum(); + break; + case 3: + CLift::_elevator3Floor = pet->getRoomsFloorNum(); + break; + case 4: + CLift::_elevator4Floor = pet->getRoomsFloorNum(); + break; + default: + break; + } + + debugC(kDebugScripts, "Lifts = %d,%d,%d,%d %d", + CLift::_elevator1Floor, CLift::_elevator2Floor, + CLift::_elevator3Floor, CLift::_elevator4Floor, + petGetRoomsWellEntry()); + } + } + } + + return true; +} + +bool CLiftindicator::MovieEndMsg(CMovieEndMsg *msg) { + playSound("357 gp button 1.wav"); + sleep(100); + changeView("Lift.Node 1.N"); + + unlockMouse(); + return true; +} + +bool CLiftindicator::EnterRoomMsg(CEnterRoomMsg *msg) { + return true; +} + +bool CLiftindicator::LeaveRoomMsg(CLeaveRoomMsg *msg) { + return true; +} + +bool CLiftindicator::TimerMsg(CTimerMsg *msg) { + debugC(kDebugScripts, "Start %d, End %d", _start, _end); + + if (_start > _end) { + setPosition(Point(_bounds.left, _bounds.top - 1)); + --_start; + addTimer(20); + } else if (_start < _end) { + setPosition(Point(_bounds.left, _bounds.top + 1)); + ++_start; + addTimer(20); + } else { + CMovieEndMsg endMsg(0, 0); + endMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/lift_indicator.h b/engines/titanic/game/transport/lift_indicator.h new file mode 100644 index 0000000000..5d0bc45d7b --- /dev/null +++ b/engines/titanic/game/transport/lift_indicator.h @@ -0,0 +1,63 @@ +/* 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_LIFT_INDICATOR_H +#define TITANIC_LIFT_INDICATOR_H + +#include "titanic/game/transport/lift.h" +#include "titanic/messages/messages.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CLiftindicator : public CLift { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool PETActivateMsg(CPETActivateMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool TimerMsg(CTimerMsg *msg); +private: + int _fieldFC; + Point _indicatorPos; + int _start; + int _end; +public: + CLASSDEF; + CLiftindicator(); + + /** + * 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_LIFT_INDICATOR_H */ diff --git a/engines/titanic/game/transport/pellerator.cpp b/engines/titanic/game/transport/pellerator.cpp new file mode 100644 index 0000000000..5bc2423478 --- /dev/null +++ b/engines/titanic/game/transport/pellerator.cpp @@ -0,0 +1,365 @@ +/* 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/game/transport/pellerator.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +static const char *const WAVE_NAMES[10] = { + "z#465.wav", "z#456.wav", "z#455.wav", "z#453.wav", + "z#452.wav", "NoStandingInFunnyWays", "z#450.wav", + "z#449.wav", "z#435.wav", "z#434.wav" +}; + +BEGIN_MESSAGE_MAP(CPellerator, CTransport) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +int CPellerator::_soundHandle; +int CPellerator::_destination; + +CPellerator::CPellerator() : CTransport() { +} + +void CPellerator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_destination, indent); + + CTransport::save(file, indent); +} + +void CPellerator::load(SimpleFile *file) { + file->readNumber(); + _soundHandle = file->readNumber(); + _destination = file->readNumber(); + + CTransport::load(file); +} + +bool CPellerator::StatusChangeMsg(CStatusChangeMsg *msg) { + setVisible(true); + playGlobalSound("z#74.wav", -2, true, true, 0); + int classNum = getPassengerClass(); + int newDest = msg->_newStatus; + + if (msg->_newStatus == _destination) { + petDisplayMessage(1, "You are already at your chosen destination."); + } else if (classNum == 3 || (msg->_newStatus > 4 && classNum != 1)) { + petDisplayMessage(1, "Passengers of your class are not permitted to enter this area."); + } else if (newDest > _destination) { + CString name = getName(); + changeView(name == "PelleratorObject2" ? + "Pellerator.Node 1.N" : "Pellerator.Node 1.S"); + + if (name == "PelleratorObject") { + for (; _destination < newDest; ++_destination) { + switch (_destination) { + case 0: + case 1: + playMovie(315, 323, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(299, 304, 0); + playMovie(305, 313, MOVIE_GAMESTATE); + break; + + case 2: + playMovie(315, 323, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(299, 304, 0); + for (int idx = 0; idx < 5; ++idx) + playMovie(253, 263, 0); + playMovie(153, 197, 0); + for (int idx = 0; idx < 5; ++idx) + playMovie(253, 263, 0); + playMovie(290, 293, MOVIE_GAMESTATE); + break; + + case 4: + playMovie(267, 270, 0); + for (int idx = 0; idx < 5; ++idx) + playMovie(253, 263, 0); + playMovie(3, 71, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(253, 263, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + break; + + case 5: + playMovie(315, 323, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(299, 304, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(253, 263, 0); + playMovie(3, 71, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(299, 304, 0); + + } + } + } else { + for (; _destination < newDest; ++_destination) { + switch (_destination) { + case 0: + case 1: + playMovie(315, 323, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(299, 304, 0); + playMovie(305, 313, MOVIE_GAMESTATE); + break; + + case 2: + playMovie(315, 323, 0); + for (int idx = 0; idx < 4; ++idx) + playMovie(299, 304, 0); + for (int idx = 0; idx < 15; ++idx) + playMovie(245, 255, 0); + playMovie(264, 267, MOVIE_GAMESTATE); + ++_destination; + break; + + case 4: + playMovie(241, 244, 0); + for (int idx = 0; idx < 15; ++idx) + playMovie(245, 255, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + break; + + case 5: + playMovie(315, 323, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(229, 304, 0); + for (int idx = 0; idx < 12; ++idx) + playMovie(245, 255, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(299, 304, 0); + playMovie(305, 313, MOVIE_GAMESTATE); + break; + + default: + break; + } + } + } + + playMovie(264, 264, MOVIE_NOTIFY_OBJECT); + _destination = newDest; + } else if (newDest < _destination) { + CString name = getName(); + changeView(name == "PelleratorObject2" ? + "Pellerator.Node 1.N" : "Pellerator.Node 1.S"); + + if (name == "PelleratorObject") { + for (; _destination > newDest; --_destination) { + switch (_destination) { + case 0: + case 1: + playMovie(351, 359, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + break; + + case 3: + playMovie(241, 244, 0); + for (int idx = 0; idx < 5; ++idx) + playMovie(245, 255, 0); + playMovie(197, 239, 0); + for (int idx = 0; idx < 5; ++idx) + playMovie(245, 255, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + --_destination; + break; + + case 4: + playMovie(315, 323, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(299, 304, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(245, 255, 0); + playMovie(78, 149, 0); + for (int idx = 0; idx < 5; ++idx) + playMovie(245, 255, 0); + playMovie(264, 267, MOVIE_GAMESTATE); + break; + + case 5: + playMovie(351, 359, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(336, 341, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(245, 255, 0); + playMovie(78, 149, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + break; + + default: + break; + } + } + } else { + for (; _destination > newDest; --_destination) { + switch (_destination) { + case 0: + case 1: + playMovie(351, 359, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + break; + + case 3: + playMovie(267, 270, 0); + for (int idx = 0; idx < 15; ++idx) + playMovie(253, 263, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + --_destination; + break; + + case 4: + playMovie(315, 323, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(299, 304, 0); + for (int idx = 0; idx < 15; ++idx) + playMovie(253, 263, 0); + playMovie(290, 293, MOVIE_GAMESTATE); + break; + + case 5: + playMovie(351, 359, 0); + for (int idx = 0; idx < 7; ++idx) + playMovie(336, 341, 0); + for (int idx = 0; idx < 13; ++idx) + playMovie(253, 263, 0); + for (int idx = 0; idx < 3; ++idx) + playMovie(336, 341, 0); + playMovie(342, 348, MOVIE_GAMESTATE); + break; + + default: + break; + } + } + } + + playMovie(264, 264, MOVIE_NOTIFY_OBJECT); + _destination = newDest; + } + + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _destination; + statusMsg.execute("ExitPellerator"); + + return true; +} + +bool CPellerator::EnterRoomMsg(CEnterRoomMsg *msg) { + if (isEquals("PelleratorObject")) { + for (int idx = 0; idx < 10; ++idx) + loadSound(WAVE_NAMES[idx]); + addTimer(10000); + } + + CString name = msg->_oldRoom ? msg->_oldRoom->getName() : ""; + int oldVal = _destination; + + if (name.empty()) { + _destination = 4; + oldVal = 4; + } else if (name == "PromenadeDeck") { + _destination = 0; + } else if (name == "MusicRoomLobby") { + _destination = 1; + } else if (name == "Bar") { + _destination = 2; + } else if (name == "TopOfWell") { + _destination = 4; + } else if (name == "1stClassRestaurant") { + _destination = 5; + } else if (name == "Arboretum" || name == "FrozenArboretum") { + _destination = 6; + } + + if (_destination != oldVal) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = _destination; + statusMsg.execute("ExitPellerator"); + } + + loadFrame(264); + return true; +} + +bool CPellerator::MovieEndMsg(CMovieEndMsg *msg) { + setVisible(false); + stopGlobalSound(true, -1); + + switch (_destination) { + case 0: + _soundHandle = queueSound("z#429.wav", _soundHandle); + break; + case 1: + _soundHandle = queueSound("z#430.wav", _soundHandle); + break; + case 2: + _soundHandle = queueSound("z#431.wav", _soundHandle); + break; + case 4: + _soundHandle = queueSound("z#428.wav", _soundHandle); + break; + case 5: + _soundHandle = queueSound("z#433.wav", _soundHandle); + break; + case 6: + _soundHandle = queueSound("z#432.wav", _soundHandle); + break; + default: + break; + } + + return true; +} + +bool CPellerator::TimerMsg(CTimerMsg *msg) { + if (compareRoomNameTo("Pellerator")) { + _soundHandle = queueSound(WAVE_NAMES[getRandomNumber(9)], _soundHandle); + addTimer(20000 + getRandomNumber(10000)); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/pellerator.h b/engines/titanic/game/transport/pellerator.h new file mode 100644 index 0000000000..c634f435cc --- /dev/null +++ b/engines/titanic/game/transport/pellerator.h @@ -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. +* +*/ + +#ifndef TITANIC_PELLERATOR_H +#define TITANIC_PELLERATOR_H + +#include "titanic/game/transport/transport.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CPellerator : public CTransport { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool TimerMsg(CTimerMsg *msg); +public: + static int _soundHandle; + static int _destination; +public: + CLASSDEF; + CPellerator(); + + /** + * 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_PELLERATOR_H */ diff --git a/engines/titanic/game/transport/service_elevator.cpp b/engines/titanic/game/transport/service_elevator.cpp new file mode 100644 index 0000000000..1ea8d14e36 --- /dev/null +++ b/engines/titanic/game/transport/service_elevator.cpp @@ -0,0 +1,61 @@ +/* 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/game/transport/service_elevator.h" + +namespace Titanic { + +int CServiceElevator::_v1; +int CServiceElevator::_v2; +int CServiceElevator::_v3; + +CServiceElevator::CServiceElevator() : CTransport(), + _fieldF8(0), _fieldFC(0), _field100(0), _field104(0) { +} + +void CServiceElevator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_v3, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_fieldFC, indent); + file->writeNumberLine(_field100, indent); + file->writeNumberLine(_field104, indent); + + CTransport::save(file, indent); +} + +void CServiceElevator::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + _v3 = file->readNumber(); + _fieldF8 = file->readNumber(); + _fieldFC = file->readNumber(); + _field100 = file->readNumber(); + _field104 = file->readNumber(); + + CTransport::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/service_elevator.h b/engines/titanic/game/transport/service_elevator.h new file mode 100644 index 0000000000..b2c135021a --- /dev/null +++ b/engines/titanic/game/transport/service_elevator.h @@ -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. + * + */ + +#ifndef TITANIC_SERVICE_ELEVATOR_H +#define TITANIC_SERVICE_ELEVATOR_H + +#include "titanic/game/transport/transport.h" + +namespace Titanic { + +class CServiceElevator : public CTransport { +private: + static int _v1; + static int _v2; + static int _v3; + + int _fieldF8; + int _fieldFC; + int _field100; + int _field104; +public: + CLASSDEF; + CServiceElevator(); + + /** + * 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_SERVICE_ELEVATOR_H */ diff --git a/engines/titanic/game/transport/transport.cpp b/engines/titanic/game/transport/transport.cpp new file mode 100644 index 0000000000..6fe45c2fc8 --- /dev/null +++ b/engines/titanic/game/transport/transport.cpp @@ -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. + * + */ + +#include "titanic/game/transport/transport.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CTransport, CMobile); + +CTransport::CTransport() : CMobile(), _string1("*.*.*") { +} + +void CTransport::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + + CMobile::save(file, indent); +} + +void CTransport::load(SimpleFile *file) { + file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + + CMobile::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/transport/transport.h b/engines/titanic/game/transport/transport.h new file mode 100644 index 0000000000..d87251212a --- /dev/null +++ b/engines/titanic/game/transport/transport.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_TRANSPORT_H +#define TITANIC_TRANSPORT_H + +#include "titanic/npcs/mobile.h" + +namespace Titanic { + +class CTransport : public CMobile { + DECLARE_MESSAGE_MAP; +public: + CString _string1; + CString _string2; +public: + CLASSDEF; + CTransport(); + + /** + * 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_TRANSPORT_H */ diff --git a/engines/titanic/game/up_lighter.cpp b/engines/titanic/game/up_lighter.cpp new file mode 100644 index 0000000000..f03b8f37a0 --- /dev/null +++ b/engines/titanic/game/up_lighter.cpp @@ -0,0 +1,56 @@ +/* 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/game/up_lighter.h" + +namespace Titanic { + +CUpLighter::CUpLighter() : CDropTarget(), _field118(0), + _field11C(0), _field120(0), _field124(0) { +} + +void CUpLighter::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field118, indent); + file->writeNumberLine(_field11C, indent); + file->writeNumberLine(_field120, indent); + file->writeNumberLine(_field124, indent); + + CDropTarget::save(file, indent); +} + +void CUpLighter::load(SimpleFile *file) { + file->readNumber(); + _field118 = file->readNumber(); + _field11C = file->readNumber(); + _field120 = file->readNumber(); + _field124 = file->readNumber(); + + CDropTarget::load(file); +} + +bool CUpLighter::EnterRoomMsg(CEnterRoomMsg *msg) { + warning("CUpLighter::handleEvent"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/up_lighter.h b/engines/titanic/game/up_lighter.h new file mode 100644 index 0000000000..2367e41314 --- /dev/null +++ b/engines/titanic/game/up_lighter.h @@ -0,0 +1,55 @@ +/* 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_UP_LIGHTER_H +#define TITANIC_UP_LIGHTER_H + +#include "titanic/core/drop_target.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CUpLighter : public CDropTarget { + bool EnterRoomMsg(CEnterRoomMsg *msg); +private: + int _field118; + int _field11C; + int _field120; + int _field124; +public: + CLASSDEF; + CUpLighter(); + + /** + * 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_UP_LIGHTER_H */ diff --git a/engines/titanic/game/useless_lever.cpp b/engines/titanic/game/useless_lever.cpp new file mode 100644 index 0000000000..e48ad55a71 --- /dev/null +++ b/engines/titanic/game/useless_lever.cpp @@ -0,0 +1,37 @@ +/* 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/game/useless_lever.h" + +namespace Titanic { + +void CUselessLever::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleButton::save(file, indent); +} + +void CUselessLever::load(SimpleFile *file) { + file->readNumber(); + CToggleButton::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/useless_lever.h b/engines/titanic/game/useless_lever.h new file mode 100644 index 0000000000..27397de216 --- /dev/null +++ b/engines/titanic/game/useless_lever.h @@ -0,0 +1,47 @@ +/* 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_USELESS_LEVER_H +#define TITANIC_USELESS_LEVER_H + +#include "titanic/gfx/toggle_button.h" + +namespace Titanic { + +class CUselessLever : public CToggleButton { +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_UP_LIGHTER_H */ diff --git a/engines/titanic/game/volume_control.cpp b/engines/titanic/game/volume_control.cpp new file mode 100644 index 0000000000..c6b0e414ae --- /dev/null +++ b/engines/titanic/game/volume_control.cpp @@ -0,0 +1,53 @@ +/* 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/game/volume_control.h" + +namespace Titanic { + +CVolumeControl::CVolumeControl() : CGameObject() { +} + +void CVolumeControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeQuotedLine(_string1, indent); + file->writeNumberLine(_fieldCC, indent); + + CGameObject::save(file, indent); +} + +void CVolumeControl::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _string1 = file->readString(); + _fieldCC = file->readNumber(); + + CGameObject::load(file); +} + +bool CVolumeControl::EnterNodeMsg(CEnterNodeMsg *msg) { + warning("CVolumeControl::handleEvent"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/volume_control.h b/engines/titanic/game/volume_control.h new file mode 100644 index 0000000000..dcc6f63781 --- /dev/null +++ b/engines/titanic/game/volume_control.h @@ -0,0 +1,54 @@ +/* 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_VOLUME_CONTROL_H +#define TITANIC_VOLUME_CONTROL_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CVolumeControl : public CGameObject { + bool EnterNodeMsg(CEnterNodeMsg *msg); +private: + int _fieldBC; + CString _string1; + int _fieldCC; +public: + CLASSDEF; + CVolumeControl(); + + /** + * 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_VOLUME_CONTROL_H */ diff --git a/engines/titanic/game/wheel_button.cpp b/engines/titanic/game/wheel_button.cpp new file mode 100644 index 0000000000..19c42a8807 --- /dev/null +++ b/engines/titanic/game/wheel_button.cpp @@ -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. + * + */ + +#include "titanic/game/wheel_button.h" + +namespace Titanic { + +CWheelButton::CWheelButton() : CBackground(), + _fieldE0(0), _fieldE4(0), _fieldE8(0) { +} + +void CWheelButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + + CBackground::save(file, indent); +} + +void CWheelButton::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/wheel_button.h b/engines/titanic/game/wheel_button.h new file mode 100644 index 0000000000..cb089a660f --- /dev/null +++ b/engines/titanic/game/wheel_button.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_WHEEL_BUTTON_H +#define TITANIC_WHEEL_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CWheelButton : public CBackground { +public: + int _fieldE0; + int _fieldE4; + int _fieldE8; +public: + CLASSDEF; + CWheelButton(); + + /** + * 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_WHEEL_BUTTON_H */ diff --git a/engines/titanic/game/wheel_hotspot.cpp b/engines/titanic/game/wheel_hotspot.cpp new file mode 100644 index 0000000000..f9af594cd5 --- /dev/null +++ b/engines/titanic/game/wheel_hotspot.cpp @@ -0,0 +1,43 @@ +/* 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/game/wheel_hotspot.h" + +namespace Titanic { + +void CWheelHotSpot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + + CBackground::save(file, indent); +} + +void CWheelHotSpot::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/wheel_hotspot.h b/engines/titanic/game/wheel_hotspot.h new file mode 100644 index 0000000000..364fe9a060 --- /dev/null +++ b/engines/titanic/game/wheel_hotspot.h @@ -0,0 +1,51 @@ +/* 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_WHEEL_HOTSPOT_H +#define TITANIC_WHEEL_HOTSPOT_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CWheelHotSpot : public CBackground { +public: + int _fieldE0; + int _fieldE4; +public: + CLASSDEF; + CWheelHotSpot() : CBackground(), _fieldE0(0), _fieldE4(0) {} + + /** + * 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_WHEEL_HOTSPOT_H */ diff --git a/engines/titanic/game/wheel_spin.cpp b/engines/titanic/game/wheel_spin.cpp new file mode 100644 index 0000000000..daa9918e29 --- /dev/null +++ b/engines/titanic/game/wheel_spin.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/game/wheel_spin.h" + +namespace Titanic { + +void CWheelSpin::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CBackground::save(file, indent); +} + +void CWheelSpin::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/wheel_spin.h b/engines/titanic/game/wheel_spin.h new file mode 100644 index 0000000000..509db1a4bf --- /dev/null +++ b/engines/titanic/game/wheel_spin.h @@ -0,0 +1,50 @@ +/* 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_WHEEL_SPIN_H +#define TITANIC_WHEEL_SPIN_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CWheelSpin : public CBackground { +public: + int _value; +public: + CLASSDEF; + CWheelSpin() : CBackground(), _value(0) {} + + /** + * 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_WHEEL_SPIN_H */ diff --git a/engines/titanic/game/wheel_spin_horn.cpp b/engines/titanic/game/wheel_spin_horn.cpp new file mode 100644 index 0000000000..b01cc678df --- /dev/null +++ b/engines/titanic/game/wheel_spin_horn.cpp @@ -0,0 +1,43 @@ +/* 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/game/wheel_spin_horn.h" + +namespace Titanic { + +void CWheelSpinHorn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + + CWheelSpin::save(file, indent); +} + +void CWheelSpinHorn::load(SimpleFile *file) { + file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + + CWheelSpin::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game/wheel_spin_horn.h b/engines/titanic/game/wheel_spin_horn.h new file mode 100644 index 0000000000..21182253b3 --- /dev/null +++ b/engines/titanic/game/wheel_spin_horn.h @@ -0,0 +1,50 @@ +/* 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_WHEEL_SPIN_HORN_H +#define TITANIC_WHEEL_SPIN_HORN_H + +#include "titanic/game/wheel_spin.h" + +namespace Titanic { + +class CWheelSpinHorn : public CWheelSpin { +public: + CString _string1; + CString _string2; +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_WHEEL_SPIN_HORN_H */ diff --git a/engines/titanic/game_location.cpp b/engines/titanic/game_location.cpp new file mode 100644 index 0000000000..3a1d0c9e48 --- /dev/null +++ b/engines/titanic/game_location.cpp @@ -0,0 +1,115 @@ +/* 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/game_location.h" +#include "titanic/game_manager.h" +#include "titanic/game_state.h" +#include "titanic/core/game_object.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +#define STARTING_ROOM 3 +#define STARTING_NODE 1 +#define STARTING_VIEW 4 + +CGameLocation::CGameLocation(CGameState *owner) : _gameState(owner), + _view(nullptr), _roomNumber(STARTING_ROOM), + _nodeNumber(STARTING_NODE), _viewNumber(STARTING_VIEW) { +} + +void CGameLocation::save(SimpleFile *file) const { + file->writeNumber(_roomNumber); + file->writeNumber(_nodeNumber); + file->writeNumber(_viewNumber); +} + +void CGameLocation::load(SimpleFile *file) { + _view = nullptr; + _roomNumber = file->readNumber(); + _nodeNumber = file->readNumber(); + _viewNumber = file->readNumber(); +} + +void CGameLocation::setView(CViewItem *view) { + if (_view) { + for (CTreeItem *treeItem = _view; treeItem; + treeItem = treeItem->scan(_view)) { + CGameObject *obj = dynamic_cast<CGameObject *>(treeItem); + if (obj) + obj->stopMovie(); + } + } + + _view = view; + if (_view) { + _viewNumber = _view->_viewNumber; + _nodeNumber = _view->findNode()->_nodeNumber; + _roomNumber = _view->findRoom()->_roomNumber; + } else { + _viewNumber = _nodeNumber = _roomNumber = -1; + } +} + +CViewItem *CGameLocation::getView() { + if (!_view) { + CGameManager *gm = _gameState->_gameManager; + _view = gm->_project->findView(_roomNumber, _nodeNumber, _viewNumber); + + if (!_view) { + // Fallback if view not found + _view = gm->_project->findView(STARTING_ROOM, + STARTING_NODE, STARTING_VIEW); + + if (!_view) { + // Fallback for the fallback + for (int idx = 0; idx < 99 && !_view; ++idx) { + _view = gm->_project->findView(idx, 1, 1); + } + } + } + } + + if (!_view) { + // Okay seriously, yet another fallback if view not found + _viewNumber = _nodeNumber = _roomNumber = -1; + _view = nullptr; + } else { + _viewNumber = _view->_viewNumber; + _nodeNumber = _view->findNode()->_nodeNumber; + _roomNumber = _view->findRoom()->_roomNumber; + } + + return _view; +} + +CNodeItem *CGameLocation::getNode() { + CViewItem *view = getView(); + return !view ? nullptr : view->findNode(); +} + +CRoomItem *CGameLocation::getRoom() { + CViewItem *view = getView(); + return !view ? nullptr : view->findRoom(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game_location.h b/engines/titanic/game_location.h new file mode 100644 index 0000000000..f145d36340 --- /dev/null +++ b/engines/titanic/game_location.h @@ -0,0 +1,79 @@ +/* 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_GAME_LOCATION_H +#define TITANIC_GAME_LOCATION_H + +#include "titanic/support/simple_file.h" +#include "titanic/core/node_item.h" +#include "titanic/core/room_item.h" +#include "titanic/core/view_item.h" + +namespace Titanic { + +class CGameState; + +class CGameLocation { +private: + CGameState *_gameState; + CViewItem *_view; + + int _roomNumber; + int _nodeNumber; + int _viewNumber; +public: + CGameLocation(CGameState *owner); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file) const; + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file); + + /** + * Set the current view + */ + void setView(CViewItem *view); + + /** + * Get the current view + */ + CViewItem *getView(); + + /** + * Get the current node + */ + CNodeItem *getNode(); + + /** + * Get the current room + */ + CRoomItem *getRoom(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_GAME_LOCATION_H */ diff --git a/engines/titanic/game_manager.cpp b/engines/titanic/game_manager.cpp new file mode 100644 index 0000000000..73ec5de993 --- /dev/null +++ b/engines/titanic/game_manager.cpp @@ -0,0 +1,313 @@ +/* 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/titanic.h" +#include "titanic/game_manager.h" +#include "titanic/game_view.h" +#include "titanic/support/screen_manager.h" +#include "titanic/core/project_item.h" +#include "titanic/messages/messages.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +CGameManager::CGameManager(CProjectItem *project, CGameView *gameView, Audio::Mixer *mixer): + _project(project), _gameView(gameView), _trueTalkManager(this), + _inputHandler(this), _inputTranslator(&_inputHandler), + _gameState(this), _sound(this, mixer), _musicRoom(this), + _treeItem(nullptr), _soundMaker(nullptr), _movieRoom(nullptr), + _dragItem(nullptr), _field54(0), _lastDiskTicksCount(0), _tickCount2(0) { + + CTimeEventInfo::_nextId = 0; + _movie = nullptr; + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); + _project->setGameManager(this); + g_vm->_filesManager->setGameManager(this); +} + +CGameManager::~CGameManager() { + delete _movie; + delete _movieSurface; + destroyTreeItem(); + + _project->resetGameManager(); +} + +void CGameManager::destroyTreeItem() { + if (_treeItem) { + _treeItem->destroyAll(); + _treeItem = nullptr; + } +} + +void CGameManager::save(SimpleFile *file) { + file->writeNumber(_lastDiskTicksCount); + _gameState.save(file); + _timers.save(file, 0); + _trueTalkManager.save(file); + _sound.save(file); +} + +void CGameManager::load(SimpleFile *file) { + file->readNumber(); + + _gameState.load(file); + _timers.load(file); + _trueTalkManager.load(file); + _sound.load(file); +} + +void CGameManager::preLoad() { + updateDiskTicksCount(); + _timers.destroyContents(); + _soundMaker = nullptr; + + _trueTalkManager.preLoad(); + _sound.preLoad(); +} + +void CGameManager::postLoad(CProjectItem *project) { + if (_gameView) { + _gameView->postLoad(); + + if (!_gameView->_surface) { + CViewItem *view = getView(); + if (view) + _gameView->setView(view); + } + } + + // Signal to anything interested that the game has been loaded + CLoadSuccessMsg msg(_lastDiskTicksCount - _tickCount2); + msg.execute(project, nullptr, MSGFLAG_SCAN); + + // Signal to any registered timers + _timers.postLoad(_lastDiskTicksCount, _project); + + // Signal the true talk manager and sound + _trueTalkManager.postLoad(); + _sound.postLoad(); +} + +void CGameManager::preSave(CProjectItem *project) { + // Generate a message that a save is being done + updateDiskTicksCount(); + CPreSaveMsg msg(_lastDiskTicksCount); + msg.execute(project, nullptr, MSGFLAG_SCAN); + + // Notify sub-objects of the save + _timers.preSave(_lastDiskTicksCount); + _trueTalkManager.preSave(); + _sound.preSave(); +} + +void CGameManager::postSave() { + _timers.postSave(); + _trueTalkManager.postSave(); + _sound.postSave(); +} + +void CGameManager::initBounds() { + _bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); +} + +void CGameManager::roomTransition(CRoomItem *oldRoom, CRoomItem *newRoom) { + delete _movie; + _movie = nullptr; + + CResourceKey movieKey = (oldRoom == newRoom) ? oldRoom->getTransitionMovieKey() : + oldRoom->getExitMovieKey(); + CString filename = movieKey.exists(); + if (g_vm->_filesManager->fileExists(filename)) { + _movieSurface->freeSurface(); + _movie = g_vm->_movieManager.createMovie(filename, _movieSurface); + } +} + +void CGameManager::playClip(CMovieClip *clip, CRoomItem *oldRoom, CRoomItem *newRoom) { + if (oldRoom != newRoom || newRoom != _movieRoom || !_movie) + roomTransition(oldRoom, newRoom); + + if (clip && clip->_startFrame != clip->_endFrame && _movie) { + // Clip details specifying a sub-section of movie to play + Rect tempRect(20, 10, SCREEN_WIDTH - 20, 350); + + lockInputHandler(); + CScreenManager::_screenManagerPtr->_mouseCursor->hide(); + _movie->playCutscene(tempRect, clip->_startFrame, clip->_endFrame); + CScreenManager::_screenManagerPtr->_mouseCursor->show(); + unlockInputHandler(); + } +} + +void CGameManager::update() { + updateMovies(); + frameMessage(getRoom()); + _timers.update(g_vm->_events->getTicksCount()); + _trueTalkManager.removeCompleted(); + _trueTalkManager.update2(); + CScreenManager::_screenManagerPtr->_mouseCursor->update(); + + CViewItem *view = getView(); + if (view) { + // Expand the game manager's bounds to encompass all the view's items + for (CTreeItem *item = view; item; item = item->scan(view)) { + Rect r = item->getBounds(); + if (!r.isEmpty()) + _bounds.extend(r); + } + + // Also include the PET control in the bounds + if (_project) { + CPetControl *pet = _project->getPetControl(); + if (pet) + _bounds.extend(pet->getBounds()); + } + + // And the text cursor + CScreenManager *screenManager = CScreenManager::_screenManagerPtr; + CTextCursor *textCursor = screenManager->_textCursor; + if (textCursor && textCursor->_active) + _bounds.extend(textCursor->getCursorBounds()); + + // Set the surface bounds + screenManager->setSurfaceBounds(SURFACE_BACKBUFFER, _bounds); + + // Handle redrawing the view + if (!_bounds.isEmpty()) { + _gameView->draw(_bounds); + _bounds = Rect(); + } + + _gameState.checkForViewChange(); + } +} + +void CGameManager::updateMovies() { + // Initial iteration to mark all the movies as not yet handled + for (CMovieList::iterator i = CMovie::_playingMovies->begin(); + i != CMovie::_playingMovies->end(); ++i) + (*i)->_handled = false; + + bool repeatFlag; + do { + repeatFlag = false; + + // Scan for a movie to process + for (CMovieList::iterator i = CMovie::_playingMovies->begin(); + i != CMovie::_playingMovies->end(); ++i) { + CMovie *movie = *i; + if (movie->_handled) + continue; + + CMovieEventList eventsList; + if (!movie->handleEvents(eventsList)) + movie->removeFromPlayingMovies(); + + while (!eventsList.empty()) { + CMovieEvent *movieEvent = eventsList.front(); + + switch (movieEvent->_type) { + case MET_MOVIE_END: { + CMovieEndMsg endMsg(movieEvent->_startFrame, movieEvent->_endFrame); + endMsg.execute(movieEvent->_gameObject); + break; + } + + case MET_FRAME: { + CMovieFrameMsg frameMsg(movieEvent->_initialFrame, 0); + frameMsg.execute(movieEvent->_gameObject); + break; + } + + default: + break; + } + + eventsList.remove(movieEvent); + } + + // Flag the movie as having been handled + movie->_handled = true; + repeatFlag = true; + break; + } + } while (repeatFlag); +} + +void CGameManager::updateDiskTicksCount() { + _lastDiskTicksCount = g_vm->_events->getTicksCount(); +} + +void CGameManager::viewChange() { + delete _movie; + delete _movieSurface; + + _movie = nullptr; + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); + _trueTalkManager.clear(); + + for (CTreeItem *treeItem = _project; treeItem; treeItem = treeItem->scan(_project)) + treeItem->viewChange(); + + initBounds(); +} + +void CGameManager::frameMessage(CRoomItem *room) { + if (room) { + // Signal the next frame + CFrameMsg frameMsg(g_vm->_events->getTicksCount()); + frameMsg.execute(room, nullptr, MSGFLAG_SCAN); + + if (!_soundMaker) { + // Check for a sound maker in the room + _soundMaker = dynamic_cast<CBackgroundSoundMaker *>( + _project->findByName("zBackgroundSoundMaker")); + } + + // If there's a sound maker, dispatch the event to it as well + if (_soundMaker) + frameMsg.execute(_soundMaker); + } +} + +void CGameManager::extendBounds(const Rect &r) { + if (_bounds.isEmpty()) + _bounds = r; + else + _bounds.combine(r); +} + +CScreenManager *CGameManager::setScreenManager() const { + return CScreenManager::setCurrent(); +} + +CString CGameManager::getFullViewName() { + CViewItem *view = getView(); + CNodeItem *node = view->findNode(); + CRoomItem *room = node->findRoom(); + + return CString::format("%s.%s.%s", room->getName().c_str(), + node->getName().c_str(), view->getName().c_str()); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game_manager.h b/engines/titanic/game_manager.h new file mode 100644 index 0000000000..262ea0169b --- /dev/null +++ b/engines/titanic/game_manager.h @@ -0,0 +1,217 @@ +/* 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_GAME_MANAGER_H +#define TITANIC_GAME_MANAGER_H + +#include "common/scummsys.h" +#include "titanic/game_state.h" +#include "titanic/input_handler.h" +#include "titanic/input_translator.h" +#include "titanic/support/simple_file.h" +#include "titanic/support/time_event_info.h" +#include "titanic/support/video_surface.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/sound/background_sound_maker.h" +#include "titanic/sound/music_room.h" +#include "titanic/sound/sound.h" + +namespace Titanic { + +class CProjectItem; +class CGameView; + +class CGameManager { +private: + CTrueTalkManager _trueTalkManager; + CTimeEventInfoList _timers; + CTreeItem *_treeItem; + CBackgroundSoundMaker *_soundMaker; + CMovie *_movie; + CRoomItem *_movieRoom; + int _field54; + CVideoSurface *_movieSurface; + uint _lastDiskTicksCount; + uint _tickCount2; +private: + /** + * Generates a message for the next game frame + */ + void frameMessage(CRoomItem *room); + + /** + * Handles any ongoing movie playback + */ + void updateMovies(); + + /** + * Handles a room transition + */ + void roomTransition(CRoomItem *oldRoom, CRoomItem *newRoom); +public: + CProjectItem *_project; + CGameView *_gameView; + CGameState _gameState; + Rect _bounds; + CInputHandler _inputHandler; + CInputTranslator _inputTranslator; + CTreeItem *_dragItem; + CMusicRoom _musicRoom; + CSound _sound; +public: + CGameManager(CProjectItem *project, CGameView *gameView, Audio::Mixer *mixer); + ~CGameManager(); + + /** + * Destroys and allocated tree item + */ + void destroyTreeItem(); + + /** + * Save data to a save file + */ + void save(SimpleFile *file); + + /** + * Load data from a save file + */ + void load(SimpleFile *file); + + /** + * Called when a game is about to be loaded + */ + void preLoad(); + + /** + * Called after loading a game has finished + */ + void postLoad(CProjectItem *project); + + /** + * Called when a game is about to be saved + */ + void preSave(CProjectItem *project); + + /** + * Called when a game has finished being saved + */ + void postSave(); + + /** + * Updates the game time when the last disk access started + */ + void updateDiskTicksCount(); + + /** + * Gets the current view + */ + CViewItem *getView() { return _gameState._gameLocation.getView(); } + + /** + * Gets the current room node + */ + CNodeItem *getNode() { return _gameState._gameLocation.getNode(); } + + /** + * Gets the current room + */ + CRoomItem *getRoom() { return _gameState._gameLocation.getRoom(); } + + /** + * Lock the input handler + */ + void lockInputHandler() { _inputHandler.incLockCount(); } + + /** + * Unlock the input handler + */ + void unlockInputHandler() { _inputHandler.decLockCount(); } + + /** + * Set default screen bounds + */ + void initBounds(); + + /** + * Plays a movie clip + */ + void playClip(CMovieClip *clip, CRoomItem *oldRoom, CRoomItem *newRoom); + + /** + * Main frame update method for the game + */ + void update(); + + /** + * Called when the view changes + */ + void viewChange(); + + bool test54() const { return !_field54; } + + void inc54() { ++_field54; } + + void dec54() { --_field54; } + + /** + * Extends the bounds of the currently affected game display area + * to include the passed rect + */ + void extendBounds(const Rect &r); + + /** + * Set and return the current screen manager + */ + CScreenManager *setScreenManager() const; + + /** + * Adds a timer + */ + void addTimer(CTimeEventInfo *timer) { _timers.push_back(timer); } + + /** + * Stops a timer + */ + void stopTimer(uint id) { _timers.stop(id); } + + /** + * Flags whether the timer will be persisent across save & loads + */ + void setTimerPersisent(uint id, bool flag) { + _timers.setPersisent(id, flag); + } + + /** + * Return the true talk manager + */ + CTrueTalkManager *getTalkManager() { return &_trueTalkManager; } + + /** + * Return the full Id of the current view in a + * room.node.view tuplet form + */ + CString getFullViewName(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_GAME_MANAGER_H */ diff --git a/engines/titanic/game_state.cpp b/engines/titanic/game_state.cpp new file mode 100644 index 0000000000..5628161558 --- /dev/null +++ b/engines/titanic/game_state.cpp @@ -0,0 +1,168 @@ +/* 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/game_state.h" +#include "titanic/titanic.h" +#include "titanic/game_manager.h" +#include "titanic/support/screen_manager.h" + +namespace Titanic { + +bool CGameStateMovieList::clear() { + for (CGameStateMovieList::iterator i = begin(); i != end(); ) { + CMovieListItem *movieItem = *i; + + if (movieItem->_item->isActive()) { + ++i; + } else { + i = erase(i); + delete movieItem; + } + } + + return !empty(); +} + +/*------------------------------------------------------------------------*/ + +CGameState::CGameState(CGameManager *gameManager) : + _gameManager(gameManager), _gameLocation(this), + _passengerClass(0), _priorClass(0), _mode(GSMODE_NONE), + _field14(0), _petActive(false), _field1C(false), _quitGame(false), + _field24(0), _nodeChangeCtr(0), _nodeEnterTicks(0), _field38(0) { +} + +void CGameState::save(SimpleFile *file) const { + file->writeNumber(_petActive); + file->writeNumber(_passengerClass); + file->writeNumber(_priorClass); + file->writeNumber(_field14); + file->writeNumber(_field24); + file->writeNumber(_field38); + _gameLocation.save(file); + file->writeNumber(_field1C); +} + +void CGameState::load(SimpleFile *file) { + _petActive = file->readNumber() != 0; + _passengerClass = file->readNumber(); + _priorClass = file->readNumber(); + _field14 = file->readNumber(); + _field24 = file->readNumber(); + _field38 = file->readNumber(); + _gameLocation.load(file); + + _field1C = file->readNumber(); + _nodeChangeCtr = 0; + _nodeEnterTicks = 0; +} + +void CGameState::setMode(GameStateMode newMode) { + CScreenManager *sm = CScreenManager::_screenManagerPtr; + + if (newMode == GSMODE_CUTSCENE && newMode != _mode) { + if (_gameManager) + _gameManager->lockInputHandler(); + + if (sm && sm->_mouseCursor) + sm->_mouseCursor->hide(); + + } else if (newMode != GSMODE_CUTSCENE && newMode != _mode) { + if (sm && sm->_mouseCursor) + sm->_mouseCursor->show(); + + if (_gameManager) + _gameManager->unlockInputHandler(); + } + + _mode = newMode; +} + +void CGameState::enterNode() { + ++_nodeChangeCtr; + _nodeEnterTicks = g_vm->_events->getTicksCount(); +} + +void CGameState::enterView() { + CViewItem *oldView = _gameLocation.getView(); + CViewItem *newView = _movieList._view; + oldView->preEnterView(newView); + + _gameManager->_gameView->setView(newView); + CRoomItem *oldRoom = oldView->findNode()->findRoom(); + CRoomItem *newRoom = newView->findNode()->findRoom(); + _gameManager->playClip(_movieList._movieClip, oldRoom, newRoom); + + _gameManager->_sound.preEnterView(newView, newRoom != oldRoom); + _gameManager->dec54(); + oldView->enterView(newView); + + _movieList._view = nullptr; + _movieList._movieClip = nullptr; +} + +void CGameState::triggerLink(CLinkItem *link) { + changeView(link->getDestView(), link->getClip()); +} + +void CGameState::changeView(CViewItem *newView, CMovieClip *clip) { + // Signal the old view that it's being left + CViewItem *oldView = _gameLocation.getView(); + oldView->leaveView(newView); + + // If Shift key is pressed, skip showing the transition clip + if (g_vm->_window->isSpecialPressed(MK_SHIFT)) + clip = nullptr; + + if (_mode == GSMODE_CUTSCENE) { + _movieList._view = newView; + _movieList._movieClip = clip; + } else { + oldView->preEnterView(newView); + _gameManager->_gameView->setView(newView); + CRoomItem *oldRoom = newView->findNode()->findRoom(); + CRoomItem *newRoom = newView->findNode()->findRoom(); + + // If a transition clip is defined, play it + if (clip) + _gameManager->playClip(clip, oldRoom, newRoom); + + // Final view change handling + _gameManager->_sound.preEnterView(newView, newRoom != oldRoom); + oldView->enterView(newView); + } +} + +void CGameState::checkForViewChange() { + if (_mode == GSMODE_CUTSCENE && _movieList.clear()) { + setMode(GSMODE_INTERACTIVE); + if (_movieList._view) + enterView(); + } +} + +void CGameState::addMovie(CMovie *movie) { + _movieList.push_back(new CMovieListItem(movie)); + setMode(GSMODE_CUTSCENE); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game_state.h b/engines/titanic/game_state.h new file mode 100644 index 0000000000..0bfa0d5b31 --- /dev/null +++ b/engines/titanic/game_state.h @@ -0,0 +1,140 @@ +/* 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_GAME_STATE_H +#define TITANIC_GAME_STATE_H + +#include "titanic/core/list.h" +#include "titanic/core/link_item.h" +#include "titanic/support/simple_file.h" +#include "titanic/game_location.h" +#include "titanic/support/movie.h" + +namespace Titanic { + +class CGameManager; + +enum GameStateMode { + GSMODE_NONE = 0, GSMODE_INTERACTIVE = 1, GSMODE_CUTSCENE = 2, + GSMODE_3 = 3, GSMODE_4 = 4, GSMODE_5 = 5, GSMODE_PENDING_LOAD = 6 +}; + +PTR_LIST_ITEM(CMovie); +class CGameStateMovieList : public List<CMovieListItem> { +public: + CViewItem *_view; + CMovieClip *_movieClip; +public: + CGameStateMovieList() : List<CMovieListItem>(), _view(nullptr), _movieClip(nullptr) {} + + /** + * Clear the movie list + */ + bool clear(); +}; + +class CGameState { +public: + CGameManager *_gameManager; + CGameLocation _gameLocation; + CGameStateMovieList _movieList; + int _passengerClass; + int _priorClass; + GameStateMode _mode; + int _field14; + bool _petActive; + bool _field1C; + bool _quitGame; + int _field24; + uint _nodeChangeCtr; + uint32 _nodeEnterTicks; + Point _mousePos; + int _field38; +public: + CGameState(CGameManager *gameManager); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file) const; + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file); + + /** + * Sets a new mode + */ + void setMode(GameStateMode newMode); + + /** + * Sets the current mouse position + */ + void setMousePos(const Point &pt) { _mousePos = pt; } + + /** + * Gets the current mouse position + */ + Point getMousePos() const { return _mousePos; } + + /** + * Called by the PET when a new node is entered + */ + void enterNode(); + + /** + * Enters a new view + */ + void enterView(); + + /** + * Triggers a link item in a view + */ + void triggerLink(CLinkItem *link); + + /** + * Changes the current view + */ + void changeView(CViewItem *newView, CMovieClip *clip); + + /** + * Check for whether it's time to change the active view + */ + void checkForViewChange(); + + /** + * Adds a movie to the movie list + */ + void addMovie(CMovie *movie); + + void inc14() { _field14 = (_field14 + 1) & 3; } + void set24(int v) { _field24 = v; } + int get24() const { return _field24; } + int getNodeChangedCtr() const { return _nodeChangeCtr; } + uint32 getNodeEnterTicks() const { return _nodeEnterTicks; } + void inc38() { ++_field38; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_GAME_STATE_H */ diff --git a/engines/titanic/game_view.cpp b/engines/titanic/game_view.cpp new file mode 100644 index 0000000000..cb84b6a3b1 --- /dev/null +++ b/engines/titanic/game_view.cpp @@ -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. + * + */ + +#include "titanic/game_view.h" +#include "titanic/game_manager.h" +#include "titanic/main_game_window.h" +#include "titanic/support/screen_manager.h" + +namespace Titanic { + +#define VIEW_OFFSET_X 20 +#define VIEW_OFFSET_Y 10 + +CGameView::CGameView() : _gameManager(nullptr), _surface(nullptr) { +} + +CGameView::~CGameView() { + if (_surface) + delete _surface; +} + +void CGameView::setGameManager(CGameManager *gameManager) { + _gameManager = gameManager; +} + +void CGameView::postLoad() { + delete _surface; + _surface = nullptr; +} + +void CGameView::deleteView(int roomNumber, int nodeNumber, int viewNumber) { + CViewItem *view = _gameManager->_project->findView(roomNumber, nodeNumber, viewNumber); + if (view) + delete view; +} + +void CGameView::createSurface(const CResourceKey &key) { + // Reset any current view surface + _gameManager->initBounds(); + delete _surface; + _surface = nullptr; + + // Create a fresh surface + CScreenManager::setCurrent(); + _surface = CScreenManager::_currentScreenManagerPtr->createSurface(key); + _surface->_fastBlitFlag = true; +} + +void CGameView::drawView() { + CScreenManager::setCurrent(); + Rect srcRect = _gameManager->_bounds; + + Rect rect2(0, 0, 600, 340); + rect2.translate(VIEW_OFFSET_X, VIEW_OFFSET_Y); + srcRect.constrain(rect2); + Common::Point destPos(srcRect.left, srcRect.top); + srcRect.translate(-VIEW_OFFSET_X, -VIEW_OFFSET_Y); + + CScreenManager::_currentScreenManagerPtr->blitFrom(SURFACE_BACKBUFFER, + _surface, &destPos, &srcRect); +} + +/*------------------------------------------------------------------------*/ + +CSTGameView::CSTGameView(CMainGameWindow *gameWindow) : + CGameView(), _gameWindow(gameWindow) { +} + +void CSTGameView::setView(CViewItem *view) { + _gameWindow->setActiveView(view); +} + +void CSTGameView::draw(const Rect &bounds) { + _gameWindow->draw(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/game_view.h b/engines/titanic/game_view.h new file mode 100644 index 0000000000..29e800bc7a --- /dev/null +++ b/engines/titanic/game_view.h @@ -0,0 +1,93 @@ +/* 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_GAME_VIEW_H +#define TITANIC_GAME_VIEW_H + +#include "common/scummsys.h" +#include "titanic/core/view_item.h" +#include "titanic/support/video_surface.h" + +namespace Titanic { + +class CMainGameWindow; +class CGameManager; + +class CGameView { +protected: + CGameManager *_gameManager; +public: + CVideoSurface *_surface; +public: + CGameView(); + virtual ~CGameView(); + + /** + * Set the game manager + */ + void setGameManager(CGameManager *gameManager); + + /** + * Called after loading a game has finished + */ + void postLoad(); + + virtual void deleteView(int roomNumber, int nodeNumber, int viewNumber); + + /** + * Set the currently active view + */ + virtual void setView(CViewItem *item) = 0; + + virtual void draw(const Rect &bounds) = 0; + + /** + * Creates a surface from a specified resource + */ + void createSurface(const CResourceKey &key); + + /** + * Draws the background of a view + */ + void drawView(); +}; + +class CSTGameView: public CGameView { +private: + CMainGameWindow *_gameWindow; +public: + CSTGameView(CMainGameWindow *gameWindow); + + /** + * Set the currently active view + */ + virtual void setView(CViewItem *item); + + /** + * Handles drawing the view + */ + virtual void draw(const Rect &bounds); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_GAME_VIEW_H */ diff --git a/engines/titanic/gfx/act_button.cpp b/engines/titanic/gfx/act_button.cpp new file mode 100644 index 0000000000..75c999b10f --- /dev/null +++ b/engines/titanic/gfx/act_button.cpp @@ -0,0 +1,50 @@ +/* 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/gfx/act_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CActButton, CSTButton) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +CActButton::CActButton() : CSTButton() { +} + +void CActButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSTButton::save(file, indent); +} + +void CActButton::load(SimpleFile *file) { + file->readNumber(); + CSTButton::load(file); +} + +bool CActButton::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + CActMsg actMsg(_actionName); + actMsg.execute(_actionTarget); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/act_button.h b/engines/titanic/gfx/act_button.h new file mode 100644 index 0000000000..910ace1d13 --- /dev/null +++ b/engines/titanic/gfx/act_button.h @@ -0,0 +1,50 @@ +/* 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_ACT_BUTTON_H +#define TITANIC_ACT_BUTTON_H + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +class CActButton : public CSTButton { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +public: + CLASSDEF; + CActButton(); + + /** + * 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_ACT_BUTTON_H */ diff --git a/engines/titanic/gfx/changes_season_button.cpp b/engines/titanic/gfx/changes_season_button.cpp new file mode 100644 index 0000000000..584a9542f3 --- /dev/null +++ b/engines/titanic/gfx/changes_season_button.cpp @@ -0,0 +1,51 @@ +/* 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/gfx/changes_season_button.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChangesSeasonButton, CSTButton) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CChangesSeasonButton::CChangesSeasonButton() : CSTButton() { +} + +void CChangesSeasonButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSTButton::save(file, indent); +} + +void CChangesSeasonButton::load(SimpleFile *file) { + file->readNumber(); + CSTButton::load(file); +} + +bool CChangesSeasonButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CChangeSeasonMsg changeMsg(_actionName); + changeMsg.execute(getRoot(), nullptr, MSGFLAG_SCAN); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/changes_season_button.h b/engines/titanic/gfx/changes_season_button.h new file mode 100644 index 0000000000..4f588187eb --- /dev/null +++ b/engines/titanic/gfx/changes_season_button.h @@ -0,0 +1,50 @@ +/* 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_CHANGES_SEASON_BUTTON_H +#define TITANIC_CHANGES_SEASON_BUTTON_H + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +class CChangesSeasonButton : public CSTButton { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + CLASSDEF; + CChangesSeasonButton(); + + /** + * 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_CHANGES_SEASON_BUTTON_H */ diff --git a/engines/titanic/gfx/chev_left_off.cpp b/engines/titanic/gfx/chev_left_off.cpp new file mode 100644 index 0000000000..d5c7dcffd6 --- /dev/null +++ b/engines/titanic/gfx/chev_left_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/gfx/chev_left_off.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CChevLeftOff, CToggleSwitch); + +CChevLeftOff::CChevLeftOff() : CToggleSwitch() { +} + +void CChevLeftOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CChevLeftOff::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/chev_left_off.h b/engines/titanic/gfx/chev_left_off.h new file mode 100644 index 0000000000..5034c1a71a --- /dev/null +++ b/engines/titanic/gfx/chev_left_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_CHEV_LEFT_OFF_H +#define TITANIC_CHEV_LEFT_OFF_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CChevLeftOff : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CChevLeftOff(); + + /** + * 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_CHEV_LEFT_OFF_H */ diff --git a/engines/titanic/gfx/chev_left_on.cpp b/engines/titanic/gfx/chev_left_on.cpp new file mode 100644 index 0000000000..9b4a5b6d58 --- /dev/null +++ b/engines/titanic/gfx/chev_left_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/gfx/chev_left_on.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CChevLeftOn, CToggleSwitch); + +CChevLeftOn::CChevLeftOn() : CToggleSwitch() { +} + +void CChevLeftOn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CChevLeftOn::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/chev_left_on.h b/engines/titanic/gfx/chev_left_on.h new file mode 100644 index 0000000000..df430f6700 --- /dev/null +++ b/engines/titanic/gfx/chev_left_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_CHEV_LEFT_ON_H +#define TITANIC_CHEV_LEFT_ON_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CChevLeftOn : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CChevLeftOn(); + + /** + * 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_CHEV_LEFT_ON_H */ diff --git a/engines/titanic/gfx/chev_right_off.cpp b/engines/titanic/gfx/chev_right_off.cpp new file mode 100644 index 0000000000..c4ff3628a0 --- /dev/null +++ b/engines/titanic/gfx/chev_right_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/gfx/chev_right_off.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CChevRightOff, CToggleSwitch); + +CChevRightOff::CChevRightOff() : CToggleSwitch() { +} + +void CChevRightOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CChevRightOff::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/chev_right_off.h b/engines/titanic/gfx/chev_right_off.h new file mode 100644 index 0000000000..8f6c3fc254 --- /dev/null +++ b/engines/titanic/gfx/chev_right_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_CHEV_RIGHT_OFF_H +#define TITANIC_CHEV_RIGHT_OFF_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CChevRightOff : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CChevRightOff(); + + /** + * 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_CHEV_RIGHT_OFF_H */ diff --git a/engines/titanic/gfx/chev_right_on.cpp b/engines/titanic/gfx/chev_right_on.cpp new file mode 100644 index 0000000000..0351c105d2 --- /dev/null +++ b/engines/titanic/gfx/chev_right_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/gfx/chev_right_on.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CChevRightOn, CToggleSwitch); + +CChevRightOn::CChevRightOn() : CToggleSwitch() { +} + +void CChevRightOn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CChevRightOn::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/chev_right_on.h b/engines/titanic/gfx/chev_right_on.h new file mode 100644 index 0000000000..accd42cff8 --- /dev/null +++ b/engines/titanic/gfx/chev_right_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_CHEV_RIGHT_ON_H +#define TITANIC_CHEV_RIGHT_ON_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CChevRightOn : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CChevRightOn(); + + /** + * 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_CHEV_RIGHT_ON_H */ diff --git a/engines/titanic/gfx/chev_send_rec_switch.cpp b/engines/titanic/gfx/chev_send_rec_switch.cpp new file mode 100644 index 0000000000..6e30280315 --- /dev/null +++ b/engines/titanic/gfx/chev_send_rec_switch.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/gfx/chev_send_rec_switch.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CChevSendRecSwitch, CToggleSwitch); + +CChevSendRecSwitch::CChevSendRecSwitch() : CToggleSwitch() { +} + +void CChevSendRecSwitch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CChevSendRecSwitch::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/chev_send_rec_switch.h b/engines/titanic/gfx/chev_send_rec_switch.h new file mode 100644 index 0000000000..b3ccab2f09 --- /dev/null +++ b/engines/titanic/gfx/chev_send_rec_switch.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_CHEV_SEND_REC_SWITCH_H +#define TITANIC_CHEV_SEND_REC_SWITCH_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CChevSendRecSwitch : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CChevSendRecSwitch(); + + /** + * 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_CHEV_SEND_REC_SWITCH_H */ diff --git a/engines/titanic/gfx/chev_switch.cpp b/engines/titanic/gfx/chev_switch.cpp new file mode 100644 index 0000000000..177f0ada76 --- /dev/null +++ b/engines/titanic/gfx/chev_switch.cpp @@ -0,0 +1,78 @@ +/* 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/gfx/chev_switch.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CChevSwitch, CToggleSwitch) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(SetChevButtonImageMsg) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CChevSwitch::CChevSwitch() : CToggleSwitch(), _value(0) { +} + +void CChevSwitch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CChevSwitch::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +bool CChevSwitch::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + return true; +} + +bool CChevSwitch::SetChevButtonImageMsg(CSetChevButtonImageMsg *msg) { + if (msg->_value2 && getParent()) { + error("TODO: Don't know parent type"); + } + + _fieldBC = msg->_value1; + if (_fieldBC) { + loadImage((_value & 1) ? "on_odd.tga" : "on_even.tga"); + } else { + loadImage((_value & 1) ? "off_odd.tga" : "off_even.tga"); + } + + return true; +} + +bool CChevSwitch::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + _fieldBC ^= 1; + if (getParent()) { + CSetChevPanelBitMsg bitMsg(_value, _fieldBC); + bitMsg.execute(getParent()); + } + + CSetChevButtonImageMsg chevMsg(_fieldBC, 0); + chevMsg.execute(this); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/chev_switch.h b/engines/titanic/gfx/chev_switch.h new file mode 100644 index 0000000000..01da53c854 --- /dev/null +++ b/engines/titanic/gfx/chev_switch.h @@ -0,0 +1,54 @@ +/* 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_CHEV_SWITCH_H +#define TITANIC_CHEV_SWITCH_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CChevSwitch : public CToggleSwitch { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool SetChevButtonImageMsg(CSetChevButtonImageMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + int _value; +public: + CLASSDEF; + CChevSwitch(); + + /** + * 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_CHEV_SWITCH_H */ diff --git a/engines/titanic/gfx/edit_control.cpp b/engines/titanic/gfx/edit_control.cpp new file mode 100644 index 0000000000..3f3c4d4035 --- /dev/null +++ b/engines/titanic/gfx/edit_control.cpp @@ -0,0 +1,222 @@ +/* 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/gfx/edit_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEditControl, CGameObject) + ON_MESSAGE(EditControlMsg) +END_MESSAGE_MAP() + +CEditControl::CEditControl() : CGameObject(), _fieldBC(false), _fontNumber(0), _fieldD4(2), + _textR(0), _textG(0), _textB(0), _fieldF0(0), _fieldF4(0) { +} + +void CEditControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_editLeft, indent); + file->writeNumberLine(_editBottom, indent); + file->writeNumberLine(_editHeight, indent); + file->writeNumberLine(_maxTextChars, indent); + file->writeNumberLine(_fontNumber, indent); + file->writeNumberLine(_fieldD4, indent); + file->writeNumberLine(_textR, indent); + file->writeNumberLine(_textG, indent); + file->writeNumberLine(_textB, indent); + file->writeQuotedLine(_text, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_fieldF4, indent); + + CGameObject::save(file, indent); +} + +void CEditControl::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _editLeft = file->readNumber(); + _editBottom = file->readNumber(); + _editHeight = file->readNumber(); + _maxTextChars = file->readNumber(); + _fontNumber = file->readNumber(); + _fieldD4 = file->readNumber(); + _textR = file->readNumber(); + _textG = file->readNumber(); + _textB = file->readNumber(); + _text = file->readString(); + _fieldF0 = file->readNumber(); + _fieldF4 = file->readNumber(); + + CGameObject::load(file); +} + +bool CEditControl::EditControlMsg(CEditControlMsg *msg) { + switch (msg->_mode) { + case 0: + if (!_editLeft) { + _editHeight = _bounds.height(); + _editBottom = _bounds.bottom; + _editLeft = _bounds.left + _bounds.width() / 2; + _maxTextChars = msg->_param; + setTextFontNumber(_fontNumber); + + CEditControlMsg ctlMsg; + ctlMsg._mode = 10; + ctlMsg._param = _fieldD4; + ctlMsg.execute(this); + + ctlMsg._mode = 11; + ctlMsg._textR = _textR; + ctlMsg._textG = _textG; + ctlMsg._textB = _textB; + ctlMsg.execute(this); + } + break; + + case 1: { + _text = ""; + CEditControlMsg ctlMsg; + ctlMsg._mode = 14; + ctlMsg.execute(this); + break; + } + + case 2: { + _text = msg->_text; + CEditControlMsg ctlMsg; + ctlMsg._mode = 14; + ctlMsg.execute(this); + break; + } + + case 3: + msg->_text = _text; + break; + + case 4: + msg->_param = _text.size(); + break; + + case 5: + _maxTextChars = msg->_param; + break; + + case 6: + if (msg->_param == 8 && !_text.empty()) { + _text = _text.left(_text.size() - 1); + CEditControlMsg ctlMsg; + ctlMsg._mode = 14; + ctlMsg.execute(this); + } else if (msg->_param == 13) { + msg->_param = 1000; + } else if (msg->_param >= 32 && msg->_param < 127 + && _text.size() < _maxTextChars) { + char c = (char)msg->_param; + _text += c; + + CEditControlMsg ctlMsg; + ctlMsg._mode = 14; + ctlMsg.execute(this); + } + break; + + case 7: + setTextFontNumber(msg->_param); + break; + + case 8: + if (!_fieldBC) { + _fieldBC = true; + CEditControlMsg ctlMsg; + ctlMsg._mode = 14; + ctlMsg.execute(this); + } + break; + + case 9: + if (_fieldBC) { + _fieldBC = false; + getTextCursor()->hide(); + } + break; + + case 10: { + setTextHasBorders((msg->_param & 1) != 0); + if (msg->_param & 4) + _fieldF0 = 1; + else if (msg->_param & 8) + _fieldF0 = 2; + else + _fieldF0 = 0; + + _fieldF4 = msg->_param & 0x10; + CEditControlMsg ctlMsg; + ctlMsg._mode = 14; + ctlMsg.execute(this); + break; + } + + case 11: + setTextColor(msg->_textR, msg->_textG, msg->_textB); + break; + + case 12: + setVisible(true); + break; + + case 13: + setVisible(false); + break; + + case 14: { + makeDirty(); + CString str = _fieldF4 ? CString('*', _text.size()) : _text; + setText(str); + + int textWidth = getTextWidth(); + if (_fieldF0 == 2) { + _bounds.left = _editLeft - textWidth / 2; + _bounds.setWidth(textWidth + 16); + setTextBounds(); + makeDirty(); + } + + if (_fieldBC) { + CTextCursor *textCursor = getTextCursor(); + textCursor->show(); + textCursor->setPos(Point(_bounds.left + textWidth + 1, _bounds.top + 3)); + textCursor->setSize(Point(2, _editHeight - 6)); + textCursor->setColor(0xff, 0xff, 0xff); + textCursor->clearBounds(); + } + break; + } + + default: + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/edit_control.h b/engines/titanic/gfx/edit_control.h new file mode 100644 index 0000000000..6c02f7afb9 --- /dev/null +++ b/engines/titanic/gfx/edit_control.h @@ -0,0 +1,64 @@ +/* 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_EDIT_CONTROL_H +#define TITANIC_EDIT_CONTROL_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CEditControl : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EditControlMsg(CEditControlMsg *msg); +protected: + bool _fieldBC; + int _editLeft; + int _editBottom; + int _editHeight; + uint _maxTextChars; + int _fontNumber; + int _fieldD4; + byte _textR; + byte _textG; + byte _textB; + CString _text; + int _fieldF0; + int _fieldF4; +public: + CLASSDEF; + CEditControl(); + + /** + * 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_EDIT_CONTROL_H */ diff --git a/engines/titanic/gfx/elevator_button.cpp b/engines/titanic/gfx/elevator_button.cpp new file mode 100644 index 0000000000..e66ee19af3 --- /dev/null +++ b/engines/titanic/gfx/elevator_button.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/gfx/elevator_button.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CElevatorButton, CSTButton); + +CElevatorButton::CElevatorButton() : CSTButton() { +} + +void CElevatorButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSTButton::save(file, indent); +} + +void CElevatorButton::load(SimpleFile *file) { + file->readNumber(); + CSTButton::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/elevator_button.h b/engines/titanic/gfx/elevator_button.h new file mode 100644 index 0000000000..28110d8102 --- /dev/null +++ b/engines/titanic/gfx/elevator_button.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_ELEVATOR_BUTTON_H +#define TITANIC_ELEVATOR_BUTTON_H + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +class CElevatorButton : public CSTButton { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CElevatorButton(); + + /** + * 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_ELEVATOR_BUTTON_H */ diff --git a/engines/titanic/gfx/get_from_succ.cpp b/engines/titanic/gfx/get_from_succ.cpp new file mode 100644 index 0000000000..d701f73537 --- /dev/null +++ b/engines/titanic/gfx/get_from_succ.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/gfx/get_from_succ.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CGetFromSucc, CToggleSwitch); + +CGetFromSucc::CGetFromSucc() : CToggleSwitch() { +} + +void CGetFromSucc::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CGetFromSucc::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/get_from_succ.h b/engines/titanic/gfx/get_from_succ.h new file mode 100644 index 0000000000..f85f1b4cf2 --- /dev/null +++ b/engines/titanic/gfx/get_from_succ.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_GET_FROM_SUCC_H +#define TITANIC_GET_FROM_SUCC_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CGetFromSucc : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CGetFromSucc(); + + /** + * 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_GET_FROM_SUCC_H */ diff --git a/engines/titanic/gfx/helmet_on_off.cpp b/engines/titanic/gfx/helmet_on_off.cpp new file mode 100644 index 0000000000..06e7d43d32 --- /dev/null +++ b/engines/titanic/gfx/helmet_on_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/gfx/helmet_on_off.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CHelmetOnOff, CToggleSwitch); + +CHelmetOnOff::CHelmetOnOff() : CToggleSwitch() { +} + +void CHelmetOnOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CHelmetOnOff::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/helmet_on_off.h b/engines/titanic/gfx/helmet_on_off.h new file mode 100644 index 0000000000..c2910eb59d --- /dev/null +++ b/engines/titanic/gfx/helmet_on_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_HELMET_ON_OFF_H +#define TITANIC_HELMET_ON_OFF_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CHelmetOnOff : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CHelmetOnOff(); + + /** + * 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_HELMET_ON_OFF_H */ diff --git a/engines/titanic/gfx/home_photo.cpp b/engines/titanic/gfx/home_photo.cpp new file mode 100644 index 0000000000..758a5caa75 --- /dev/null +++ b/engines/titanic/gfx/home_photo.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/gfx/home_photo.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CHomePhoto, CToggleSwitch); + +CHomePhoto::CHomePhoto() : CToggleSwitch() { +} + +void CHomePhoto::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CHomePhoto::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/home_photo.h b/engines/titanic/gfx/home_photo.h new file mode 100644 index 0000000000..09b18b7c0f --- /dev/null +++ b/engines/titanic/gfx/home_photo.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_HOME_PHOTO_H +#define TITANIC_HOME_PHOTO_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CHomePhoto : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CHomePhoto(); + + /** + * 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_HOME_PHOTO_H */ diff --git a/engines/titanic/gfx/icon_nav_action.cpp b/engines/titanic/gfx/icon_nav_action.cpp new file mode 100644 index 0000000000..4d32f46571 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_action.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/gfx/icon_nav_action.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavAction, CToggleSwitch); + +CIconNavAction::CIconNavAction() : CToggleSwitch() { +} + +void CIconNavAction::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CIconNavAction::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_action.h b/engines/titanic/gfx/icon_nav_action.h new file mode 100644 index 0000000000..841334dd41 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_action.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_ICON_NAV_ACTION_H +#define TITANIC_ICON_NAV_ACTION_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CIconNavAction : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CIconNavAction(); + + /** + * 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_ICON_NAV_ACTION_H */ diff --git a/engines/titanic/gfx/icon_nav_butt.cpp b/engines/titanic/gfx/icon_nav_butt.cpp new file mode 100644 index 0000000000..951c2f5e7b --- /dev/null +++ b/engines/titanic/gfx/icon_nav_butt.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/gfx/icon_nav_butt.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavButt, CPetGraphic); + +void CIconNavButt::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CIconNavButt::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_butt.h b/engines/titanic/gfx/icon_nav_butt.h new file mode 100644 index 0000000000..c60877e2c0 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_butt.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_ICON_NAV_BUTT_H +#define TITANIC_ICON_NAV_BUTT_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CIconNavButt : 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_ICON_NAV_BUTT_H */ diff --git a/engines/titanic/gfx/icon_nav_down.cpp b/engines/titanic/gfx/icon_nav_down.cpp new file mode 100644 index 0000000000..efa2124b14 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_down.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/gfx/icon_nav_down.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavDown, CToggleSwitch); + +CIconNavDown::CIconNavDown() : CToggleSwitch() { +} + +void CIconNavDown::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CIconNavDown::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_down.h b/engines/titanic/gfx/icon_nav_down.h new file mode 100644 index 0000000000..6c0c2870e4 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_down.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_ICON_NAV_DOWN_H +#define TITANIC_ICON_NAV_DOWN_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CIconNavDown : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CIconNavDown(); + + /** + * 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_ICON_NAV_DOWN_H */ diff --git a/engines/titanic/gfx/icon_nav_image.cpp b/engines/titanic/gfx/icon_nav_image.cpp new file mode 100644 index 0000000000..403ae44b17 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_image.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/gfx/icon_nav_image.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavImage, CPetGraphic); + +void CIconNavImage::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CIconNavImage::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_image.h b/engines/titanic/gfx/icon_nav_image.h new file mode 100644 index 0000000000..580762c32d --- /dev/null +++ b/engines/titanic/gfx/icon_nav_image.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_ICON_NAV_IMAGE_H +#define TITANIC_ICON_NAV_IMAGE_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CIconNavImage : 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_ICON_NAV_IMAGE_H */ diff --git a/engines/titanic/gfx/icon_nav_left.cpp b/engines/titanic/gfx/icon_nav_left.cpp new file mode 100644 index 0000000000..8d98f3724c --- /dev/null +++ b/engines/titanic/gfx/icon_nav_left.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/gfx/icon_nav_left.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavLeft, CToggleSwitch); + +CIconNavLeft::CIconNavLeft() : CToggleSwitch() { +} + +void CIconNavLeft::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CIconNavLeft::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_left.h b/engines/titanic/gfx/icon_nav_left.h new file mode 100644 index 0000000000..bb61c26362 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_left.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_ICON_NAV_LEFT_H +#define TITANIC_ICON_NAV_LEFT_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CIconNavLeft : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CIconNavLeft(); + + /** + * 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_ICON_NAV_LEFT_H */ diff --git a/engines/titanic/gfx/icon_nav_receive.cpp b/engines/titanic/gfx/icon_nav_receive.cpp new file mode 100644 index 0000000000..e3e0986690 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_receive.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/gfx/icon_nav_receive.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavReceive, CPetGraphic); + +void CIconNavReceive::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CIconNavReceive::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_receive.h b/engines/titanic/gfx/icon_nav_receive.h new file mode 100644 index 0000000000..0744105835 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_receive.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_ICON_NAV_RECEIVE_H +#define TITANIC_ICON_NAV_RECEIVE_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CIconNavReceive : 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_ICON_NAV_RECEIVE_H */ diff --git a/engines/titanic/gfx/icon_nav_right.cpp b/engines/titanic/gfx/icon_nav_right.cpp new file mode 100644 index 0000000000..de827918e9 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_right.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/gfx/icon_nav_right.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavRight, CToggleSwitch); + +CIconNavRight::CIconNavRight() : CToggleSwitch() { +} + +void CIconNavRight::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CIconNavRight::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_right.h b/engines/titanic/gfx/icon_nav_right.h new file mode 100644 index 0000000000..a1bed9ca8f --- /dev/null +++ b/engines/titanic/gfx/icon_nav_right.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_ICON_NAV_RIGHT_H +#define TITANIC_ICON_NAV_RIGHT_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CIconNavRight : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CIconNavRight(); + + /** + * 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_ICON_NAV_RIGHT_H */ diff --git a/engines/titanic/gfx/icon_nav_send.cpp b/engines/titanic/gfx/icon_nav_send.cpp new file mode 100644 index 0000000000..9baa9e8f33 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_send.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/gfx/icon_nav_send.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavSend, CPetGraphic); + +void CIconNavSend::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CIconNavSend::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_send.h b/engines/titanic/gfx/icon_nav_send.h new file mode 100644 index 0000000000..f3af8d9c65 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_send.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_ICON_NAV_SEND_H +#define TITANIC_ICON_NAV_SEND_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CIconNavSend : 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_ICON_NAV_SEND_H */ diff --git a/engines/titanic/gfx/icon_nav_up.cpp b/engines/titanic/gfx/icon_nav_up.cpp new file mode 100644 index 0000000000..4268d97868 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_up.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/gfx/icon_nav_up.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CIconNavUp, CToggleSwitch); + +CIconNavUp::CIconNavUp() : CToggleSwitch() { +} + +void CIconNavUp::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CIconNavUp::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/icon_nav_up.h b/engines/titanic/gfx/icon_nav_up.h new file mode 100644 index 0000000000..4b7320d610 --- /dev/null +++ b/engines/titanic/gfx/icon_nav_up.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_ICON_NAV_UP_H +#define TITANIC_ICON_NAV_UP_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CIconNavUp : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CIconNavUp(); + + /** + * 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_ICON_NAV_UP_H */ diff --git a/engines/titanic/gfx/keybrd_butt.cpp b/engines/titanic/gfx/keybrd_butt.cpp new file mode 100644 index 0000000000..063e709a7b --- /dev/null +++ b/engines/titanic/gfx/keybrd_butt.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/gfx/keybrd_butt.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CKeybrdButt, CToggleSwitch); + +CKeybrdButt::CKeybrdButt() : CToggleSwitch() { +} + +void CKeybrdButt::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CKeybrdButt::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/keybrd_butt.h b/engines/titanic/gfx/keybrd_butt.h new file mode 100644 index 0000000000..822be41ed2 --- /dev/null +++ b/engines/titanic/gfx/keybrd_butt.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_KEYBRD_BUTT_H +#define TITANIC_KEYBRD_BUTT_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CKeybrdButt : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CKeybrdButt(); + + /** + * 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_KEYBRD_BUTT_H */ diff --git a/engines/titanic/gfx/move_object_button.cpp b/engines/titanic/gfx/move_object_button.cpp new file mode 100644 index 0000000000..bcd2b2bd76 --- /dev/null +++ b/engines/titanic/gfx/move_object_button.cpp @@ -0,0 +1,61 @@ +/* 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/gfx/move_object_button.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMoveObjectButton, CSTButton) + ON_MESSAGE(MouseButtonUpMsg) +END_MESSAGE_MAP() + +CMoveObjectButton::CMoveObjectButton() : CSTButton(), _field11C(1) { +} + +void CMoveObjectButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_pos1, indent); + file->writeNumberLine(_field11C, indent); + + CSTButton::save(file, indent); +} + +void CMoveObjectButton::load(SimpleFile *file) { + file->readNumber(); + _pos1 = file->readPoint(); + _field11C = file->readNumber(); + + CSTButton::load(file); +} + +bool CMoveObjectButton::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + CGameObject *obj = dynamic_cast<CGameObject *>(getRoot()->findByName(_actionTarget)); + if (obj) { + obj->petAddToInventory(); + obj->setVisible(_field11C); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/move_object_button.h b/engines/titanic/gfx/move_object_button.h new file mode 100644 index 0000000000..46c49c36e2 --- /dev/null +++ b/engines/titanic/gfx/move_object_button.h @@ -0,0 +1,53 @@ +/* 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_MOVE_OBJECT_BUTTON_H +#define TITANIC_MOVE_OBJECT_BUTTON_H + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +class CMoveObjectButton : public CSTButton { + DECLARE_MESSAGE_MAP; + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); +private: + Point _pos1; + int _field11C; +public: + CLASSDEF; + CMoveObjectButton(); + + /** + * 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_MOVE_OBJECT_BUTTON_H */ diff --git a/engines/titanic/gfx/music_control.cpp b/engines/titanic/gfx/music_control.cpp new file mode 100644 index 0000000000..317bec209f --- /dev/null +++ b/engines/titanic/gfx/music_control.cpp @@ -0,0 +1,68 @@ +/* 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/gfx/music_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicControl, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseDoubleClickMsg) +END_MESSAGE_MAP() + +CMusicControl::CMusicControl() : CBackground(), + _controlArea(BELLS), _controlVal(0), _controlMax(1), _fieldEC(1) { +} + +void CMusicControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_controlArea, indent); + file->writeNumberLine(_controlVal, indent); + file->writeNumberLine(_controlMax, indent); + file->writeNumberLine(_fieldEC, indent); + + CBackground::save(file, indent); +} + +void CMusicControl::load(SimpleFile *file) { + file->readNumber(); + _controlArea = (MusicControlArea)file->readNumber(); + _controlVal = file->readNumber(); + _controlMax = file->readNumber(); + _fieldEC = file->readNumber(); + + CBackground::load(file); +} + +bool CMusicControl::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CMusicSettingChangedMsg changedMsg; + changedMsg.execute(this); + return true; +} + +bool CMusicControl::MouseDoubleClickMsg(CMouseDoubleClickMsg *msg) { + CMusicSettingChangedMsg changedMsg; + changedMsg.execute(this); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_control.h b/engines/titanic/gfx/music_control.h new file mode 100644 index 0000000000..a0e73392f9 --- /dev/null +++ b/engines/titanic/gfx/music_control.h @@ -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. + * + */ + +#ifndef TITANIC_MUSIC_CONTROL_H +#define TITANIC_MUSIC_CONTROL_H + +#include "titanic/core/background.h" +#include "titanic/sound/music_room.h" + +namespace Titanic { + +class CMusicControl : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseDoubleClickMsg(CMouseDoubleClickMsg *msg); +public: + MusicControlArea _controlArea; + int _controlVal; + int _controlMax; + int _fieldEC; +public: + CLASSDEF; + CMusicControl(); + + /** + * 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_MUSIC_CONTROL_H */ diff --git a/engines/titanic/gfx/music_slider.cpp b/engines/titanic/gfx/music_slider.cpp new file mode 100644 index 0000000000..ec7ff5e3f6 --- /dev/null +++ b/engines/titanic/gfx/music_slider.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/gfx/music_slider.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CMusicSlider, CMusicControl); + +void CMusicSlider::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicControl::save(file, indent); +} + +void CMusicSlider::load(SimpleFile *file) { + file->readNumber(); + CMusicControl::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_slider.h b/engines/titanic/gfx/music_slider.h new file mode 100644 index 0000000000..be2c5631b6 --- /dev/null +++ b/engines/titanic/gfx/music_slider.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_MUSIC_SLIDER_H +#define TITANIC_MUSIC_SLIDER_H + +#include "titanic/gfx/music_control.h" + +namespace Titanic { + +class CMusicSlider : public CMusicControl { + 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_MUSIC_SLIDER_H */ diff --git a/engines/titanic/gfx/music_slider_pitch.cpp b/engines/titanic/gfx/music_slider_pitch.cpp new file mode 100644 index 0000000000..5f0432e742 --- /dev/null +++ b/engines/titanic/gfx/music_slider_pitch.cpp @@ -0,0 +1,67 @@ +/* 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/gfx/music_slider_pitch.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicSliderPitch, CMusicSlider) + ON_MESSAGE(MusicSettingChangedMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(QueryMusicControlSettingMsg) +END_MESSAGE_MAP() + +void CMusicSliderPitch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicSlider::save(file, indent); +} + +void CMusicSliderPitch::load(SimpleFile *file) { + file->readNumber(); + CMusicSlider::load(file); +} + +bool CMusicSliderPitch::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) { + if (_fieldEC) { + if (++_controlVal > _controlMax) + _controlVal = 0; + + loadFrame(3 - _controlVal); + playSound("z#54.wav", 50); + } else { + playSound("z#46.wav"); + } + + return true; +} + +bool CMusicSliderPitch::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(3 - _controlVal); + return true; +} + +bool CMusicSliderPitch::QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *msg) { + msg->_value = _controlVal - 2; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_slider_pitch.h b/engines/titanic/gfx/music_slider_pitch.h new file mode 100644 index 0000000000..c375c6db33 --- /dev/null +++ b/engines/titanic/gfx/music_slider_pitch.h @@ -0,0 +1,51 @@ +/* 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_MUSIC_SLIDER_PITCH_H +#define TITANIC_MUSIC_SLIDER_PITCH_H + +#include "titanic/gfx/music_slider.h" + +namespace Titanic { + +class CMusicSliderPitch : public CMusicSlider { + DECLARE_MESSAGE_MAP; + bool MusicSettingChangedMsg(CMusicSettingChangedMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *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_MUSIC_SLIDER_PITCH_H */ diff --git a/engines/titanic/gfx/music_slider_speed.cpp b/engines/titanic/gfx/music_slider_speed.cpp new file mode 100644 index 0000000000..93af5d82b7 --- /dev/null +++ b/engines/titanic/gfx/music_slider_speed.cpp @@ -0,0 +1,67 @@ +/* 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/gfx/music_slider_speed.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicSliderSpeed, CMusicSlider) + ON_MESSAGE(MusicSettingChangedMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(QueryMusicControlSettingMsg) +END_MESSAGE_MAP() + +void CMusicSliderSpeed::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicSlider::save(file, indent); +} + +void CMusicSliderSpeed::load(SimpleFile *file) { + file->readNumber(); + CMusicSlider::load(file); +} + +bool CMusicSliderSpeed::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) { + if (_fieldEC) { + if (++_controlVal > _controlMax) + _controlVal = 0; + + loadFrame(3 - _controlVal); + playSound("z#54.wav", 50); + } else { + playSound("z#46.wav"); + } + + return true; +} + +bool CMusicSliderSpeed::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(3 - _controlVal); + return true; +} + +bool CMusicSliderSpeed::QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *msg) { + msg->_value = _controlVal - 1; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_slider_speed.h b/engines/titanic/gfx/music_slider_speed.h new file mode 100644 index 0000000000..2d54f4487c --- /dev/null +++ b/engines/titanic/gfx/music_slider_speed.h @@ -0,0 +1,51 @@ +/* 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_MUSIC_SLIDER_SPEED_H +#define TITANIC_MUSIC_SLIDER_SPEED_H + +#include "titanic/gfx/music_slider.h" + +namespace Titanic { + +class CMusicSliderSpeed : public CMusicSlider { + DECLARE_MESSAGE_MAP; + bool MusicSettingChangedMsg(CMusicSettingChangedMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *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_MUSIC_SLIDER_SPEED_H */ diff --git a/engines/titanic/gfx/music_switch.cpp b/engines/titanic/gfx/music_switch.cpp new file mode 100644 index 0000000000..1c2ced0b4e --- /dev/null +++ b/engines/titanic/gfx/music_switch.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/gfx/music_switch.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CMusicSwitch, CMusicControl); + +void CMusicSwitch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicControl::save(file, indent); +} + +void CMusicSwitch::load(SimpleFile *file) { + file->readNumber(); + CMusicControl::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_switch.h b/engines/titanic/gfx/music_switch.h new file mode 100644 index 0000000000..35af84bdbf --- /dev/null +++ b/engines/titanic/gfx/music_switch.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_MUSIC_SWITCH_H +#define TITANIC_MUSIC_SWITCH_H + +#include "titanic/gfx/music_control.h" + +namespace Titanic { + +class CMusicSwitch : public CMusicControl { + 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_MUSIC_SWITCH_H */ diff --git a/engines/titanic/gfx/music_switch_inversion.cpp b/engines/titanic/gfx/music_switch_inversion.cpp new file mode 100644 index 0000000000..d11df79ab4 --- /dev/null +++ b/engines/titanic/gfx/music_switch_inversion.cpp @@ -0,0 +1,67 @@ +/* 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/gfx/music_switch_inversion.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicSwitchInversion, CMusicSwitch) + ON_MESSAGE(MusicSettingChangedMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(QueryMusicControlSettingMsg) +END_MESSAGE_MAP() + +void CMusicSwitchInversion::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicSwitch::save(file, indent); +} + +void CMusicSwitchInversion::load(SimpleFile *file) { + file->readNumber(); + CMusicSwitch::load(file); +} + +bool CMusicSwitchInversion::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) { + if (_fieldEC) { + if (++_controlVal > _controlMax) + _controlVal = 0; + + loadFrame(_controlVal); + playSound("z#59.wav", 50); + } else { + playSound("z#46.wav"); + } + + return true; +} + +bool CMusicSwitchInversion::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(_controlVal); + return true; +} + +bool CMusicSwitchInversion::QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *msg) { + msg->_value = _controlVal; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_switch_inversion.h b/engines/titanic/gfx/music_switch_inversion.h new file mode 100644 index 0000000000..869b4745ea --- /dev/null +++ b/engines/titanic/gfx/music_switch_inversion.h @@ -0,0 +1,51 @@ +/* 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_MUSIC_SWITCH_INVERSION_H +#define TITANIC_MUSIC_SWITCH_INVERSION_H + +#include "titanic/gfx/music_switch.h" + +namespace Titanic { + +class CMusicSwitchInversion : public CMusicSwitch { + DECLARE_MESSAGE_MAP; + bool MusicSettingChangedMsg(CMusicSettingChangedMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *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_MUSIC_SWITCH_INVERSION_H */ diff --git a/engines/titanic/gfx/music_switch_reverse.cpp b/engines/titanic/gfx/music_switch_reverse.cpp new file mode 100644 index 0000000000..9fe6d51d47 --- /dev/null +++ b/engines/titanic/gfx/music_switch_reverse.cpp @@ -0,0 +1,66 @@ +/* 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/gfx/music_switch_reverse.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicSwitchReverse, CMusicSwitch) + ON_MESSAGE(MusicSettingChangedMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(QueryMusicControlSettingMsg) +END_MESSAGE_MAP() + +void CMusicSwitchReverse::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicSwitch::save(file, indent); +} + +void CMusicSwitchReverse::load(SimpleFile *file) { + file->readNumber(); + CMusicSwitch::load(file); +} +bool CMusicSwitchReverse::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) { + if (_fieldEC) { + if (++_controlVal > _controlMax) + _controlVal = 0; + + loadFrame(_controlVal); + playSound("z#59.wav", 50); + } else { + playSound("z#46.wav"); + } + + return true; +} + +bool CMusicSwitchReverse::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(_controlVal); + return true; +} + +bool CMusicSwitchReverse::QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *msg) { + msg->_value = _controlVal; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_switch_reverse.h b/engines/titanic/gfx/music_switch_reverse.h new file mode 100644 index 0000000000..c101f19d25 --- /dev/null +++ b/engines/titanic/gfx/music_switch_reverse.h @@ -0,0 +1,51 @@ +/* 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_MUSIC_SWITCH_REVERSE_H +#define TITANIC_MUSIC_SWITCH_REVERSE_H + +#include "titanic/gfx/music_switch.h" + +namespace Titanic { + +class CMusicSwitchReverse : public CMusicSwitch { + DECLARE_MESSAGE_MAP; + bool MusicSettingChangedMsg(CMusicSettingChangedMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *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_MUSIC_SWITCH_REVERSE_H */ diff --git a/engines/titanic/gfx/music_voice_mute.cpp b/engines/titanic/gfx/music_voice_mute.cpp new file mode 100644 index 0000000000..ff59edc988 --- /dev/null +++ b/engines/titanic/gfx/music_voice_mute.cpp @@ -0,0 +1,59 @@ +/* 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/gfx/music_voice_mute.h" +#include "titanic/sound/music_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicVoiceMute, CMusicControl) + ON_MESSAGE(MusicSettingChangedMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(QueryMusicControlSettingMsg) +END_MESSAGE_MAP() + +bool CMusicVoiceMute::MusicSettingChangedMsg(CMusicSettingChangedMsg *msg) { + if (++_controlVal > _controlMax) + _controlVal = 0; + + CMusicRoom *musicRoom = getMusicRoom(); + musicRoom->setItem5(_controlArea, _controlVal == 1 ? 1 : 0); + loadFrame(1 - _controlVal); + playSound("z#55.wav", 50); + + return true; +} + +bool CMusicVoiceMute::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(1 - _controlVal); + CMusicRoom *musicRoom = getMusicRoom(); + musicRoom->setItem5(_controlArea, _controlVal == 1 ? 1 : 0); + + return true; +} + +bool CMusicVoiceMute::QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *msg) { + msg->_value = _controlVal; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/music_voice_mute.h b/engines/titanic/gfx/music_voice_mute.h new file mode 100644 index 0000000000..f64b107423 --- /dev/null +++ b/engines/titanic/gfx/music_voice_mute.h @@ -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. + * + */ + +#ifndef TITANIC_MUSIC_VOICE_MUTE_H +#define TITANIC_MUSIC_VOICE_MUTE_H + +#include "titanic/gfx/music_control.h" + +namespace Titanic { + +class CMusicVoiceMute : public CMusicControl { + DECLARE_MESSAGE_MAP; + bool MusicSettingChangedMsg(CMusicSettingChangedMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool QueryMusicControlSettingMsg(CQueryMusicControlSettingMsg *msg); +public: + CLASSDEF; + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMusicControl::save(file, indent); + } + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file) { + file->readNumber(); + CMusicControl::load(file); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MUSIC_VOICE_MUTE_H */ diff --git a/engines/titanic/gfx/send_to_succ.cpp b/engines/titanic/gfx/send_to_succ.cpp new file mode 100644 index 0000000000..0e2b83361b --- /dev/null +++ b/engines/titanic/gfx/send_to_succ.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/gfx/send_to_succ.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSendToSucc, CToggleSwitch); + +CSendToSucc::CSendToSucc() : CToggleSwitch() { +} + +void CSendToSucc::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CSendToSucc::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/send_to_succ.h b/engines/titanic/gfx/send_to_succ.h new file mode 100644 index 0000000000..734c4a7db3 --- /dev/null +++ b/engines/titanic/gfx/send_to_succ.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_SEND_TO_SUCC_H +#define TITANIC_SEND_TO_SUCC_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CSendToSucc : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CSendToSucc(); + + /** + * 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_SEND_TO_SUCC_H */ diff --git a/engines/titanic/gfx/sgt_selector.cpp b/engines/titanic/gfx/sgt_selector.cpp new file mode 100644 index 0000000000..81cccb72ce --- /dev/null +++ b/engines/titanic/gfx/sgt_selector.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/gfx/sgt_selector.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSGTSelector, CPetGraphic); + +void CSGTSelector::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CSGTSelector::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/sgt_selector.h b/engines/titanic/gfx/sgt_selector.h new file mode 100644 index 0000000000..be35635c2b --- /dev/null +++ b/engines/titanic/gfx/sgt_selector.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_SGT_SELECTOR_H +#define TITANIC_SGT_SELECTOR_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CSGTSelector : 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_SGT_SELECTOR_H */ diff --git a/engines/titanic/gfx/slider_button.cpp b/engines/titanic/gfx/slider_button.cpp new file mode 100644 index 0000000000..0633158e97 --- /dev/null +++ b/engines/titanic/gfx/slider_button.cpp @@ -0,0 +1,51 @@ +/* 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/gfx/slider_button.h" + +namespace Titanic { + +CSliderButton::CSliderButton() : CSTButton(), _field114(0), + _field118(0), _field11C(0) { +} + +void CSliderButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field114, indent); + file->writeNumberLine(_field118, indent); + file->writeNumberLine(_field11C, indent); + file->writePoint(_pos1, indent); + + CSTButton::save(file, indent); +} + +void CSliderButton::load(SimpleFile *file) { + file->readNumber(); + _field114 = file->readNumber(); + _field118 = file->readNumber(); + _field11C = file->readNumber(); + _pos1 = file->readPoint(); + + CSTButton::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/slider_button.h b/engines/titanic/gfx/slider_button.h new file mode 100644 index 0000000000..398290bb05 --- /dev/null +++ b/engines/titanic/gfx/slider_button.h @@ -0,0 +1,53 @@ +/* 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_SLIDER_BUTTON_H +#define TITANIC_SLIDER_BUTTON_H + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +class CSliderButton : public CSTButton { +private: + int _field114; + int _field118; + int _field11C; + Point _pos1; +public: + CLASSDEF; + CSliderButton(); + + /** + * 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_SLIDER_BUTTON_H */ diff --git a/engines/titanic/gfx/small_chev_left_off.cpp b/engines/titanic/gfx/small_chev_left_off.cpp new file mode 100644 index 0000000000..f7c27f9036 --- /dev/null +++ b/engines/titanic/gfx/small_chev_left_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/gfx/small_chev_left_off.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSmallChevLeftOff, CToggleSwitch); + +CSmallChevLeftOff::CSmallChevLeftOff() : CToggleSwitch() { +} + +void CSmallChevLeftOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CSmallChevLeftOff::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/small_chev_left_off.h b/engines/titanic/gfx/small_chev_left_off.h new file mode 100644 index 0000000000..bed64befdb --- /dev/null +++ b/engines/titanic/gfx/small_chev_left_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_SMALL_CHEV_LEFT_OFF_H +#define TITANIC_SMALL_CHEV_LEFT_OFF_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CSmallChevLeftOff : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CSmallChevLeftOff(); + + /** + * 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_SMALL_CHEV_LEFT_OFF_H */ diff --git a/engines/titanic/gfx/small_chev_left_on.cpp b/engines/titanic/gfx/small_chev_left_on.cpp new file mode 100644 index 0000000000..7a82c1878e --- /dev/null +++ b/engines/titanic/gfx/small_chev_left_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/gfx/small_chev_left_on.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSmallChevLeftOn, CToggleSwitch); + +CSmallChevLeftOn::CSmallChevLeftOn() : CToggleSwitch() { +} + +void CSmallChevLeftOn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CSmallChevLeftOn::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/small_chev_left_on.h b/engines/titanic/gfx/small_chev_left_on.h new file mode 100644 index 0000000000..9d1771311c --- /dev/null +++ b/engines/titanic/gfx/small_chev_left_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_SMALL_CHEV_LEFT_ON_H +#define TITANIC_SMALL_CHEV_LEFT_ON_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CSmallChevLeftOn : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CSmallChevLeftOn(); + + /** + * 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_SMALL_CHEV_LEFT_ON_H */ diff --git a/engines/titanic/gfx/small_chev_right_off.cpp b/engines/titanic/gfx/small_chev_right_off.cpp new file mode 100644 index 0000000000..f07c5a3d00 --- /dev/null +++ b/engines/titanic/gfx/small_chev_right_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/gfx/small_chev_right_off.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSmallChevRightOff, CToggleSwitch); + +CSmallChevRightOff::CSmallChevRightOff() : CToggleSwitch() { +} + +void CSmallChevRightOff::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CSmallChevRightOff::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/small_chev_right_off.h b/engines/titanic/gfx/small_chev_right_off.h new file mode 100644 index 0000000000..eb6ca455d2 --- /dev/null +++ b/engines/titanic/gfx/small_chev_right_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_SMALL_CHEV_RIGHT_OFF_H +#define TITANIC_SMALL_CHEV_RIGHT_OFF_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CSmallChevRightOff : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CSmallChevRightOff(); + + /** + * 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_SMALL_CHEV_RIGHT_OFF_H */ diff --git a/engines/titanic/gfx/small_chev_right_on.cpp b/engines/titanic/gfx/small_chev_right_on.cpp new file mode 100644 index 0000000000..18aba4a91f --- /dev/null +++ b/engines/titanic/gfx/small_chev_right_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/gfx/small_chev_right_on.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CSmallChevRightOn, CToggleSwitch); + +CSmallChevRightOn::CSmallChevRightOn() : CToggleSwitch() { +} + +void CSmallChevRightOn::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CToggleSwitch::save(file, indent); +} + +void CSmallChevRightOn::load(SimpleFile *file) { + file->readNumber(); + CToggleSwitch::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/small_chev_right_on.h b/engines/titanic/gfx/small_chev_right_on.h new file mode 100644 index 0000000000..1dfb2d6fb2 --- /dev/null +++ b/engines/titanic/gfx/small_chev_right_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_SMALL_CHEV_RIGHT_ON_H +#define TITANIC_SMALL_CHEV_RIGHT_ON_H + +#include "titanic/gfx/toggle_switch.h" + +namespace Titanic { + +class CSmallChevRightOn : public CToggleSwitch { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CSmallChevRightOn(); + + /** + * 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_SMALL_CHEV_RIGHT_ON_H */ diff --git a/engines/titanic/gfx/st_button.cpp b/engines/titanic/gfx/st_button.cpp new file mode 100644 index 0000000000..6fc31f4c64 --- /dev/null +++ b/engines/titanic/gfx/st_button.cpp @@ -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. + * + */ + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSTButton, CBackground) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MouseButtonUpMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CSTButton::CSTButton() : CBackground() { + _statusInc = 0; + _actionTarget = "NULL"; + _fieldF0 = 0; + _currentStatus = 0; + _actionName = "NULL"; + _soundName = "NULL"; + _buttonFrame = 0; +} + +void CSTButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_statusInc, indent); + file->writeQuotedLine(_actionTarget, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_currentStatus, indent); + file->writeQuotedLine(_actionName, indent); + file->writeQuotedLine(_soundName, indent); + file->writeNumberLine(_buttonFrame, indent); + + CBackground::save(file, indent); +} + +void CSTButton::load(SimpleFile *file) { + file->readNumber(); + _statusInc = file->readNumber(); + _actionTarget = file->readString(); + _fieldF0 = file->readNumber(); + _currentStatus = file->readNumber(); + _actionName = file->readString(); + _soundName = file->readString(); + _buttonFrame = file->readNumber() != 0; + + CBackground::load(file); +} + +bool CSTButton::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + playMovie(0); + playSound(_soundName, 100, 0, 0); + + return true; +} + +bool CSTButton::MouseButtonUpMsg(CMouseButtonUpMsg *msg) { + int oldStatus = _currentStatus; + int newStatus = _currentStatus + _statusInc; + + CStatusChangeMsg statusMsg(oldStatus, newStatus, false); + _currentStatus = newStatus; + statusMsg.execute(_actionTarget); + + if (!statusMsg._success) { + _currentStatus -= _statusInc; + } + + return true; +} + +bool CSTButton::EnterViewMsg(CEnterViewMsg *msg) { + loadFrame(_buttonFrame); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/st_button.h b/engines/titanic/gfx/st_button.h new file mode 100644 index 0000000000..444c883f59 --- /dev/null +++ b/engines/titanic/gfx/st_button.h @@ -0,0 +1,62 @@ +/* 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_ST_BUTTON_H +#define TITANIC_ST_BUTTON_H + +#include "titanic/core/background.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CSTButton : public CBackground { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseButtonUpMsg(CMouseButtonUpMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +protected: + int _statusInc; + CString _actionTarget; + int _fieldF0; + int _currentStatus; + CString _actionName; + CString _soundName; + int _buttonFrame; +public: + CLASSDEF; + CSTButton(); + + /** + * 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_ST_BUTTON_H */ diff --git a/engines/titanic/gfx/status_change_button.cpp b/engines/titanic/gfx/status_change_button.cpp new file mode 100644 index 0000000000..6644247ff2 --- /dev/null +++ b/engines/titanic/gfx/status_change_button.cpp @@ -0,0 +1,40 @@ +/* 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/gfx/status_change_button.h" + +namespace Titanic { + +CStatusChangeButton::CStatusChangeButton() : CSTButton() { +} + +void CStatusChangeButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CSTButton::save(file, indent); +} + +void CStatusChangeButton::load(SimpleFile *file) { + file->readNumber(); + CSTButton::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/status_change_button.h b/engines/titanic/gfx/status_change_button.h new file mode 100644 index 0000000000..9e410c66f2 --- /dev/null +++ b/engines/titanic/gfx/status_change_button.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_STATUS_CHANGE_BUTTON_H +#define TITANIC_STATUS_CHANGE_BUTTON_H + +#include "titanic/gfx/st_button.h" + +namespace Titanic { + +class CStatusChangeButton : public CSTButton { +public: + CLASSDEF; + CStatusChangeButton(); + + /** + * 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_STATUS_CHANGE_BUTTON_H */ diff --git a/engines/titanic/gfx/text_down.cpp b/engines/titanic/gfx/text_down.cpp new file mode 100644 index 0000000000..4d9bb0b077 --- /dev/null +++ b/engines/titanic/gfx/text_down.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/gfx/text_down.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CTextDown, CPetGraphic); + +void CTextDown::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CTextDown::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/text_down.h b/engines/titanic/gfx/text_down.h new file mode 100644 index 0000000000..97660605d5 --- /dev/null +++ b/engines/titanic/gfx/text_down.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_TEXT_DOWN_H +#define TITANIC_TEXT_DOWN_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CTextDown : 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_TEXT_DOWN_H */ diff --git a/engines/titanic/gfx/text_skrew.cpp b/engines/titanic/gfx/text_skrew.cpp new file mode 100644 index 0000000000..6d403eabfb --- /dev/null +++ b/engines/titanic/gfx/text_skrew.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/gfx/text_skrew.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CTextSkrew, CPetGraphic); + +void CTextSkrew::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CTextSkrew::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/text_skrew.h b/engines/titanic/gfx/text_skrew.h new file mode 100644 index 0000000000..d0d9b82afd --- /dev/null +++ b/engines/titanic/gfx/text_skrew.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_TEXT_SKREW_H +#define TITANIC_TEXT_SKREW_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CTextSkrew : 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_TEXT_SKREW_H */ diff --git a/engines/titanic/gfx/text_up.cpp b/engines/titanic/gfx/text_up.cpp new file mode 100644 index 0000000000..842be63ee6 --- /dev/null +++ b/engines/titanic/gfx/text_up.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/gfx/text_up.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CTextUp, CPetGraphic); + +void CTextUp::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CPetGraphic::save(file, indent); +} + +void CTextUp::load(SimpleFile *file) { + file->readNumber(); + CPetGraphic::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/text_up.h b/engines/titanic/gfx/text_up.h new file mode 100644 index 0000000000..dda8d8461b --- /dev/null +++ b/engines/titanic/gfx/text_up.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_TEXT_UP_H +#define TITANIC_TEXT_UP_H + +#include "titanic/pet_control/pet_graphic.h" + +namespace Titanic { + +class CTextUp : 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_TEXT_UP_H */ diff --git a/engines/titanic/gfx/toggle_button.cpp b/engines/titanic/gfx/toggle_button.cpp new file mode 100644 index 0000000000..2b7c80d3df --- /dev/null +++ b/engines/titanic/gfx/toggle_button.cpp @@ -0,0 +1,43 @@ +/* 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/gfx/toggle_button.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CToggleButton, CBackground); + +void CToggleButton::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + + CBackground::save(file, indent); +} + +void CToggleButton::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + + CBackground::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/toggle_button.h b/engines/titanic/gfx/toggle_button.h new file mode 100644 index 0000000000..5328072982 --- /dev/null +++ b/engines/titanic/gfx/toggle_button.h @@ -0,0 +1,51 @@ +/* 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_TOGGLE_BUTTON_H +#define TITANIC_TOGGLE_BUTTON_H + +#include "titanic/core/background.h" + +namespace Titanic { + +class CToggleButton : public CBackground { + DECLARE_MESSAGE_MAP; +private: + int _fieldE0; +public: + CLASSDEF; + CToggleButton() : CBackground(), _fieldE0(1) {} + + /** + * 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_TOGGLE_BUTTON_H */ diff --git a/engines/titanic/gfx/toggle_switch.cpp b/engines/titanic/gfx/toggle_switch.cpp new file mode 100644 index 0000000000..20cbb863ee --- /dev/null +++ b/engines/titanic/gfx/toggle_switch.cpp @@ -0,0 +1,46 @@ +/* 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/gfx/toggle_switch.h" + +namespace Titanic { + +CToggleSwitch::CToggleSwitch() : CGameObject(), _fieldBC(0) { +} + +void CToggleSwitch::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writePoint(_pos1, indent); + + CGameObject::save(file, indent); +} + +void CToggleSwitch::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _pos1 = file->readPoint(); + + CGameObject::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/gfx/toggle_switch.h b/engines/titanic/gfx/toggle_switch.h new file mode 100644 index 0000000000..8e7d057d8c --- /dev/null +++ b/engines/titanic/gfx/toggle_switch.h @@ -0,0 +1,51 @@ +/* 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_TOGGLE_SWITCH_H +#define TITANIC_TOGGLE_SWITCH_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CToggleSwitch : public CGameObject { +protected: + int _fieldBC; + Point _pos1; +public: + CLASSDEF; + CToggleSwitch(); + + /** + * 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_TOGGLE_SWITCH_H */ diff --git a/engines/titanic/input_handler.cpp b/engines/titanic/input_handler.cpp new file mode 100644 index 0000000000..7c35a5d855 --- /dev/null +++ b/engines/titanic/input_handler.cpp @@ -0,0 +1,177 @@ +/* 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/input_handler.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/support/screen_manager.h" + +namespace Titanic { + +CInputHandler::CInputHandler(CGameManager *owner) : + _gameManager(owner), _inputTranslator(nullptr), _dragging(false), + _buttonDown(false), _dragItem(nullptr), _lockCount(0), + _singleton(false) { + CScreenManager::_screenManagerPtr->_inputHandler = this; +} + +void CInputHandler::setTranslator(CInputTranslator *translator) { + _inputTranslator = translator; +} + +void CInputHandler::incLockCount() { + ++_lockCount; +} + +void CInputHandler::decLockCount() { + if (--_lockCount == 0 && _inputTranslator) { + if (_dragging && !_inputTranslator->isMousePressed()) { + CMouseButtonUpMsg upMsg(_mousePos, MK_LBUTTON); + handleMessage(upMsg); + } + + _buttonDown = _inputTranslator->isMousePressed(); + _singleton = true; + } +} + +void CInputHandler::handleMessage(CMessage &msg, bool respectLock) { + if (!respectLock || _lockCount <= 0) { + if (_gameManager->_gameState._mode == GSMODE_INTERACTIVE) { + processMessage(&msg); + } else if (!msg.isMouseMsg()) { + g_vm->_filesManager->loadDrive(); + } + } +} + +void CInputHandler::processMessage(CMessage *msg) { + const CMouseMsg *mouseMsg = dynamic_cast<const CMouseMsg *>(msg); + _singleton = false; + dispatchMessage(msg); + + if (_singleton) { + _singleton = false; + } else if (mouseMsg) { + // Keep the game state mouse position up to date + if (_mousePos != mouseMsg->_mousePos) { + _mousePos = mouseMsg->_mousePos; + _gameManager->_gameState.setMousePos(mouseMsg->_mousePos); + } + + // Set flag for whether a mouse button is currently being pressed + if (mouseMsg->isButtonDownMsg()) + _buttonDown = true; + else if (mouseMsg->isButtonUpMsg()) + _buttonDown = false; + + // Drag events generation + if (_dragging) { + if (mouseMsg->isMouseMoveMsg()) { + if (_dragItem) { + CMouseDragMoveMsg moveMsg(_mousePos); + moveMsg.execute(_dragItem); + } + } else { + if (mouseMsg->isButtonUpMsg() && _dragItem) { + // Mouse drag ended + CGameObject *target = dragEnd(_mousePos, _dragItem); + CMouseDragEndMsg endMsg(_mousePos, target); + endMsg.execute(_dragItem); + } + + _dragging = false; + _dragItem = nullptr; + } + } else if (_buttonDown) { + if (!mouseMsg->isMouseMoveMsg()) { + // Save where the drag movement started from + _dragStartPos = _mousePos; + } else { + Point delta = mouseMsg->_mousePos - _dragStartPos; + int distance = (int)sqrt(double(delta.x * delta.x + delta.y * delta.y)); + + if (distance > 4) { + // We've moved far enough with the mouse button held down + // to trigger an official dragging operation + CMouseDragStartMsg startMsg(_dragStartPos); + dispatchMessage(&startMsg); + + // Set the drag item, if any, that a handler will have set on the message + _dragItem = startMsg._dragItem; + _gameManager->_dragItem = startMsg._dragItem; + + if (_dragItem) { + CMouseDragMoveMsg moveMsg(_dragStartPos); + dispatchMessage(&moveMsg); + } + + _dragging = true; + } + } + } + } +} + +void CInputHandler::dispatchMessage(CMessage *msg) { + CPetControl *pet = _gameManager->_project->getPetControl(); + if (!pet || !msg->execute(pet, nullptr, MSGFLAG_BREAK_IF_HANDLED)) { + CViewItem *view = _gameManager->getView(); + msg->execute(view); + } +} + +CGameObject *CInputHandler::dragEnd(const Point &pt, CTreeItem *dragItem) { + CViewItem *view = _gameManager->getView(); + if (!view) + return nullptr; + + // Scan through the view items to find the item being dropped on + CGameObject *target = nullptr; + for (CTreeItem *treeItem = view->scan(view); treeItem; treeItem = treeItem->scan(view)) { + CGameObject *gameObject = static_cast<CGameObject *>(treeItem); + if (gameObject && gameObject != dragItem) { + if (gameObject->checkPoint(pt)) + target = gameObject; + } + } + + if (target) { + // Check if the cursor is on the PET. If so, pass to the PET + // to see what specific element the drag ended on + CProjectItem *project = view->getRoot(); + if (project) { + CPetControl *petControl = project->getPetControl(); + if (petControl && petControl->contains(pt)) { + target = petControl->dragEnd(pt); + if (!target) + target = petControl; + } + } + } + + return target; +} + +} // End of namespace Titanic diff --git a/engines/titanic/input_handler.h b/engines/titanic/input_handler.h new file mode 100644 index 0000000000..7244ddc050 --- /dev/null +++ b/engines/titanic/input_handler.h @@ -0,0 +1,83 @@ +/* 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_INPUT_HANDLER_H +#define TITANIC_INPUT_HANDLER_H + +#include "titanic/support/rect.h" +#include "titanic/input_translator.h" +#include "titanic/core/tree_item.h" + +namespace Titanic { + +class CGameManager; + +class CInputHandler { +private: + /** + * Process and dispatch a passed message + */ + void processMessage(CMessage *msg); + + /** + * Dispatches a message to the project + */ + void dispatchMessage(CMessage *msg); + + /** + * Called when a drag operation has ended + */ + CGameObject *dragEnd(const Point &pt, CTreeItem *dragItem); +public: + CGameManager *_gameManager; + CInputTranslator *_inputTranslator; + bool _dragging; + bool _buttonDown; + CTreeItem *_dragItem; + Point _dragStartPos; + Point _mousePos; + int _lockCount; + bool _singleton; +public: + CInputHandler(CGameManager *owner); + + void setTranslator(CInputTranslator *translator); + + /** + * Increment the lock count + */ + void incLockCount(); + + /** + * Decrement the lock count on the input handler + */ + void decLockCount(); + + /** + * Handles a genereated mouse message + */ + void handleMessage(CMessage &msg, bool respectLock = true); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_INPUT_HANDLER_H */ diff --git a/engines/titanic/input_translator.cpp b/engines/titanic/input_translator.cpp new file mode 100644 index 0000000000..ce272d152c --- /dev/null +++ b/engines/titanic/input_translator.cpp @@ -0,0 +1,114 @@ +/* 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/input_handler.h" +#include "titanic/input_translator.h" +#include "titanic/events.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CInputTranslator::CInputTranslator(CInputHandler *inputHandler) : + _inputHandler(inputHandler) { + inputHandler->setTranslator(this); +} + +int CInputTranslator::getButtons(int special) const { + int buttons = 0; + if (special & MK_LBUTTON) + buttons |= MB_LEFT; + if (special & MK_MBUTTON) + buttons |= MB_MIDDLE; + if (special & MK_RBUTTON) + buttons |= MB_RIGHT; + + return buttons; +} + +void CInputTranslator::mouseMove(int special, const Point &pt) { + CMouseMoveMsg msg(pt, getButtons(special)); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::leftButtonDown(int special, const Point &pt) { + CMouseButtonDownMsg msg(pt, MB_LEFT); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::leftButtonUp(int special, const Point &pt) { + CMouseButtonUpMsg msg(pt, MB_LEFT); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::leftButtonDoubleClick(int special, const Point &pt) { + CMouseDoubleClickMsg msg(pt, MB_LEFT); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::middleButtonDown(int special, const Point &pt) { + CMouseButtonDownMsg msg(pt, MB_MIDDLE); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::middleButtonUp(int special, const Point &pt) { + CMouseButtonUpMsg msg(pt, MB_MIDDLE); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::middleButtonDoubleClick(int special, const Point &pt) { + CMouseDoubleClickMsg msg(pt, MB_MIDDLE); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::rightButtonDown(int special, const Point &pt) { + CMouseButtonDownMsg msg(pt, MB_RIGHT); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::rightButtonUp(int special, const Point &pt) { + CMouseButtonUpMsg msg(pt, MB_RIGHT); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::rightButtonDoubleClick(int special, const Point &pt) { + CMouseDoubleClickMsg msg(pt, MB_RIGHT); + _inputHandler->handleMessage(msg); +} + +void CInputTranslator::keyDown(const Common::KeyState &keyState) { + if (keyState.keycode >= Common::KEYCODE_F1 && keyState.keycode <= Common::KEYCODE_F5) { + CVirtualKeyCharMsg msg(keyState); + _inputHandler->handleMessage(msg); + } + + if (keyState.ascii <= 127) { + CKeyCharMsg msg(keyState.ascii); + _inputHandler->handleMessage(msg); + } +} + +bool CInputTranslator::isMousePressed() const { + return g_vm->_window->getSpecialButtons() & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON); +} + +} // End of namespace Titanic diff --git a/engines/titanic/input_translator.h b/engines/titanic/input_translator.h new file mode 100644 index 0000000000..d92157bccc --- /dev/null +++ b/engines/titanic/input_translator.h @@ -0,0 +1,64 @@ +/* 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_INPUT_TRANSLATOR_H +#define TITANIC_INPUT_TRANSLATOR_H + +#include "common/keyboard.h" +#include "titanic/messages/mouse_messages.h" + +namespace Titanic { + +class CInputHandler; + +class CInputTranslator { +private: + /** + * Converts the special buttons bitset into a buttons bitset + */ + int getButtons(int special) const; +public: + CInputHandler *_inputHandler; +public: + CInputTranslator(CInputHandler *inputHandler); + + void mouseMove(int special, const Point &pt); + void leftButtonDown(int special, const Point &pt); + void leftButtonUp(int special, const Point &pt); + void leftButtonDoubleClick(int special, const Point &pt); + void middleButtonDown(int special, const Point &pt); + void middleButtonUp(int special, const Point &pt); + void middleButtonDoubleClick(int special, const Point &pt); + void rightButtonDown(int special, const Point &pt); + void rightButtonUp(int special, const Point &pt); + void rightButtonDoubleClick(int special, const Point &pt); + void keyDown(const Common::KeyState &keyState); + + /** + * Returns true if any mouse button is currently pressed + */ + bool isMousePressed() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_INPUT_TRANSLATOR_H */ diff --git a/engines/titanic/main_game_window.cpp b/engines/titanic/main_game_window.cpp new file mode 100644 index 0000000000..486bc417d7 --- /dev/null +++ b/engines/titanic/main_game_window.cpp @@ -0,0 +1,350 @@ +/* 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/config-manager.h" +#include "titanic/titanic.h" +#include "titanic/continue_save_dialog.h" +#include "titanic/game_manager.h" +#include "titanic/game_view.h" +#include "titanic/main_game_window.h" +#include "titanic/messages/messages.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +CMainGameWindow::CMainGameWindow(TitanicEngine *vm): _vm(vm), + _specialButtons(0), _priorLeftDownTime(0), + _priorMiddleDownTime(0), _priorRightDownTime(0) { + _gameView = nullptr; + _gameManager = nullptr; + _project = nullptr; + _inputAllowed = false; + _image = nullptr; + _cursor = nullptr; + _pendingLoadSlot = -1; + + // Set the window as an event target + vm->_events->addTarget(this); +} + +CMainGameWindow::~CMainGameWindow() { +} + +bool CMainGameWindow::Create() { + Image image; + image.load("TITANIC"); + + // TODO: Stuff + return true; +} + +void CMainGameWindow::applicationStarting() { + // Set the video mode + CScreenManager *screenManager = CScreenManager::setCurrent(); + screenManager->setMode(640, 480, 16, 0, true); + + // Set up the game project, and get game slot + int saveSlot = getSavegameSlot(); + if (saveSlot == -2) + return; + + // Create game view and manager + _gameView = new CSTGameView(this); + _gameManager = new CGameManager(_project, _gameView, g_vm->_mixer); + _gameView->setGameManager(_gameManager); + + // Load either a new game or selected existing save + _project->loadGame(saveSlot); + _inputAllowed = true; + _gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + + // TODO: Cursor/image + + // Generate starting messages for entering the view, node, and room. + // Note the old fields are nullptr, since there's no previous view/node/room + CViewItem *view = _gameManager->_gameState._gameLocation.getView(); + CEnterViewMsg enterViewMsg(nullptr, view); + enterViewMsg.execute(view, nullptr, MSGFLAG_SCAN); + + CNodeItem *node = view->findNode(); + CEnterNodeMsg enterNodeMsg(nullptr, node); + enterNodeMsg.execute(node, nullptr, MSGFLAG_SCAN); + + CRoomItem *room = view->findRoom(); + CEnterRoomMsg enterRoomMsg(nullptr, room); + enterRoomMsg.execute(room, nullptr, MSGFLAG_SCAN); + + _gameManager->initBounds(); +} + +int CMainGameWindow::getSavegameSlot() { + _project = new CProjectItem(); + _project->setFilename("starship.prj"); + + return selectSavegame(); +} + +int CMainGameWindow::selectSavegame() { + // If the user selected a savegame from the launcher, return it + if (ConfMan.hasKey("save_slot")) + return ConfMan.getInt("save_slot"); + + CContinueSaveDialog dialog; + bool hasSavegames = false; + + // Loop through save slots to find any existing save slots + for (int idx = 0; idx < MAX_SAVES; ++idx) { + CString saveName = g_vm->getSavegameName(idx); + if (!saveName.empty()) { + dialog.addSavegame(idx, saveName); + hasSavegames = true; + } + } + + // If there are savegames, show the select dialog and get a choice. + // If there aren't, return -1 to indicate starting a new game + return hasSavegames ? dialog.show() : -1; +} + +void CMainGameWindow::setActiveView(CViewItem *viewItem) { + _gameManager->_gameState._gameLocation.setView(viewItem); + + CResourceKey key; + if (viewItem->getResourceKey(&key)) { + // Create a surface based on the key + _gameView->createSurface(key); + } +} + +void CMainGameWindow::draw() { + if (_gameManager) { + if (!_gameView->_surface) { + CViewItem *view = _gameManager->getView(); + if (view) + setActiveView(view); + } + + CScreenManager *scrManager = CScreenManager::setCurrent(); + scrManager->clearSurface(SURFACE_BACKBUFFER, &_gameManager->_bounds); + + switch (_gameManager->_gameState._mode) { + case GSMODE_INTERACTIVE: + case GSMODE_CUTSCENE: + if (_gameManager->_gameState._petActive) + drawPet(scrManager); + + drawView(); + drawViewContents(scrManager); + scrManager->drawCursors(); + break; + + case GSMODE_5: + g_vm->_filesManager->debug(scrManager); + break; + + case GSMODE_PENDING_LOAD: + // Pending savegame to load + _gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + _vm->_window->_project->loadGame(_pendingLoadSlot); + break; + + default: + break; + } + } +} + +void CMainGameWindow::drawPet(CScreenManager *screenManager) { + if (_gameView && _gameView->_surface) { + CPetControl *petControl = _gameManager->_project->getPetControl(); + if (petControl) + petControl->draw(screenManager); + } +} + +void CMainGameWindow::drawView() { + if (_gameView->_surface) + _gameView->drawView(); +} + +void CMainGameWindow::drawViewContents(CScreenManager *screenManager) { + // Get a reference to the reference, validating that it's present + if (!screenManager) + return; + CViewItem *view = _gameManager->getView(); + if (!view) + return; + CNodeItem *node = view->findNode(); + if (!node) + return; + CRoomItem *room = node->findRoom(); + if (!room) + return; + + double xVal = 0.0, yVal = 0.0; + room->calcNodePosition(node->_nodePos, xVal, yVal); + + // Iterate through drawing all the items in the scene except any item + // that's currently being dragged + for (CTreeItem *treeItem = view; treeItem; treeItem = treeItem->scan(view)) { + if (treeItem != _gameManager->_dragItem) + treeItem->draw(screenManager); + } + + // Finally draw the drag item if there is one + if (_gameManager->_dragItem) + _gameManager->_dragItem->draw(screenManager); +} + +void CMainGameWindow::mouseChanged() { + if (_gameManager->_gameState._mode != GSMODE_5) + _gameManager->update(); +} + +void CMainGameWindow::loadGame(int slotId) { + _pendingLoadSlot = slotId; + _gameManager->_gameState.setMode(GSMODE_PENDING_LOAD); +} + +void CMainGameWindow::onIdle() { + if (!_inputAllowed) + return; + CGameManager *gameManager = _gameManager; + if (!gameManager) + return; + + // Let the game manager perform any game updates + gameManager->update(); + + if (gameManager->_gameState._quitGame) { + // Game needs to shut down + _vm->quitGame(); + } +} + +#define HANDLE_MESSAGE(METHOD) if (_inputAllowed) { \ + _gameManager->_inputTranslator.METHOD(_specialButtons, mousePos); \ + mouseChanged(); \ + } + + +void CMainGameWindow::mouseMove(const Point &mousePos) { + HANDLE_MESSAGE(mouseMove) +} + +void CMainGameWindow::leftButtonDown(const Point &mousePos) { + _specialButtons |= MK_LBUTTON; + + if ((_vm->_events->getTicksCount() - _priorLeftDownTime) < DOUBLE_CLICK_TIME) { + _priorLeftDownTime = 0; + leftButtonDoubleClick(mousePos); + } else { + _priorLeftDownTime = _vm->_events->getTicksCount(); + HANDLE_MESSAGE(leftButtonDown) + } +} + +void CMainGameWindow::leftButtonUp(const Point &mousePos) { + _specialButtons &= ~MK_LBUTTON; + HANDLE_MESSAGE(leftButtonUp) +} + +void CMainGameWindow::leftButtonDoubleClick(const Point &mousePos) { + HANDLE_MESSAGE(leftButtonDoubleClick) +} + +void CMainGameWindow::middleButtonDown(const Point &mousePos) { + _specialButtons |= MK_MBUTTON; + + if ((_vm->_events->getTicksCount() - _priorMiddleDownTime) < DOUBLE_CLICK_TIME) { + _priorMiddleDownTime = 0; + middleButtonDoubleClick(mousePos); + } else { + _priorMiddleDownTime = _vm->_events->getTicksCount(); + HANDLE_MESSAGE(middleButtonDown) + } +} + +void CMainGameWindow::middleButtonUp(const Point &mousePos) { + _specialButtons &= ~MK_MBUTTON; + HANDLE_MESSAGE(middleButtonUp) +} + +void CMainGameWindow::middleButtonDoubleClick(const Point &mousePos) { + HANDLE_MESSAGE(middleButtonDoubleClick) +} + +void CMainGameWindow::rightButtonDown(const Point &mousePos) { + _specialButtons |= MK_RBUTTON; + + if ((_vm->_events->getTicksCount() - _priorRightDownTime) < DOUBLE_CLICK_TIME) { + _priorRightDownTime = 0; + rightButtonDoubleClick(mousePos); + } else { + _priorRightDownTime = _vm->_events->getTicksCount(); + HANDLE_MESSAGE(rightButtonDown) + } +} + +void CMainGameWindow::rightButtonUp(const Point &mousePos) { + _specialButtons &= ~MK_RBUTTON; + HANDLE_MESSAGE(rightButtonUp) +} + +void CMainGameWindow::rightButtonDoubleClick(const Point &mousePos) { + HANDLE_MESSAGE(rightButtonDoubleClick) +} + +void CMainGameWindow::charPress(char c) { + +} + +void CMainGameWindow::keyDown(Common::KeyState keyState) { + handleKbdSpecial(keyState); + + if (keyState.keycode == Common::KEYCODE_d && (keyState.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } + + if (_inputAllowed) + _gameManager->_inputTranslator.keyDown(keyState); +} + +void CMainGameWindow::keyUp(Common::KeyState keyState) { + handleKbdSpecial(keyState); +} + +void CMainGameWindow::handleKbdSpecial(Common::KeyState keyState) { + if (keyState.flags & Common::KBD_CTRL) + _specialButtons |= MK_CONTROL; + else + _specialButtons &= ~MK_CONTROL; + + if (keyState.flags & Common::KBD_SHIFT) + _specialButtons |= MK_SHIFT; + else + _specialButtons &= ~MK_SHIFT; +} + +} // End of namespace Titanic diff --git a/engines/titanic/main_game_window.h b/engines/titanic/main_game_window.h new file mode 100644 index 0000000000..82e24e250e --- /dev/null +++ b/engines/titanic/main_game_window.h @@ -0,0 +1,149 @@ +/* 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_MAIN_GAME_WINDOW_H +#define TITANIC_MAIN_GAME_WINDOW_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "titanic/game_manager.h" +#include "titanic/game_view.h" +#include "titanic/support/image.h" +#include "titanic/core/project_item.h" +#include "titanic/events.h" + +namespace Titanic { + +class TitanicEngine; + +class CMainGameWindow : public CEventTarget { +private: + TitanicEngine *_vm; + int _pendingLoadSlot; + uint _specialButtons; + uint32 _priorFrameTime; + uint32 _priorLeftDownTime; + uint32 _priorMiddleDownTime; + uint32 _priorRightDownTime; +private: + /** + * Checks for the presence of any savegames and, if present, + * lets the user pick one to resume + */ + int getSavegameSlot(); + + /** + * Creates the game "project" and determine a game save slot + * to use + */ + int selectSavegame(); + + /** + * Used for drawing the PET fullscreen? maybe + */ + void drawPet(CScreenManager *screenManager); + + /** + * Draws the background for the view + */ + void drawView(); + + /** + * Draws all the items within the view + */ + void drawViewContents(CScreenManager *screenManager); + + void leftButtonDoubleClick(const Point &mousePos); + void middleButtonDoubleClick(const Point &mousePos); + void rightButtonDoubleClick(const Point &mousePos); + void charPress(char c); + void handleKbdSpecial(Common::KeyState keyState); +public: + CGameView *_gameView; + CGameManager *_gameManager; + CProjectItem *_project; + bool _inputAllowed; + Image *_image; + void *_cursor; +public: + CMainGameWindow(TitanicEngine *vm); + virtual ~CMainGameWindow(); + + /** + * Called to handle any regular updates the game requires + */ + void onIdle(); + + virtual void mouseMove(const Point &mousePos); + virtual void leftButtonDown(const Point &mousePos); + virtual void leftButtonUp(const Point &mousePos); + virtual void middleButtonDown(const Point &mousePos); + virtual void middleButtonUp(const Point &mousePos); + virtual void rightButtonDown(const Point &mousePos); + virtual void rightButtonUp(const Point &mousePos); + virtual void keyDown(Common::KeyState keyState); + virtual void keyUp(Common::KeyState keyState); + + /** + * Creates the window + */ + bool Create(); + + /** + * Called when the application starts + */ + void applicationStarting(); + + /** + * Sets the view to be shown + */ + void setActiveView(CViewItem *viewItem); + + /** + * Main draw method for the window + */ + void draw(); + + /** + * Called by the event handler when a mouse event has been generated + */ + void mouseChanged(); + + /** + * Schedules a savegame to be loaded + */ + void loadGame(int slotId); + + /* + * Return whether a given special key is currently pressed + */ + bool isSpecialPressed(SpecialButtons btn) const { return _specialButtons; } + + /** + * Returns the bitset of the currently pressed special buttons + */ + uint getSpecialButtons() const { return _specialButtons; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MAIN_GAME_WINDOW_H */ diff --git a/engines/titanic/messages/auto_sound_event.cpp b/engines/titanic/messages/auto_sound_event.cpp new file mode 100644 index 0000000000..bc2cd7d074 --- /dev/null +++ b/engines/titanic/messages/auto_sound_event.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/messages/auto_sound_event.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAutoSoundEvent, CGameObject) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +CAutoSoundEvent::CAutoSoundEvent() : CGameObject(), _value1(0), _value2(0xFFFFFF) { +} + +void CAutoSoundEvent::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value1, indent); + file->writeNumberLine(_value2, indent); + + CGameObject::save(file, indent); +} + +void CAutoSoundEvent::load(SimpleFile *file) { + file->readNumber(); + _value1 = file->readNumber(); + _value2 = file->readNumber(); + + CGameObject::load(file); +} + +bool CAutoSoundEvent::FrameMsg(CFrameMsg *msg) { + if (_value1 >= 0) + _value1 = (_value1 + 1) & _value2; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/auto_sound_event.h b/engines/titanic/messages/auto_sound_event.h new file mode 100644 index 0000000000..d88976708e --- /dev/null +++ b/engines/titanic/messages/auto_sound_event.h @@ -0,0 +1,53 @@ +/* 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_AUTO_SOUND_EVENT_H +#define TITANIC_AUTO_SOUND_EVENT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CAutoSoundEvent : public CGameObject { + DECLARE_MESSAGE_MAP; + bool FrameMsg(CFrameMsg *msg); +public: + int _value1; + int _value2; +public: + CLASSDEF; + CAutoSoundEvent(); + + /** + * 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_AUTO_SOUND_EVENT_H */ diff --git a/engines/titanic/messages/bilge_auto_sound_event.cpp b/engines/titanic/messages/bilge_auto_sound_event.cpp new file mode 100644 index 0000000000..fa87b4b79c --- /dev/null +++ b/engines/titanic/messages/bilge_auto_sound_event.cpp @@ -0,0 +1,37 @@ +/* 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/messages/bilge_auto_sound_event.h" + +namespace Titanic { + +void CBilgeAutoSoundEvent::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CAutoSoundEvent::save(file, indent); +} + +void CBilgeAutoSoundEvent::load(SimpleFile *file) { + file->readNumber(); + CAutoSoundEvent::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/bilge_auto_sound_event.h b/engines/titanic/messages/bilge_auto_sound_event.h new file mode 100644 index 0000000000..9a7fbd6261 --- /dev/null +++ b/engines/titanic/messages/bilge_auto_sound_event.h @@ -0,0 +1,47 @@ +/* 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_BILGE_AUTO_SOUND_EVENT_H +#define TITANIC_BILGE_AUTO_SOUND_EVENT_H + +#include "titanic/messages/auto_sound_event.h" + +namespace Titanic { + +class CBilgeAutoSoundEvent : public CAutoSoundEvent { +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_BILGE_AUTO_SOUND_EVENT_H */ diff --git a/engines/titanic/messages/bilge_dispensor_event.cpp b/engines/titanic/messages/bilge_dispensor_event.cpp new file mode 100644 index 0000000000..584da00a6f --- /dev/null +++ b/engines/titanic/messages/bilge_dispensor_event.cpp @@ -0,0 +1,77 @@ +/* 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/messages/bilge_dispensor_event.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBilgeDispensorEvent, CAutoSoundEvent) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +void CBilgeDispensorEvent::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CAutoSoundEvent::save(file, indent); +} + +void CBilgeDispensorEvent::load(SimpleFile *file) { + file->readNumber(); + CAutoSoundEvent::load(file); +} + +bool CBilgeDispensorEvent::EnterRoomMsg(CEnterRoomMsg *msg) { + _value1 = 0; + return true; +} + +bool CBilgeDispensorEvent::LeaveRoomMsg(CLeaveRoomMsg *msg) { + _value1 = -1; + return true; +} + +bool CBilgeDispensorEvent::FrameMsg(CFrameMsg *msg) { + if (_value1 >= 0 && (_value1 & 0xffff) == 0x4000) { + int volume = 20 + getRandomNumber(30); + int val3 = getRandomNumber(20) - 10; + + if (getRandomNumber(2) == 0) { + playSound("b#18.wav", volume, val3); + } + } + + CAutoSoundEvent::FrameMsg(msg); + return true; +} + +bool CBilgeDispensorEvent::StatusChangeMsg(CStatusChangeMsg *msg) { + if (msg->_newStatus == 1) + _value1 = -1; + else if (msg->_newStatus == 2) + _value1 = 0; + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/bilge_dispensor_event.h b/engines/titanic/messages/bilge_dispensor_event.h new file mode 100644 index 0000000000..61d3116db4 --- /dev/null +++ b/engines/titanic/messages/bilge_dispensor_event.h @@ -0,0 +1,54 @@ +/* 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_BILGE_DISPENSOR_EVENT_H +#define TITANIC_BILGE_DISPENSOR_EVENT_H + +#include "titanic/messages/auto_sound_event.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CBilgeDispensorEvent : public CAutoSoundEvent { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +public: + CLASSDEF; + CBilgeDispensorEvent() : CAutoSoundEvent() {} + + /** + * 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_BILGE_DISPENSOR_EVENT_H */ diff --git a/engines/titanic/messages/door_auto_sound_event.cpp b/engines/titanic/messages/door_auto_sound_event.cpp new file mode 100644 index 0000000000..7618577e50 --- /dev/null +++ b/engines/titanic/messages/door_auto_sound_event.cpp @@ -0,0 +1,65 @@ +/* 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/messages/door_auto_sound_event.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDoorAutoSoundEvent, CAutoSoundEvent) + ON_MESSAGE(PreEnterNodeMsg) + ON_MESSAGE(LeaveNodeMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +void CDoorAutoSoundEvent::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_fieldDC, indent); + file->writeNumberLine(_fieldE0, indent); + + CAutoSoundEvent::save(file, indent); +} + +void CDoorAutoSoundEvent::load(SimpleFile *file) { + file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + _fieldDC = file->readNumber(); + _fieldE0 = file->readNumber(); + + CAutoSoundEvent::load(file); +} + +bool CDoorAutoSoundEvent::PreEnterNodeMsg(CPreEnterNodeMsg *msg) { + return true; +} + +bool CDoorAutoSoundEvent::LeaveNodeMsg(CLeaveNodeMsg *msg) { + return true; +} + +bool CDoorAutoSoundEvent::TimerMsg(CTimerMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/door_auto_sound_event.h b/engines/titanic/messages/door_auto_sound_event.h new file mode 100644 index 0000000000..8b064a7221 --- /dev/null +++ b/engines/titanic/messages/door_auto_sound_event.h @@ -0,0 +1,59 @@ +/* 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_DOOR_AUTO_SOUND_EVENT_H +#define TITANIC_DOOR_AUTO_SOUND_EVENT_H + +#include "titanic/messages/auto_sound_event.h" + +namespace Titanic { + +class CDoorAutoSoundEvent : public CAutoSoundEvent { + DECLARE_MESSAGE_MAP; + bool PreEnterNodeMsg(CPreEnterNodeMsg *msg); + bool LeaveNodeMsg(CLeaveNodeMsg *msg); + bool TimerMsg(CTimerMsg *msg); +public: + CString _string1; + CString _string2; + int _fieldDC; + int _fieldE0; +public: + CLASSDEF; + CDoorAutoSoundEvent() : CAutoSoundEvent(), + _string1("z#44.wav"), _string2("z#43.wav"), _fieldDC(25), _fieldE0(25) { + } + + /** + * 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_DOOR_AUTO_SOUND_EVENT_H */ diff --git a/engines/titanic/messages/messages.cpp b/engines/titanic/messages/messages.cpp new file mode 100644 index 0000000000..5f587c975d --- /dev/null +++ b/engines/titanic/messages/messages.cpp @@ -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. + * + */ + +#include "titanic/messages/messages.h" +#include "titanic/messages/mouse_messages.h" +#include "titanic/core/game_object.h" +#include "titanic/core/message_target.h" +#include "titanic/core/tree_item.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CMessage::CMessage() : CSaveableObject() { +} + +void CMessage::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); +} + +void CMessage::load(SimpleFile *file) { + file->readNumber(); + CSaveableObject::load(file); +} + +bool CMessage::execute(CTreeItem *target, const ClassDef *classDef, int flags) { + // If no target was specified, then there's nothing to do + if (!target) + return false; + + bool result = false; + CTreeItem *item = target; + CTreeItem *nextItem = nullptr; + do { + if (flags & MSGFLAG_SCAN) + nextItem = item->scan(target); + + if (!classDef || item->isInstanceOf(classDef)) { + bool handled = perform(item); + + if (handled) { + result = true; + if (flags & MSGFLAG_BREAK_IF_HANDLED) + return true; + } + } + + item = nextItem; + } while (nextItem); + + return result; +} + +bool CMessage::execute(const CString &target, const ClassDef *classDef, int flags) { + // Scan for the target by name + CProjectItem *project = g_vm->_window->_project; + for (CTreeItem *treeItem = project; treeItem; treeItem = treeItem->scan(project)) { + if (!treeItem->getName().compareToIgnoreCase(target)) + return execute(treeItem, classDef, flags); + } + + return false; +} + +const MSGMAP_ENTRY *CMessage::findMapEntry(const CTreeItem *treeItem, const ClassDef *classDef) { + // Iterate through the class and any parent classes + for (const MSGMAP *msgMap = treeItem->getMessageMap(); msgMap->pFnGetBaseMap; + msgMap = msgMap->pFnGetBaseMap()) { + // Iterate through the map entries for this class + for (const MSGMAP_ENTRY *entry = msgMap->lpEntries; + entry->_class != nullptr; ++entry) { + // Check if the class or any of it's ancesotrs is handled by this entry + for (const ClassDef *entryDef = entry->_class; entryDef; entryDef = entryDef->_parent) { + if (entryDef == classDef) + return entry; + } + } + } + + return nullptr; +} + +bool CMessage::perform(CTreeItem *treeItem) { + const MSGMAP_ENTRY *entry = findMapEntry(treeItem, getType()); + return entry && (*treeItem.*(entry->_fn))(this); +} + +bool CMessage::supports(const CTreeItem *treeItem, ClassDef *classDef) { + return findMapEntry(treeItem, classDef) != nullptr; +} + +bool CMessage::isMouseMsg() const { + return dynamic_cast<const CMouseMsg *>(this) != nullptr; +} + +bool CMessage::isButtonDownMsg() const { + return dynamic_cast<const CMouseButtonDownMsg *>(this) != nullptr; +} + +bool CMessage::isButtonUpMsg() const { + return dynamic_cast<const CMouseButtonUpMsg *>(this) != nullptr; +} + +bool CMessage::isMouseMoveMsg() const { + return dynamic_cast<const CMouseMoveMsg *>(this) != nullptr; +} + +bool CMessage::isDoubleClickMsg() const { + return dynamic_cast<const CMouseDoubleClickMsg *>(this) != nullptr; +} + +bool CMessage::isEnterRoomMsg() const { + return dynamic_cast<const CEnterRoomMsg *>(this) != nullptr; +} + +bool CMessage::isPreEnterRoomMsg() const { + return dynamic_cast<const CPreEnterRoomMsg *>(this) != nullptr; +} + +bool CMessage::isleaveRoomMsg() const { + return dynamic_cast<const CLeaveRoomMsg *>(this) != nullptr; +} + +bool CMessage::isEnterNodeMsg() const { + return dynamic_cast<const CEnterNodeMsg *>(this) != nullptr; +} + +bool CMessage::isPreEnterNodeMsg() const { + return dynamic_cast<const CPreEnterNodeMsg *>(this) != nullptr; +} + +bool CMessage::isLeaveNodeMsg() const { + return dynamic_cast<const CLeaveNodeMsg *>(this) != nullptr; +} + +bool CMessage::isEnterViewMsg() const { + return dynamic_cast<const CEnterViewMsg *>(this) != nullptr; +} + +bool CMessage::isPreEnterViewMsg() const { + return dynamic_cast<const CPreEnterViewMsg *>(this) != nullptr; +} + +bool CMessage::isLeaveViewMsg() const { + return dynamic_cast<const CLeaveViewMsg *>(this) != nullptr; +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/messages.h b/engines/titanic/messages/messages.h new file mode 100644 index 0000000000..7ce92d190f --- /dev/null +++ b/engines/titanic/messages/messages.h @@ -0,0 +1,345 @@ +/* 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_MESSAGES_H +#define TITANIC_MESSAGES_H + +#include "common/keyboard.h" +#include "titanic/core/saveable_object.h" +#include "titanic/core/tree_item.h" + +namespace Titanic { + +enum MessageFlag { + MSGFLAG_SCAN = 1, + MSGFLAG_BREAK_IF_HANDLED = 2, + MSGFLAG_CLASS_DEF = 4 +}; + +#define MESSAGE0(NAME) \ + class NAME: public CMessage { \ + public: NAME() : CMessage() {} \ + CLASSDEF; \ + static bool isSupportedBy(const CTreeItem *item) { \ + return supports(item, _type); } \ +} +#define MESSAGE1(NAME, F1, N1, V1) \ + class NAME: public CMessage { \ + public: F1 _##N1; \ + NAME() : CMessage(), _##N1(V1) {} \ + NAME(F1 N1) : CMessage(), _##N1(N1) {} \ + CLASSDEF; \ + static bool isSupportedBy(const CTreeItem *item) { \ + return supports(item, _type); } \ +} +#define MESSAGE2(NAME, F1, N1, V1, F2, N2, V2) \ + class NAME: public CMessage { \ + public: F1 _##N1; F2 _##N2; \ + NAME() : CMessage(), _##N1(V1), _##N2(V2) {} \ + NAME(F1 N1, F2 N2) : CMessage(), _##N1(N1), _##N2(N2) {} \ + CLASSDEF; \ + static bool isSupportedBy(const CTreeItem *item) { \ + return supports(item, _type); } \ +} +#define MESSAGE3(NAME, F1, N1, V1, F2, N2, V2, F3, N3, V3) \ + class NAME: public CMessage { \ + public: F1 _##N1; F2 _##N2; F3 _##N3; \ + NAME() : CMessage(), _##N1(V1), _##N2(V2), _##N3(V3) {} \ + NAME(F1 N1, F2 N2, F3 N3) : CMessage(), _##N1(N1), _##N2(N2), _##N3(N3) {} \ + CLASSDEF; \ + static bool isSupportedBy(const CTreeItem *item) { \ + return supports(item, _type); } \ +} +#define MESSAGE4(NAME, F1, N1, V1, F2, N2, V2, F3, N3, V3, F4, N4, V4) \ + class NAME: public CMessage { \ + public: F1 _##N1; F2 _##N2; F3 _##N3; F4 _##N4; \ + NAME() : CMessage(), _##N1(V1), _##N2(V2), _##N3(V3), _##N4(V4) {} \ + NAME(F1 N1, F2 N2, F3 N3, F4 N4) : CMessage(), _##N1(N1), _##N2(N2), _##N3(N3), _##N4(N4) {} \ + CLASSDEF; \ + static bool isSupportedBy(const CTreeItem *item) { \ + return supports(item, _type); } \ +} + +class CCarry; +class CCharacter; +class CGameObject; +class CRoomItem; +class CNodeItem; +class CViewItem; +class CMusicPlayer; + +class CMessage : public CSaveableObject { +private: + /** + * Find a map entry that supports the given class + */ + static const MSGMAP_ENTRY *findMapEntry(const CTreeItem *treeItem, const ClassDef *classDef); +public: + CLASSDEF; + CMessage(); + + /** + * Executes the message, passing it on to the designated target, + * and optionally it's children + */ + bool execute(CTreeItem *target, const ClassDef *classDef = nullptr, + int flags = MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED); + + /** + * Executes the message, passing it on to the designated target, + * and optionally it's children + */ + bool execute(const CString &target, const ClassDef *classDef = nullptr, + int flags = MSGFLAG_SCAN | MSGFLAG_BREAK_IF_HANDLED); + + /** + * Makes the passed item execute the message + */ + virtual bool perform(CTreeItem *treeItem); + + /** + * Returns true if the passed item supports the specified message class + */ + static bool supports(const CTreeItem *treeItem, ClassDef *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); + + virtual bool isMouseMsg() const; + virtual bool isButtonDownMsg() const; + virtual bool isButtonUpMsg() const; + virtual bool isMouseMoveMsg() const; + virtual bool isDoubleClickMsg() const; + virtual bool isEnterRoomMsg() const; + virtual bool isPreEnterRoomMsg() const; + virtual bool isleaveRoomMsg() const; + virtual bool isEnterNodeMsg() const; + virtual bool isPreEnterNodeMsg() const; + virtual bool isLeaveNodeMsg() const; + virtual bool isEnterViewMsg() const; + virtual bool isPreEnterViewMsg() const; + virtual bool isLeaveViewMsg() const; +}; + +class CEditControlMsg : public CMessage { +public: + int _mode; + int _param; + CString _text; + byte _textR; + byte _textG; + byte _textB; +public: + CLASSDEF; + CEditControlMsg() : _mode(0), _param(0), _textR(0), _textG(0), _textB(0) {} + + static bool isSupportedBy(const CTreeItem *item) { + return CMessage::supports(item, _type); + } +}; + +MESSAGE1(CTimeMsg, uint, _ticks, 0); + +class CTimerMsg : public CTimeMsg { +public: + uint _timerCtr; + int _actionVal; + CString _action; +public: + CLASSDEF; + CTimerMsg() : CTimeMsg(), _timerCtr(0), _actionVal(0) {} + CTimerMsg(uint ticks, uint timerCtr, int actionVal, const CString &action) : + CTimeMsg(ticks), _timerCtr(timerCtr), _actionVal(actionVal), _action(action) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +MESSAGE1(CActMsg, CString, action, ""); +MESSAGE1(CActivationmsg, CString, value, ""); +MESSAGE1(CAddHeadPieceMsg, CString, value, "NULL"); +MESSAGE1(CAnimateMaitreDMsg, int, value, 0); +MESSAGE1(CArboretumGateMsg, int, value, 0); +MESSAGE0(CArmPickedUpFromTableMsg); +MESSAGE0(CBodyInBilgeRoomMsg); +MESSAGE1(CBowlStateChangeMsg, int, state, 0); +MESSAGE2(CCarryObjectArrivedMsg, CString, strValue, "", int, numValue, 0); +MESSAGE2(CChangeMusicMsg, CString, filename, "", int, flags, 0); +MESSAGE1(CChangeSeasonMsg, CString, season, "Summer"); +MESSAGE0(CCheckAllPossibleCodes); +MESSAGE2(CCheckChevCode, int, classNum, 0, uint, chevCode, 0); +MESSAGE1(CChildDragEndMsg, int, value, 0); +MESSAGE0(CClearChevPanelBits); +MESSAGE0(CCorrectMusicPlayedMsg); +MESSAGE0(CCreateMusicPlayerMsg); +MESSAGE0(CCylinderHolderReadyMsg); +MESSAGE0(CDeactivationMsg); +MESSAGE1(CDeliverCCarryMsg, CString, value, ""); +MESSAGE0(CDisableMaitreDProdReceptor); +MESSAGE0(CDismissBotMsg); +MESSAGE0(CDoffNavHelmet); +MESSAGE0(CDonNavHelmet); +MESSAGE1(CDoorbotNeededInElevatorMsg, int, value, 0); +MESSAGE0(CDoorbotNeededInHomeMsg); +MESSAGE1(CDropObjectMsg, CCarry *, item, nullptr); +MESSAGE1(CDropZoneGotObjectMsg, CGameObject *, object, nullptr); +MESSAGE1(CDropZoneLostObjectMsg, CGameObject *, object, nullptr); +MESSAGE1(CEjectCylinderMsg, int, value, 0); +MESSAGE2(CPreEnterNodeMsg, CNodeItem *, oldNode, nullptr, CNodeItem *, newNode, nullptr); +MESSAGE2(CPreEnterRoomMsg, CRoomItem *, oldRoom, nullptr, CRoomItem *, newRoom, nullptr); +MESSAGE2(CPreEnterViewMsg, CViewItem *, oldView, nullptr, CViewItem *, newView, nullptr); +MESSAGE2(CEnterNodeMsg, CNodeItem *, oldNode, nullptr, CNodeItem *, newNode, nullptr); +MESSAGE2(CEnterRoomMsg, CRoomItem *, oldRoom, nullptr, CRoomItem *, newRoom, nullptr); +MESSAGE2(CEnterViewMsg, CViewItem *, oldView, nullptr, CViewItem *, newView, nullptr); +MESSAGE0(CErasePhonographCylinderMsg); +MESSAGE1(CFrameMsg, uint, ticks, 0); +MESSAGE2(CFreshenCookieMsg, int, value1, 0, int, value2, 1); +MESSAGE1(CGetChevClassBits, int, classBits, 0); +MESSAGE1(CGetChevClassNum, int, classNum, 0); +MESSAGE2(CGetChevCodeFromRoomNameMsg, CString, roomName, "", uint, chevCode, 0); +MESSAGE1(CGetChevFloorBits, int, floorBits, 0); +MESSAGE1(CGetChevFloorNum, int, floorNum, 0); +MESSAGE1(CGetChevLiftBits, int, liftBits, 0); +MESSAGE1(CGetChevLiftNum, int, liftNum, 0); +MESSAGE1(CGetChevRoomBits, int, roomNum, 0); +MESSAGE1(CGetChevRoomNum, int, roomNum, 0); +MESSAGE2(CHoseConnectedMsg, int, value, 1, CGameObject *, object, nullptr); +MESSAGE0(CInitializeAnimMsg); +MESSAGE1(CIsEarBowlPuzzleDone, int, value, 0); +MESSAGE3(CIsHookedOnMsg, Rect, rect, Rect(), bool, result, false, CString, string1, ""); +MESSAGE1(CIsParrotPresentMsg, bool, value, false); +MESSAGE1(CKeyCharMsg, int, key, 32); +MESSAGE2(CLeaveNodeMsg, CNodeItem *, oldNode, nullptr, CNodeItem *, newNode, nullptr); +MESSAGE2(CLeaveRoomMsg, CRoomItem *, oldRoom, nullptr, CRoomItem *, newRoom, nullptr); +MESSAGE2(CLeaveViewMsg, CViewItem *, oldView, nullptr, CViewItem *, newView, nullptr); +MESSAGE1(CLemonFallsFromTreeMsg, Point, pt, Point()); +MESSAGE4(CLightsMsg, bool, flag1, false, bool, flag2, false, bool, flag3, false, bool, flag4, false); +MESSAGE1(CLoadSuccessMsg, int, ticks, 0); +MESSAGE1(CLockPhonographMsg, int, value, 0); +MESSAGE0(CMaitreDDefeatedMsg); +MESSAGE0(CMaitreDHappyMsg); +MESSAGE1(CMissiveOMatActionMsg, int, action, 0); +MESSAGE0(CMoveToStartPosMsg); +MESSAGE2(CMovieEndMsg, int, startFrame, 0, int, endFrame, 0); +MESSAGE2(CMovieFrameMsg, int, frameNumber, 0, int, value2, 0); +MESSAGE0(CMusicHasStartedMsg); +MESSAGE0(CMusicHasStoppedMsg); +MESSAGE0(CMusicSettingChangedMsg); +MESSAGE2(CNPCPlayAnimationMsg, const char *const *, names, nullptr, int, value2, 0); +MESSAGE1(CNPCPlayIdleAnimationMsg, const char *const *, names, 0); +MESSAGE3(CNPCPlayTalkingAnimationMsg, int, value1, 0, int, value2, 0, const char *const *, names, nullptr); +MESSAGE0(CNPCQueueIdleAnimMsg); +MESSAGE1(CNutPuzzleMsg, CString, value, ""); +MESSAGE1(COnSummonBotMsg, int, value, 0); +MESSAGE0(COpeningCreditsMsg); +MESSAGE1(CPanningAwayFromParrotMsg, CTreeItem *, target, nullptr); +MESSAGE2(CParrotSpeakMsg, CString, target, "", CString, action, ""); +MESSAGE2(CParrotTriesChickenMsg, int, value1, 0, int, value2, 0); +MESSAGE1(CPhonographPlayMsg, int, value, 0); +MESSAGE0(CPhonographReadyToPlayMsg); +MESSAGE1(CPhonographRecordMsg, int, value, 0); +MESSAGE3(CPhonographStopMsg, int, value1, 0, int, value2, 0, int, value3, 0); +MESSAGE2(CPlayRangeMsg, int, value1, 0, int, value2, 0); +MESSAGE2(CPlayerTriesRestaurantTableMsg, int, value1, 0, int, value2, 0); +MESSAGE1(CPreSaveMsg, int, value, 0); +MESSAGE1(CProdMaitreDMsg, int, value, 0); +MESSAGE2(CPumpingMsg, int, value, 0, CGameObject *, object, nullptr); +MESSAGE1(CPutBotBackInHisBoxMsg, int, value, 0); +MESSAGE1(CPutParrotBackMsg, int, value, 0); +MESSAGE0(CPuzzleSolvedMsg); +MESSAGE3(CQueryCylinderHolderMsg, int, value1, 0, int, value2, 0, CTreeItem *, target, (CTreeItem *)nullptr); +MESSAGE1(CQueryCylinderMsg, CString, name, ""); +MESSAGE1(CQueryCylinderNameMsg, CString, name, ""); +MESSAGE3(CQueryCylinderTypeMsg, int, value1, 0, int, value2, 0, int, value3, 0); +MESSAGE1(CQueryMusicControlSettingMsg, int, value, 0); +MESSAGE1(CQueryPhonographState, int, value, 0); +MESSAGE0(CRecordOntoCylinderMsg); +MESSAGE0(CRemoveFromGameMsg); +MESSAGE0(CReplaceBowlAndNutsMsg); +MESSAGE1(CRestaurantMusicChanged, CString, value, ""); +MESSAGE2(CSendCCarryMsg, CString, strValue, "", int, numValue, 0); +MESSAGE1(CSenseWorkingMsg, CString, value, "Not Working"); +MESSAGE2(CServiceElevatorFloorChangeMsg, int, value1, 0, int, value2, 0); +MESSAGE0(CServiceElevatorFloorRequestMsg); +MESSAGE1(CServiceElevatorMsg, int, value, 4); +MESSAGE2(CSetChevButtonImageMsg, int, value1, 0, int, value2, 0); +MESSAGE1(CSetChevClassBits, int, classNum, 0); +MESSAGE1(CSetChevFloorBits, int, floorNum, 0); +MESSAGE1(CSetChevLiftBits, int, liftNum, 0); +MESSAGE2(CSetChevPanelBitMsg, int, value1, 0, int, value2, 0); +MESSAGE1(CSetChevPanelButtonsMsg, int, chevCode, 0); +MESSAGE1(CSetChevRoomBits, int, roomNum, 0); +MESSAGE1(CSetFrameMsg, int, frameNumber, 0); +MESSAGE0(CSetMusicControlsMsg); +MESSAGE2(CSetVarMsg, CString, varName, "", int, value, 0); +MESSAGE2(CSetVolumeMsg, int, volume, 70, int, secondsTransition, 0); +MESSAGE2(CShipSettingMsg, int, value, 0, CString, name, ""); +MESSAGE1(CShowTextMsg, CString, value, "NO TEXT INCLUDED!!!"); +MESSAGE2(CSignalObject, CString, strValue, "", int, numValue, 0); +MESSAGE2(CSpeechFallsFromTreeMsg, int, value1, 0, int, value2, 0); +MESSAGE1(CStartMusicMsg, CMusicPlayer *, musicPlayer, (CMusicPlayer *)nullptr); +MESSAGE3(CStatusChangeMsg, int, oldStatus, 0, int, newStatus, 0, bool, success, false); +MESSAGE1(CStopMusicMsg, CMusicPlayer *, musicPlayer, (CMusicPlayer *)nullptr); +MESSAGE4(CSubAcceptCCarryMsg, CString, string1, "", int, value1, 0, int, value2, 0, CCarry *, item, nullptr); +MESSAGE0(CSubDeliverCCarryMsg); +MESSAGE0(CSubSendCCarryMsg); +MESSAGE0(CSUBTransition); +MESSAGE0(CSubTurnOffMsg); +MESSAGE0(CSubTurnOnMsg); +MESSAGE2(CSummonBotMsg, CString, npcName, "", int, value, 0); +MESSAGE1(CSummonBotQueryMsg, CString, npcName, ""); +MESSAGE1(CTakeHeadPieceMsg, CString, value, "NULL"); +MESSAGE2(CTextInputMsg, CString, input, "", CString, response, ""); +MESSAGE1(CTimeDilationMsg, int, value, 0); +MESSAGE0(CTitleSequenceEndedMsg); +MESSAGE0(CTransitMsg); +MESSAGE1(CTranslateObjectMsg, Point, delta, Point()); +MESSAGE3(CTransportMsg, CString, roomName, "", int, value1, 0, int, value2, 0); +MESSAGE1(CTriggerAutoMusicPlayerMsg, int, value, 0); +MESSAGE1(CTriggerNPCEvent, int, value, 0); +MESSAGE4(CTrueTalkGetAnimSetMsg, int, value1, 0, uint, index, 0, uint, startFrame, 0, uint, endFrame, 0); +MESSAGE2(CTrueTalkGetAssetDetailsMsg, CString, filename, "", int, numValue, 0); +MESSAGE2(CTrueTalkGetStateValueMsg, int, stateNum, 0, int, stateVal, -1000); +MESSAGE2(CTrueTalkNotifySpeechEndedMsg, int, value1, 0, int, dialogueId, 0); +MESSAGE3(CTrueTalkNotifySpeechStartedMsg, uint, soundId, 0, uint, dialogueId, 0, int, value, 0); +MESSAGE1(CTrueTalkQueueUpAnimSetMsg, int, value, 0); +MESSAGE0(CTrueTalkSelfQueueAnimSetMsg); +MESSAGE3(CTrueTalkTriggerActionMsg, int, action, 0, int, param1, 0, int, param2, 0); +MESSAGE0(CTurnOff); +MESSAGE0(CTurnOn); +MESSAGE1(CUse, CGameObject *, item, nullptr); +MESSAGE1(CUseWithCharMsg, CCharacter *, character, nullptr); +MESSAGE1(CUseWithOtherMsg, CGameObject *, other, 0); +MESSAGE1(CVirtualKeyCharMsg, Common::KeyState, keyState, Common::KeyState()); +MESSAGE1(CVisibleMsg, bool, visible, true); + +} // End of namespace Titanic + +#endif /* TITANIC_MESSAGE_H */ diff --git a/engines/titanic/messages/mouse_messages.cpp b/engines/titanic/messages/mouse_messages.cpp new file mode 100644 index 0000000000..18fa625c1c --- /dev/null +++ b/engines/titanic/messages/mouse_messages.cpp @@ -0,0 +1,47 @@ +/* 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/messages/mouse_messages.h" +#include "titanic/support/mouse_cursor.h" +#include "titanic/support/screen_manager.h" + +namespace Titanic { + +void CMouseButtonDownMsg::generate() { + CInputHandler &inputHandler = *CScreenManager::_screenManagerPtr->_inputHandler; + const Point &mousePos = inputHandler._mousePos; + + CMouseButtonDownMsg msg(mousePos, MB_LEFT); + inputHandler.handleMessage(msg, false); +} + +/*------------------------------------------------------------------------*/ + +void CMouseButtonUpMsg::generate() { + CInputHandler &inputHandler = *CScreenManager::_screenManagerPtr->_inputHandler; + const Point &mousePos = inputHandler._mousePos; + + CMouseButtonUpMsg msg(mousePos, MB_LEFT); + inputHandler.handleMessage(msg, false); +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/mouse_messages.h b/engines/titanic/messages/mouse_messages.h new file mode 100644 index 0000000000..e7c419bbdc --- /dev/null +++ b/engines/titanic/messages/mouse_messages.h @@ -0,0 +1,210 @@ +/* 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_MOUSE_MESSAGES_H +#define TITANIC_MOUSE_MESSAGES_H + +#include "titanic/support/rect.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +enum MouseButton { MB_LEFT = 1, MB_MIDDLE = 2, MB_RIGHT = 4 }; + +class CMouseMsg : public CMessage { +public: + int _buttons; + Point _mousePos; +public: + CLASSDEF; + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } + + CMouseMsg() : _buttons(0) {} + CMouseMsg(const Point &pt, int buttons) : + _mousePos(pt), _buttons(buttons) {} +}; + +class CMouseMoveMsg : public CMouseMsg { +public: + CLASSDEF; + CMouseMoveMsg() : CMouseMsg() {} + CMouseMoveMsg(const Point &pt, int buttons) : CMouseMsg(pt, buttons) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CMouseButtonMsg : public CMouseMsg { +public: + int _field10; +public: + CLASSDEF; + CMouseButtonMsg() : CMouseMsg(), _field10(0) {} + CMouseButtonMsg(const Point &pt, int buttons) : CMouseMsg(pt, buttons) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CMouseButtonDownMsg : public CMouseButtonMsg { +public: + CLASSDEF; + CMouseButtonDownMsg() : CMouseButtonMsg() {} + CMouseButtonDownMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } + + /** + * Generate a dummy mouse down message at the current mouse position + */ + static void generate(); +}; + +class CMouseButtonUpMsg : public CMouseButtonMsg { +public: + CLASSDEF; + CMouseButtonUpMsg() : CMouseButtonMsg() {} + CMouseButtonUpMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } + + /** + * Generate a dummy mouse up message at the current mouse position + */ + static void generate(); +}; + +class CMouseDoubleClickMsg : public CMouseButtonMsg { +public: + CLASSDEF; + CMouseDoubleClickMsg() : CMouseButtonMsg() {} + CMouseDoubleClickMsg(const Point &pt, int buttons) : CMouseButtonMsg(pt, buttons) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CMouseDragMsg : public CMouseMsg { +public: + CLASSDEF; + CMouseDragMsg() : CMouseMsg() {} + CMouseDragMsg(const Point &pt) : CMouseMsg(pt, 0) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CMouseDragMoveMsg : public CMouseDragMsg { +public: + CLASSDEF; + CMouseDragMoveMsg() : CMouseDragMsg() {} + CMouseDragMoveMsg(const Point &pt) : CMouseDragMsg(pt) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CMouseDragStartMsg : public CMouseDragMsg { +public: + CTreeItem *_dragItem; + bool _handled; +public: + CLASSDEF; + CMouseDragStartMsg() : CMouseDragMsg(), _dragItem(nullptr), _handled(false) {} + CMouseDragStartMsg(const Point &pt) : CMouseDragMsg(pt), + _dragItem(nullptr), _handled(false) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CPassOnDragStartMsg : public CMessage { +public: + Point _mousePos; + int _value3; + int _value4; +public: + CLASSDEF; + CPassOnDragStartMsg() : CMessage() {} + CPassOnDragStartMsg(const Point &pt, int v3 = 0, int v4 = 0) : + CMessage(), _mousePos(pt), _value3(v3), _value4(v4) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CMouseDragEndMsg : public CMouseDragMsg { +public: + CGameObject *_dropTarget; +public: + CLASSDEF; + CMouseDragEndMsg() : CMouseDragMsg(), _dropTarget(nullptr) {} + CMouseDragEndMsg(const Point &pt, CGameObject *dropTarget = nullptr) : + CMouseDragMsg(pt), _dropTarget(dropTarget) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CChildDragMoveMsg : public CMessage { +public: + Point _mousePos; +public: + CLASSDEF; + CChildDragMoveMsg() : CMessage() {} + CChildDragMoveMsg(const Point &pt) : CMessage(), _mousePos(pt) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +class CChildDragStartMsg : public CMessage { +public: + Point _mousePos; +public: + CLASSDEF; + CChildDragStartMsg() : CMessage() {} + CChildDragStartMsg(const Point &pt) : CMessage(), _mousePos(pt) {} + + static bool isSupportedBy(const CTreeItem *item) { + return supports(item, _type); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MOUSE_MESSAGES_H */ diff --git a/engines/titanic/messages/pet_messages.h b/engines/titanic/messages/pet_messages.h new file mode 100644 index 0000000000..60981726ed --- /dev/null +++ b/engines/titanic/messages/pet_messages.h @@ -0,0 +1,64 @@ +/* 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_MESSAGES_H +#define TITANIC_PET_MESSAGES_H + +#include "titanic/messages/messages.h" + +namespace Titanic { + +MESSAGE0(CPETDeliverMsg); +MESSAGE0(CPETGainedObjectMsg); +MESSAGE0(CPETHelmetOnOffMsg); +MESSAGE0(CPETKeyboardOnOffMsg); +MESSAGE0(CPETLostObjectMsg); +MESSAGE0(CPETObjectSelectedMsg); +MESSAGE1(CPETObjectStateMsg, int, value, 0); +MESSAGE0(CPETPhotoOnOffMsg); +MESSAGE1(CPETPlaySoundMsg, int, soundNum, 0); +MESSAGE0(CPETReceiveMsg); +MESSAGE0(CPETSetStarDestinationMsg); +MESSAGE1(CPETStarFieldLockMsg, int, value, 0); +MESSAGE0(CPETStereoFieldOnOffMsg); +MESSAGE2(CPETTargetMsg, CString, name, "", int, numValue, -1); + +#define PET_MESSAGE(NAME) \ + class NAME: public CPETTargetMsg { \ + public: \ + NAME() : CPETTargetMsg() {} \ + NAME(const CString &name, int num) : CPETTargetMsg(name, num) {} \ + CLASSDEF; \ + static bool isSupportedBy(const CTreeItem *item) { \ + return supports(item, _type); \ + } \ +} + +PET_MESSAGE(CPETDownMsg); +PET_MESSAGE(CPETUpMsg); +PET_MESSAGE(CPETLeftMsg); +PET_MESSAGE(CPETRightMsg); +PET_MESSAGE(CPETActivateMsg); + +} // End of namespace Titanic + +#endif /* TITANIC_PET_MESSAGES_H */ diff --git a/engines/titanic/messages/service_elevator_door.cpp b/engines/titanic/messages/service_elevator_door.cpp new file mode 100644 index 0000000000..748790e4aa --- /dev/null +++ b/engines/titanic/messages/service_elevator_door.cpp @@ -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. + * + */ + +#include "titanic/messages/service_elevator_door.h" + +namespace Titanic { + +CServiceElevatorDoor::CServiceElevatorDoor() : CDoorAutoSoundEvent() { + _string1 = "z#31.wav"; + _string2 = "z#32.wav"; +} + +void CServiceElevatorDoor::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string2, indent); + file->writeQuotedLine(_string1, indent); + + CDoorAutoSoundEvent::save(file, indent); +} + +void CServiceElevatorDoor::load(SimpleFile *file) { + file->readNumber(); + _string2 = file->readString(); + _string1 = file->readString(); + + CDoorAutoSoundEvent::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/messages/service_elevator_door.h b/engines/titanic/messages/service_elevator_door.h new file mode 100644 index 0000000000..cc8da0917d --- /dev/null +++ b/engines/titanic/messages/service_elevator_door.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_SERVICE_ELEVATOR_DOOR_H +#define TITANIC_SERVICE_ELEVATOR_DOOR_H + +#include "titanic/messages/door_auto_sound_event.h" + +namespace Titanic { + +class CServiceElevatorDoor : public CDoorAutoSoundEvent { +public: + CLASSDEF; + CServiceElevatorDoor(); + + /** + * 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_SERVICE_ELEVATOR_DOOR_H */ diff --git a/engines/titanic/module.mk b/engines/titanic/module.mk new file mode 100644 index 0000000000..90d010b57b --- /dev/null +++ b/engines/titanic/module.mk @@ -0,0 +1,528 @@ +MODULE := engines/titanic + +MODULE_OBJS := \ + continue_save_dialog.o \ + debugger.o \ + detection.o \ + events.o \ + game_location.o \ + game_manager.o \ + game_state.o \ + game_view.o \ + input_handler.o \ + input_translator.o \ + main_game_window.o \ + room_flags.o \ + titanic.o \ + carry/auditory_centre.o \ + carry/arm.o \ + carry/bowl_ear.o \ + carry/brain.o \ + carry/bridge_piece.o \ + carry/carry.o \ + carry/carry_parrot.o \ + carry/central_core.o \ + carry/chicken.o \ + carry/crushed_tv.o \ + carry/ear.o \ + carry/eye.o \ + carry/feathers.o \ + carry/fruit.o \ + carry/glass.o \ + carry/hammer.o \ + carry/head_piece.o \ + carry/hose.o \ + carry/hose_end.o \ + carry/key.o \ + carry/liftbot_head.o \ + carry/long_stick.o \ + carry/magazine.o \ + carry/maitred_left_arm.o \ + carry/maitred_right_arm.o \ + carry/mouth.o \ + carry/napkin.o \ + carry/nose.o \ + carry/note.o \ + carry/parcel.o \ + carry/perch.o \ + carry/phonograph_cylinder.o \ + carry/phonograph_ear.o \ + carry/photograph.o \ + carry/plug_in.o \ + carry/speech_centre.o \ + carry/sweets.o \ + carry/vision_centre.o \ + core/background.o \ + core/click_responder.o \ + core/dont_save_file_item.o \ + core/drop_target.o \ + core/file_item.o \ + core/game_object.o \ + core/game_object_desc_item.o \ + core/link_item.o \ + core/list.o \ + core/mail_man.o \ + core/message_target.o \ + core/multi_drop_target.o \ + core/named_item.o \ + core/node_item.o \ + core/project_item.o \ + core/resource_key.o \ + core/room_item.o \ + core/saveable_object.o \ + core/static_image.o \ + core/turn_on_object.o \ + core/turn_on_play_sound.o \ + core/turn_on_turn_off.o \ + core/tree_item.o \ + core/view_item.o \ + game/announce.o \ + game/annoy_barbot.o \ + game/arb_background.o \ + game/arboretum_gate.o \ + game/auto_animate.o \ + game/bar_menu.o \ + game/bar_menu_button.o \ + game/bar_bell.o \ + game/belbot_get_light.o \ + game/bottom_of_well_monitor.o \ + game/bomb.o \ + game/bowl_unlocker.o \ + game/brain_slot.o \ + game/bridge_door.o \ + game/bridge_view.o \ + game/broken_pell_base.o \ + game/broken_pellerator.o \ + game/broken_pellerator_froz.o \ + game/cage.o \ + game/captains_wheel.o \ + game/cdrom.o \ + game/cdrom_computer.o \ + game/cdrom_tray.o \ + game/cell_point_button.o \ + game/chev_code.o \ + game/chev_panel.o \ + game/chicken_cooler.o \ + game/chicken_dispensor.o \ + game/close_broken_pel.o \ + game/code_wheel.o \ + game/cookie.o \ + game/computer.o \ + game/computer_screen.o \ + game/credits.o \ + game/credits_button.o \ + game/dead_area.o \ + game/desk_click_responder.o \ + game/doorbot_elevator_handler.o \ + game/doorbot_home_handler.o \ + game/ear_sweet_bowl.o \ + game/eject_phonograph_button.o \ + game/elevator_action_area.o \ + game/emma_control.o \ + game/empty_nut_bowl.o \ + game/end_credit_text.o \ + game/end_credits.o \ + game/end_explode_ship.o \ + game/end_game_credits.o \ + game/end_sequence_control.o \ + game/hammer_dispensor.o \ + game/hammer_dispensor_button.o \ + game/fan.o \ + game/fan_control.o \ + game/fan_decrease.o \ + game/fan_increase.o \ + game/fan_noises.o \ + game/floor_indicator.o \ + game/games_console.o \ + game/get_lift_eye2.o \ + game/glass_smasher.o \ + game/hammer_clip.o \ + game/head_slot.o \ + game/head_smash_event.o \ + game/head_smash_lever.o \ + game/head_spinner.o \ + game/idle_summoner.o \ + game/leave_sec_class_state.o \ + game/lemon_dispensor.o \ + game/light.o \ + game/light_switch.o \ + game/little_lift_button.o \ + game/long_stick_dispenser.o \ + game/missiveomat.o \ + game/missiveomat_button.o \ + game/movie_tester.o \ + game/music_console_button.o \ + game/music_room_phonograph.o \ + game/music_room_stop_phonograph_button.o \ + game/music_system_lock.o \ + game/musical_instrument.o \ + game/nav_helmet.o \ + game/nav_helmet_off.o \ + game/nav_helmet_on.o \ + game/navigation_computer.o \ + game/no_nut_bowl.o \ + game/nose_holder.o \ + game/null_port_hole.o \ + game/nut_replacer.o \ + game/pet_disabler.o \ + game/phonograph.o \ + game/phonograph_lid.o \ + game/play_music_button.o \ + game/play_on_act.o \ + game/port_hole.o \ + game/record_phonograph_button.o \ + game/replacement_ear.o \ + game/reserved_table.o \ + game/restaurant_cylinder_holder.o \ + game/restaurant_phonograph.o \ + game/sauce_dispensor.o \ + game/search_point.o \ + game/season_background.o \ + game/season_barrel.o \ + game/seasonal_adjustment.o \ + game/service_elevator_window.o \ + game/ship_setting.o \ + game/ship_setting_button.o \ + game/show_cell_points.o \ + game/speech_dispensor.o \ + game/splash_animation.o \ + game/starling_puret.o \ + game/start_action.o \ + game/stop_phonograph_button.o \ + game/sub_glass.o \ + game/sub_wrapper.o \ + game/sweet_bowl.o \ + game/television.o \ + game/third_class_canal.o \ + game/tow_parrot_nav.o \ + game/throw_tv_down_well.o \ + game/titania_still_control.o \ + game/up_lighter.o \ + game/useless_lever.o \ + game/volume_control.o \ + game/wheel_button.o \ + game/wheel_hotspot.o \ + game/wheel_spin.o \ + game/wheel_spin_horn.o \ + game/gondolier/gondolier_base.o \ + game/gondolier/gondolier_chest.o \ + game/gondolier/gondolier_face.o \ + game/gondolier/gondolier_mixer.o \ + game/gondolier/gondolier_slider.o \ + game/maitred/maitred_arm_holder.o \ + game/maitred/maitred_body.o \ + game/maitred/maitred_legs.o \ + game/maitred/maitred_prod_receptor.o \ + game/parrot/parrot_lobby_controller.o \ + game/parrot/parrot_lobby_link_updater.o \ + game/parrot/parrot_lobby_object.o \ + game/parrot/parrot_lobby_view_object.o \ + game/parrot/parrot_loser.o \ + game/parrot/parrot_nut_bowl_actor.o \ + game/parrot/parrot_nut_eater.o \ + game/parrot/parrot_perch_holder.o \ + game/parrot/parrot_trigger.o \ + game/parrot/player_meets_parrot.o \ + game/pet/pet.o \ + game/pet/pet_class1.o \ + game/pet/pet_class2.o \ + game/pet/pet_class3.o \ + game/pet/pet_lift.o \ + game/pet/pet_monitor.o \ + game/pet/pet_pellerator.o \ + game/pet/pet_position.o \ + game/pet/pet_sentinal.o \ + game/pet/pet_sounds.o \ + game/pet/pet_transition.o \ + game/pet/pet_transport.o \ + game/pickup/pick_up.o \ + game/pickup/pick_up_bar_glass.o \ + game/pickup/pick_up_hose.o \ + game/pickup/pick_up_lemon.o \ + game/pickup/pick_up_speech_centre.o \ + game/pickup/pick_up_vis_centre.o \ + game/placeholder/bar_shelf_vis_centre.o \ + game/placeholder/place_holder.o \ + game/placeholder/lemon_on_bar.o \ + game/placeholder/tv_on_bar.o \ + game/transport/gondolier.o \ + game/transport/lift.o \ + game/transport/lift_indicator.o \ + game/transport/pellerator.o \ + game/transport/service_elevator.o \ + game/transport/transport.o \ + game/sgt/armchair.o \ + game/sgt/basin.o \ + game/sgt/bedfoot.o \ + game/sgt/bedhead.o \ + game/sgt/chest_of_drawers.o \ + game/sgt/desk.o \ + game/sgt/deskchair.o \ + game/sgt/drawer.o \ + game/sgt/sgt_doors.o \ + game/sgt/sgt_nav.o \ + game/sgt/sgt_navigation.o \ + game/sgt/sgt_restaurant_doors.o \ + game/sgt/sgt_state_control.o \ + game/sgt/sgt_state_room.o \ + game/sgt/sgt_tv.o \ + game/sgt/sgt_upper_doors_sound.o \ + game/sgt/toilet.o \ + game/sgt/vase.o \ + game/sgt/washstand.o \ + gfx/act_button.o \ + gfx/changes_season_button.o \ + gfx/chev_left_off.o \ + gfx/chev_left_on.o \ + gfx/chev_right_off.o \ + gfx/chev_right_on.o \ + gfx/chev_send_rec_switch.o \ + gfx/chev_switch.o \ + gfx/edit_control.o \ + gfx/elevator_button.o \ + gfx/get_from_succ.o \ + gfx/helmet_on_off.o \ + gfx/home_photo.o \ + gfx/icon_nav_action.o \ + gfx/icon_nav_butt.o \ + gfx/icon_nav_down.o \ + gfx/icon_nav_image.o \ + gfx/icon_nav_left.o \ + gfx/icon_nav_receive.o \ + gfx/icon_nav_right.o \ + gfx/icon_nav_send.o \ + gfx/icon_nav_up.o \ + gfx/keybrd_butt.o \ + gfx/move_object_button.o \ + gfx/music_control.o \ + gfx/music_slider.o \ + gfx/music_slider_pitch.o \ + gfx/music_slider_speed.o \ + gfx/music_switch.o \ + gfx/music_switch_inversion.o \ + gfx/music_switch_reverse.o \ + gfx/music_voice_mute.o \ + gfx/send_to_succ.o \ + gfx/sgt_selector.o \ + gfx/slider_button.o \ + gfx/small_chev_left_off.o \ + gfx/small_chev_left_on.o \ + gfx/small_chev_right_off.o \ + gfx/small_chev_right_on.o \ + gfx/status_change_button.o \ + gfx/st_button.o \ + gfx/text_down.o \ + gfx/text_skrew.o \ + gfx/text_up.o \ + gfx/toggle_button.o \ + gfx/toggle_switch.o \ + messages/auto_sound_event.o \ + messages/bilge_auto_sound_event.o \ + messages/bilge_dispensor_event.o \ + messages/door_auto_sound_event.o \ + messages/messages.o \ + messages/mouse_messages.o \ + messages/service_elevator_door.o \ + moves/call_pellerator.o \ + moves/enter_bomb_room.o \ + moves/enter_bridge.o \ + moves/enter_exit_first_class_state.o \ + moves/enter_exit_mini_lift.o \ + moves/enter_exit_sec_class_mini_lift.o \ + moves/enter_exit_view.o \ + moves/enter_sec_class_state.o \ + moves/exit_arboretum.o \ + moves/exit_bridge.o \ + moves/exit_lift.o \ + moves/exit_pellerator.o \ + moves/exit_state_room.o \ + moves/exit_tiania.o \ + moves/move_player_in_parrot_room.o \ + moves/move_player_to_from.o \ + moves/move_player_to.o \ + moves/multi_move.o \ + moves/pan_from_pel.o \ + moves/restaurant_pan_handler.o \ + moves/restricted_move.o \ + moves/scraliontis_table.o \ + moves/trip_down_canal.o \ + npcs/barbot.o \ + npcs/bellbot.o \ + npcs/bilge_succubus.o \ + npcs/callbot.o \ + npcs/character.o \ + npcs/deskbot.o \ + npcs/doorbot.o \ + npcs/liftbot.o \ + npcs/maitre_d.o \ + npcs/mobile.o \ + npcs/parrot.o \ + npcs/parrot_succubus.o \ + npcs/robot_controller.o \ + npcs/starlings.o \ + npcs/succubus.o \ + npcs/summon_bots.o \ + npcs/titania.o \ + npcs/true_talk_npc.o \ + pet_control/pet_control.o \ + pet_control/pet_conversations.o \ + pet_control/pet_element.o \ + pet_control/pet_frame.o \ + pet_control/pet_gfx_element.o \ + pet_control/pet_inventory.o \ + pet_control/pet_inventory_glyphs.o \ + pet_control/pet_message.o \ + pet_control/pet_starfield.o \ + pet_control/pet_real_life.o \ + pet_control/pet_remote.o \ + pet_control/pet_remote_glyphs.o \ + pet_control/pet_rooms.o \ + pet_control/pet_rooms_glyphs.o \ + pet_control/pet_section.o \ + pet_control/pet_drag_chev.o \ + pet_control/pet_graphic2.o \ + pet_control/pet_graphic.o \ + pet_control/pet_glyphs.o \ + pet_control/pet_leaf.o \ + pet_control/pet_load.o \ + pet_control/pet_load_save.o \ + pet_control/pet_mode_off.o \ + pet_control/pet_mode_on.o \ + pet_control/pet_mode_panel.o \ + pet_control/pet_pannel1.o \ + pet_control/pet_pannel2.o \ + pet_control/pet_pannel3.o \ + pet_control/pet_quit.o \ + pet_control/pet_save.o \ + pet_control/pet_slider.o \ + pet_control/pet_sound.o \ + pet_control/pet_text.o \ + sound/auto_music_player.o \ + sound/auto_music_player_base.o \ + sound/auto_sound_player.o \ + sound/auto_sound_player_adsr.o \ + sound/background_sound_maker.o \ + sound/bird_song.o \ + sound/dome_from_top_of_well.o \ + sound/enter_view_toggles_other_music.o \ + sound/gondolier_song.o \ + sound/music_handler.o \ + sound/music_room.o \ + sound/music_player.o \ + sound/music_wave.o \ + sound/node_auto_sound_player.o \ + sound/proximity.o \ + sound/qmixer.o \ + sound/restricted_auto_music_player.o \ + sound/room_auto_sound_player.o \ + sound/room_trigger_auto_music_player.o \ + sound/season_noises.o \ + sound/seasonal_music_player.o \ + sound/sound.o \ + sound/sound_manager.o \ + sound/titania_speech.o \ + sound/trigger_auto_music_player.o \ + sound/view_auto_sound_player.o \ + sound/view_toggles_other_music.o \ + sound/water_lapping_sounds.o \ + sound/wave_file.o \ + star_control/star_control.o \ + star_control/base_star.o \ + star_control/dmatrix.o \ + star_control/dvector.o \ + star_control/fmatrix.o \ + star_control/fpoint.o \ + star_control/fvector.o \ + star_control/star_control_sub2.o \ + star_control/star_control_sub4.o \ + star_control/star_control_sub5.o \ + star_control/star_control_sub6.o \ + star_control/star_control_sub7.o \ + star_control/star_control_sub8.o \ + star_control/star_control_sub12.o \ + star_control/star_control_sub13.o \ + star_control/star_control_sub20.o \ + star_control/star_control_sub21.o \ + star_control/star_control_sub22.o \ + star_control/star_control_sub23.o \ + star_control/star_control_sub24.o \ + star_control/star_control_sub25.o \ + star_control/star_control_sub26.o \ + star_control/star_control_sub27.o \ + star_control/star_field.o \ + star_control/star_points1.o \ + star_control/star_points2.o \ + star_control/star_view.o \ + star_control/surface_area.o \ + star_control/surface_fader_base.o \ + star_control/surface_fader.o \ + support/avi_surface.o \ + support/direct_draw.o \ + support/direct_draw_surface.o \ + support/exe_resources.o \ + support/files_manager.o \ + support/font.o \ + support/image.o \ + support/image_decoders.o \ + support/mouse_cursor.o \ + support/movie.o \ + support/movie_clip.o \ + support/movie_event.o \ + support/movie_range_info.o \ + support/movie_manager.o \ + support/credit_text.o \ + support/rect.o \ + support/screen_manager.o \ + support/simple_file.o \ + support/string.o \ + support/string_parser.o \ + support/text_cursor.o \ + support/time_event_info.o \ + support/video_surface.o \ + true_talk/barbot_script.o \ + true_talk/bellbot_script.o \ + true_talk/deskbot_script.o \ + true_talk/dialogue_file.o \ + true_talk/doorbot_script.o \ + true_talk/liftbot_script.o \ + true_talk/maitred_script.o \ + true_talk/parrot_script.o \ + true_talk/succubus_script.o \ + true_talk/title_engine.o \ + true_talk/script_handler.o \ + true_talk/script_support.o \ + true_talk/true_talk_manager.o \ + true_talk/tt_action.o \ + true_talk/tt_adj.o \ + true_talk/tt_concept.o \ + true_talk/tt_concept_node.o \ + true_talk/tt_hist.o \ + true_talk/tt_major_word.o \ + true_talk/tt_node.o \ + true_talk/tt_npc_script.o \ + true_talk/tt_parser.o \ + true_talk/tt_picture.o \ + true_talk/tt_pronoun.o \ + true_talk/tt_quotes.o \ + true_talk/tt_quotes_tree.o \ + true_talk/tt_response.o \ + true_talk/tt_room_script.o \ + true_talk/tt_script_base.o \ + true_talk/tt_scripts.o \ + true_talk/tt_sentence.o \ + true_talk/tt_sentence_node.o \ + true_talk/tt_string.o \ + true_talk/tt_string_node.o \ + true_talk/tt_synonym.o \ + true_talk/tt_talker.o \ + true_talk/tt_title_script.o \ + true_talk/tt_vocab.o \ + true_talk/tt_word.o + +# This module can be built as a plugin +ifeq ($(ENABLE_TITANIC), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/titanic/moves/call_pellerator.cpp b/engines/titanic/moves/call_pellerator.cpp new file mode 100644 index 0000000000..0dd8195277 --- /dev/null +++ b/engines/titanic/moves/call_pellerator.cpp @@ -0,0 +1,82 @@ +/* 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/moves/call_pellerator.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCallPellerator, CGameObject) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(PETActivateMsg) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CCallPellerator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CGameObject::save(file, indent); +} + +void CCallPellerator::load(SimpleFile *file) { + file->readNumber(); + CGameObject::load(file); +} + +bool CCallPellerator::EnterViewMsg(CEnterViewMsg *msg) { + petSetArea(PET_REMOTE); + petHighlightGlyph(1); + CString name = getFullViewName(); + + if (name == "TopOfWell.Node 6.S") { + petDisplayMessage(2, "You are standing outside the Pellerator."); + } + + petSetRemoteTarget(); + return true; +} + +bool CCallPellerator::LeaveViewMsg(CLeaveViewMsg *msg) { + petClear(); + return true; +} + +bool CCallPellerator::PETActivateMsg(CPETActivateMsg *msg) { + CString name = getFullViewName(); + + if (msg->_name == "Pellerator") { + if (petDoorOrBellbotPresent()) { + petDisplayMessage("I'm sorry, you cannot enter this pellerator at present as a bot is in the way."); + } else if (name == "Bar.Node 1.S") { + changeView("Pellerator.Node 1.S"); + } else { + changeView("Pellerator.Node 1.N"); + } + } + + return true; +} + +bool CCallPellerator::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/call_pellerator.h b/engines/titanic/moves/call_pellerator.h new file mode 100644 index 0000000000..3a1ef3823a --- /dev/null +++ b/engines/titanic/moves/call_pellerator.h @@ -0,0 +1,53 @@ +/* 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_CALL_PELLERATOR_H +#define TITANIC_CALL_PELLERATOR_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CCallPellerator : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool PETActivateMsg(CPETActivateMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *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_CALL_PELLERATOR_H */ diff --git a/engines/titanic/moves/enter_bomb_room.cpp b/engines/titanic/moves/enter_bomb_room.cpp new file mode 100644 index 0000000000..9956c669ee --- /dev/null +++ b/engines/titanic/moves/enter_bomb_room.cpp @@ -0,0 +1,50 @@ +/* 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/moves/enter_bomb_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterBombRoom, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CEnterBombRoom::CEnterBombRoom() : CMovePlayerTo(), _fieldC8(0) { +} + +void CEnterBombRoom::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMovePlayerTo::save(file, indent); +} + +void CEnterBombRoom::load(SimpleFile *file) { + file->readNumber(); + CMovePlayerTo::load(file); +} + +bool CEnterBombRoom::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + changeView("Titania.Node 2.SE"); + changeView(_destination); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_bomb_room.h b/engines/titanic/moves/enter_bomb_room.h new file mode 100644 index 0000000000..ccdd51f37b --- /dev/null +++ b/engines/titanic/moves/enter_bomb_room.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_ENTER_BOMB_ROOM_H +#define TITANIC_ENTER_BOMB_ROOM_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CEnterBombRoom : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +protected: + int _fieldC8; +public: + CLASSDEF; + CEnterBombRoom(); + + /** + * 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_ENTER_BOMB_ROOM_H */ diff --git a/engines/titanic/moves/enter_bridge.cpp b/engines/titanic/moves/enter_bridge.cpp new file mode 100644 index 0000000000..fb44fe2e02 --- /dev/null +++ b/engines/titanic/moves/enter_bridge.cpp @@ -0,0 +1,55 @@ +/* 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/moves/enter_bridge.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterBridge, CGameObject) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +void CEnterBridge::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CGameObject::save(file, indent); +} + +void CEnterBridge::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CGameObject::load(file); +} + +bool CEnterBridge::EnterRoomMsg(CEnterRoomMsg *msg) { + if (_flag) { + CActMsg actMsg("Disable"); + actMsg.execute("ShipAnnouncements"); + + setState1C(false); + _flag = false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_bridge.h b/engines/titanic/moves/enter_bridge.h new file mode 100644 index 0000000000..837c0e9f7d --- /dev/null +++ b/engines/titanic/moves/enter_bridge.h @@ -0,0 +1,53 @@ +/* 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_ENTER_BRIDGE_H +#define TITANIC_ENTER_BRIDGE_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CEnterBridge : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); +private: + bool _flag; +public: + CLASSDEF; + CEnterBridge() : CGameObject(), _flag(true) {} + + /** + * 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_ENTER_BRIDGE_H */ diff --git a/engines/titanic/moves/enter_exit_first_class_state.cpp b/engines/titanic/moves/enter_exit_first_class_state.cpp new file mode 100644 index 0000000000..34e9984aa7 --- /dev/null +++ b/engines/titanic/moves/enter_exit_first_class_state.cpp @@ -0,0 +1,67 @@ +/* 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/moves/enter_exit_first_class_state.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterExitFirstClassState, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +void CEnterExitFirstClassState::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_viewName, indent); + CGameObject::save(file, indent); +} + +void CEnterExitFirstClassState::load(SimpleFile *file) { + file->readNumber(); + _viewName = file->readString(); + CGameObject::load(file); +} + +bool CEnterExitFirstClassState::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + switch (getPassengerClass()) { + case 1: + if (compareRoomNameTo("1stClassLobby")) { + _viewName = getRoomNodeName() + ".E"; + changeView(_viewName); + } else if (compareRoomNameTo("1stClassState")) { + changeView(_viewName); + } + break; + + case 2: + petDisplayMessage(1, "This room is reserved for the exclusive use of first class passengeres." + " That does not currently include you"); + break; + + default: + petDisplayMessage("No losers."); + break; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_exit_first_class_state.h b/engines/titanic/moves/enter_exit_first_class_state.h new file mode 100644 index 0000000000..fe63e553de --- /dev/null +++ b/engines/titanic/moves/enter_exit_first_class_state.h @@ -0,0 +1,51 @@ +/* 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_ENTER_EXIT_FIRST_CLASS_STATE_H +#define TITANIC_ENTER_EXIT_FIRST_CLASS_STATE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEnterExitFirstClassState : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + CString _viewName; +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_ENTER_EXIT_FIRST_CLASS_STATE_H */ diff --git a/engines/titanic/moves/enter_exit_mini_lift.cpp b/engines/titanic/moves/enter_exit_mini_lift.cpp new file mode 100644 index 0000000000..e626d70a9e --- /dev/null +++ b/engines/titanic/moves/enter_exit_mini_lift.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/moves/enter_exit_mini_lift.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterExitMiniLift, CSGTNavigation) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +void CEnterExitMiniLift::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeNumberLine(_destRoomNum, indent); + + CSGTNavigation::save(file, indent); +} + +void CEnterExitMiniLift::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _destRoomNum = file->readNumber(); + + CSGTNavigation::load(file); +} + +bool CEnterExitMiniLift::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (compareRoomNameTo("SgtLobby")) { + _statics->_destView = getRoomNodeName() + ".S"; + _statics->_destRoom = "SgtLobby"; + changeView("SGTLittleLift.Node 1.E"); + + CPetControl *pet = getPetControl(); + if (pet) + pet->setRoomsRoomNum(_destRoomNum); + } else if (compareRoomNameTo("SGTLittleLift")) { + if (_statics->_changeViewFlag) { + changeView(_statics->_destView); + } + } + + return true; +} + +bool CEnterExitMiniLift::EnterViewMsg(CEnterViewMsg *msg) { + _cursorId = _statics->_changeViewFlag ? CURSOR_MOVE_FORWARD : CURSOR_INVALID; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_exit_mini_lift.h b/engines/titanic/moves/enter_exit_mini_lift.h new file mode 100644 index 0000000000..f2671a89b2 --- /dev/null +++ b/engines/titanic/moves/enter_exit_mini_lift.h @@ -0,0 +1,54 @@ +/* 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_ENTER_EXIT_MINI_LIFT_H +#define TITANIC_ENTER_EXIT_MINI_LIFT_H + +#include "titanic/game/sgt/sgt_navigation.h" + +namespace Titanic { + +class CEnterExitMiniLift : public CSGTNavigation { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +private: + int _fieldBC; + int _destRoomNum; +public: + CLASSDEF; + CEnterExitMiniLift() : CSGTNavigation(), _fieldBC(0), _destRoomNum(1) {} + + /** + * 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_ENTER_EXIT_MINI_LIFT_H */ diff --git a/engines/titanic/moves/enter_exit_sec_class_mini_lift.cpp b/engines/titanic/moves/enter_exit_sec_class_mini_lift.cpp new file mode 100644 index 0000000000..c7e16ef84e --- /dev/null +++ b/engines/titanic/moves/enter_exit_sec_class_mini_lift.cpp @@ -0,0 +1,94 @@ +/* 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/moves/enter_exit_sec_class_mini_lift.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterExitSecClassMiniLift, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +CEnterExitSecClassMiniLiftStatics *CEnterExitSecClassMiniLift::_statics; + +void CEnterExitSecClassMiniLift::init() { + _statics = new CEnterExitSecClassMiniLiftStatics(); +} + +void CEnterExitSecClassMiniLift::deinit() { + delete _statics; +} + +void CEnterExitSecClassMiniLift::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_statics->_viewName, indent); + file->writeNumberLine(_statics->_state, indent); + file->writeNumberLine(_roomNum, indent); + + CGameObject::save(file, indent); +} + +void CEnterExitSecClassMiniLift::load(SimpleFile *file) { + file->readNumber(); + _statics->_viewName = file->readString(); + _statics->_state = file->readNumber(); + _roomNum = file->readNumber(); + + CGameObject::load(file); +} + +bool CEnterExitSecClassMiniLift::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (compareRoomNameTo("2ndClassLobby")) { + _statics->_viewName = getRoomNodeName() + ".W"; + changeView("SecClassLittleLift.Node 1.E"); + _statics->_state = 1; + + CPetControl *pet = getPetControl(); + if (pet) { + pet->setRoomsRoomNum(_roomNum); + pet->setRooms1CC(1); + } + } else if (compareRoomNameTo("SecClassLittleLift")) { + if (_statics->_state == 1) { + changeView(_statics->_viewName); + } + } + + return true; +} + +bool CEnterExitSecClassMiniLift::StatusChangeMsg(CStatusChangeMsg *msg) { + _statics->_state = msg->_newStatus; + if (msg->_newStatus == 3) + _statics->_state = 2; + + CPetControl *pet = getPetControl(); + if (pet) + pet->setRooms1CC(_statics->_state); + + _cursorId = _statics->_state == 1 ? CURSOR_MOVE_FORWARD : CURSOR_INVALID; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_exit_sec_class_mini_lift.h b/engines/titanic/moves/enter_exit_sec_class_mini_lift.h new file mode 100644 index 0000000000..839d2c04fa --- /dev/null +++ b/engines/titanic/moves/enter_exit_sec_class_mini_lift.h @@ -0,0 +1,63 @@ +/* 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_ENTER_EXIT_SEC_CLASS_MINI_LIFT_H +#define TITANIC_ENTER_EXIT_SEC_CLASS_MINI_LIFT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +struct CEnterExitSecClassMiniLiftStatics { + CString _viewName; + int _state; + + CEnterExitSecClassMiniLiftStatics() : _state(1) {} +}; + +class CEnterExitSecClassMiniLift : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +private: + static CEnterExitSecClassMiniLiftStatics *_statics; + int _roomNum; +public: + CLASSDEF; + CEnterExitSecClassMiniLift() : CGameObject(), _roomNum(0) {} + static void init(); + static void deinit(); + + /** + * 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_ENTER_EXIT_SEC_CLASS_MINI_LIFT_H */ diff --git a/engines/titanic/moves/enter_exit_view.cpp b/engines/titanic/moves/enter_exit_view.cpp new file mode 100644 index 0000000000..6778ebb52a --- /dev/null +++ b/engines/titanic/moves/enter_exit_view.cpp @@ -0,0 +1,78 @@ +/* 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/moves/enter_exit_view.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterExitView, CGameObject) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +CEnterExitView::CEnterExitView() : CGameObject(), _leaveEndFrame(0), + _leaveStartFrame(0), _enterEndFrame(0), _enterStartFrame(0), + _visibleAfterMovie(true) { +} + +void CEnterExitView::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_leaveEndFrame, indent); + file->writeNumberLine(_leaveStartFrame, indent); + file->writeNumberLine(_enterEndFrame, indent); + file->writeNumberLine(_enterStartFrame, indent); + file->writeNumberLine(_visibleAfterMovie, indent); + + CGameObject::save(file, indent); +} + +void CEnterExitView::load(SimpleFile *file) { + file->readNumber(); + _leaveEndFrame = file->readNumber(); + _leaveStartFrame = file->readNumber(); + _enterEndFrame = file->readNumber(); + _enterStartFrame = file->readNumber(); + _visibleAfterMovie = file->readNumber(); + + CGameObject::load(file); +} + +bool CEnterExitView::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(true); + playMovie(_enterStartFrame, _enterEndFrame, MOVIE_NOTIFY_OBJECT); + return true; +} + +bool CEnterExitView::LeaveViewMsg(CLeaveViewMsg *msg) { + setVisible(true); + playMovie(_leaveStartFrame, _leaveEndFrame, MOVIE_NOTIFY_OBJECT); + return true; +} + +bool CEnterExitView::MovieEndMsg(CMovieEndMsg *msg) { + if (!_visibleAfterMovie) + setVisible(false); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_exit_view.h b/engines/titanic/moves/enter_exit_view.h new file mode 100644 index 0000000000..67aa5643ff --- /dev/null +++ b/engines/titanic/moves/enter_exit_view.h @@ -0,0 +1,58 @@ +/* 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_ENTER_EXIT_VIEW_H +#define TITANIC_ENTER_EXIT_VIEW_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEnterExitView : public CGameObject { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +public: + int _leaveEndFrame; + int _leaveStartFrame; + int _enterEndFrame; + int _enterStartFrame; + bool _visibleAfterMovie; +public: + CLASSDEF; + CEnterExitView(); + + /** + * 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_ENTER_EXIT_VIEW_H */ diff --git a/engines/titanic/moves/enter_sec_class_state.cpp b/engines/titanic/moves/enter_sec_class_state.cpp new file mode 100644 index 0000000000..2a35621003 --- /dev/null +++ b/engines/titanic/moves/enter_sec_class_state.cpp @@ -0,0 +1,108 @@ +/* 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/moves/enter_sec_class_state.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterSecClassState, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(MovieEndMsg) +END_MESSAGE_MAP() + +void CEnterSecClassState::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_mode, indent); + file->writeNumberLine(_soundHandle, indent); + + CGameObject::save(file, indent); +} + +void CEnterSecClassState::load(SimpleFile *file) { + file->readNumber(); + _mode = file->readNumber(); + _soundHandle = file->readNumber(); + + CGameObject::load(file); +} + +bool CEnterSecClassState::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (getPassengerClass() > 2) { + playSound("b#105.wav"); + petDisplayMessage(1, "Passengers of your class are not permitted to enter this area."); + } else if (!compareRoomNameTo("SecClassLittleLift") || _mode == 2) { + CActMsg actMsg(getFullViewName().deleteRight(3) + ".S"); + actMsg.execute("SecClassRoomLeaver"); + changeView("secClassState.Node 01.N"); + } + + return true; +} + +bool CEnterSecClassState::StatusChangeMsg(CStatusChangeMsg *msg) { + stopSound(_soundHandle); + + if (msg->_newStatus == _mode || (_mode == 2 && msg->_newStatus == 3)) { + if (_mode == 2) { + _soundHandle = queueSound("b#36.wav", _soundHandle); + } else { + _soundHandle = queueSound("b#31.wav", _soundHandle); + } + if (msg->_newStatus == 3) + msg->_newStatus = 2; + } else { + changeView("SecClassLittleLift.Node 1.N"); + if (msg->_newStatus == 1) { + _soundHandle = queueSound("b#32.wav", _soundHandle); + } else if (msg->_newStatus == 2) { + _soundHandle = queueSound("b#25.wav", _soundHandle); + } else if (msg->_newStatus == 3) { + _soundHandle = queueSound("b#33.wav", _soundHandle); + msg->_newStatus = 2; + } + } + + if (msg->_newStatus != 3) { + if (msg->_newStatus == 2 && _mode == 1) + playMovie(0, 10, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + else if (msg->_newStatus == 1) + playMovie(11, 21, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + + _cursorId = msg->_newStatus == 2 ? CURSOR_MOVE_FORWARD : CURSOR_INVALID; + _mode = msg->_newStatus; + return true; +} + +bool CEnterSecClassState::MovieEndMsg(CMovieEndMsg *msg) { + CPetControl *pet = getPetControl(); + if (pet) { + pet->setRooms1CC(_mode); + pet->resetRoomsHighlight(); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/enter_sec_class_state.h b/engines/titanic/moves/enter_sec_class_state.h new file mode 100644 index 0000000000..2b1bcaa401 --- /dev/null +++ b/engines/titanic/moves/enter_sec_class_state.h @@ -0,0 +1,54 @@ +/* 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_ENTER_SEC_CLASS_STATE_H +#define TITANIC_ENTER_SEC_CLASS_STATE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CEnterSecClassState : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); +public: + int _mode, _soundHandle; +public: + CLASSDEF; + CEnterSecClassState() : CGameObject(), _mode(1), _soundHandle(0) {} + + /** + * 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_ENTER_SEC_CLASS_STATE_H */ diff --git a/engines/titanic/moves/exit_arboretum.cpp b/engines/titanic/moves/exit_arboretum.cpp new file mode 100644 index 0000000000..e0c2ab9c9d --- /dev/null +++ b/engines/titanic/moves/exit_arboretum.cpp @@ -0,0 +1,105 @@ +/* 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/moves/exit_arboretum.h" +#include "titanic/game/seasonal_adjustment.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CExitArboretum, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +CExitArboretum::CExitArboretum() : CMovePlayerTo(), + _seasonNum(0), _fieldCC(0), _enabled(true) { +} + +void CExitArboretum::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_seasonNum, indent); + file->writeNumberLine(_fieldCC, indent); + file->writeNumberLine(_enabled, indent); + + CMovePlayerTo::save(file, indent); +} + +void CExitArboretum::load(SimpleFile *file) { + file->readNumber(); + _seasonNum = file->readNumber(); + _fieldCC = file->readNumber(); + _enabled = file->readNumber(); + + CMovePlayerTo::load(file); +} + +bool CExitArboretum::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_enabled) { + CActMsg actMsg; + if (_seasonNum == AUTUMN) { + switch (_fieldCC) { + case 0: + actMsg._action = "ExitLFrozen"; + break; + case 1: + actMsg._action = "ExitRFrozen"; + break; + default: + break; + } + } else { + switch (_fieldCC) { + case 0: + actMsg._action = "ExitLNormal"; + break; + case 1: + actMsg._action = "ExitRNormal"; + break; + default: + break; + } + } + + actMsg.execute("ArbGate"); + } + + return true; +} + +bool CExitArboretum::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + _seasonNum = (_seasonNum + 1) % 4; + return true; +} + +bool CExitArboretum::TurnOn(CTurnOn *msg) { + _enabled = false; + return true; +} + +bool CExitArboretum::TurnOff(CTurnOff *msg) { + _enabled = true; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/exit_arboretum.h b/engines/titanic/moves/exit_arboretum.h new file mode 100644 index 0000000000..b65eb92b17 --- /dev/null +++ b/engines/titanic/moves/exit_arboretum.h @@ -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. + * + */ + +#ifndef TITANIC_EXIT_ARBORETUM_H +#define TITANIC_EXIT_ARBORETUM_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CExitArboretum : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); +protected: + int _seasonNum; + int _fieldCC; + bool _enabled; +public: + CLASSDEF; + CExitArboretum(); + + /** + * 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_BACKGROUND_H */ diff --git a/engines/titanic/moves/exit_bridge.cpp b/engines/titanic/moves/exit_bridge.cpp new file mode 100644 index 0000000000..6b69b88004 --- /dev/null +++ b/engines/titanic/moves/exit_bridge.cpp @@ -0,0 +1,58 @@ +/* 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/moves/exit_bridge.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CExitBridge, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CExitBridge::CExitBridge() : CMovePlayerTo(), _viewName("Titania.Node 1.S") { +} + +void CExitBridge::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_viewName, indent); + + CMovePlayerTo::save(file, indent); +} + +void CExitBridge::load(SimpleFile *file) { + file->readNumber(); + _viewName = file->readString(); + + CMovePlayerTo::load(file); +} + +bool CExitBridge::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (getGameManager()) { + changeView(_destination); + playSound("a#53.wav"); + changeView(_viewName); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/exit_bridge.h b/engines/titanic/moves/exit_bridge.h new file mode 100644 index 0000000000..6d8ba01c91 --- /dev/null +++ b/engines/titanic/moves/exit_bridge.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_EXIT_BRIDGE_H +#define TITANIC_EXIT_BRIDGE_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CExitBridge : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + CString _viewName; +public: + CLASSDEF; + CExitBridge(); + + /** + * 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_EXIT_BRIDGE_H */ diff --git a/engines/titanic/moves/exit_lift.cpp b/engines/titanic/moves/exit_lift.cpp new file mode 100644 index 0000000000..de9a3117af --- /dev/null +++ b/engines/titanic/moves/exit_lift.cpp @@ -0,0 +1,121 @@ +/* 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/moves/exit_lift.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CExitLift, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CExitLift::CExitLift() : CGameObject(), _viewName("NULL") { +} + +void CExitLift::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_viewName, indent); + CGameObject::save(file, indent); +} + +void CExitLift::load(SimpleFile *file) { + file->readNumber(); + _viewName = file->readString(); + CGameObject::load(file); +} + +bool CExitLift::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CPetControl *pet = getPetControl(); + int floorNum = pet->getRoomsFloorNum();//ebx + int elevNum = pet->getRoomsElevatorNum(); //eax + + if (floorNum == 39) { + switch (elevNum) { + case 1: + _viewName = "BottomOfWell.Node 5.SE"; + break; + case 3: + _viewName = "BottomOfWell.Node 1.NW"; + break; + default: + break; + } + } else if (floorNum > 27) { + switch (elevNum) { + case 1: + case 2: + _viewName = "SgtLobby.Node 1.N"; + break; + default: + break; + } + } else if (floorNum > 19) { + switch (elevNum) { + case 0: + case 2: + _viewName = "2ndClassLobby.Node 8.N"; + break; + case 1: + case 3: + _viewName = "2ndClassLobby.Node 1.N"; + break; + default: + break; + } + } else if (floorNum > 1) { + switch (elevNum) { + case 0: + case 2: + _viewName = "1stClassLobby.Node 1.W"; + break; + case 1: + case 3: + _viewName = "1stClassLobby.Node 1.E"; + break; + default: + break; + } + } else { + switch (elevNum) { + case 0: + _viewName = "TopOfWell.Node 6.E"; + break; + case 1: + _viewName = "TopOfWell.Node 6.W"; + break; + case 2: + _viewName = "TopOfWell.Node 10.W"; + break; + case 3: + _viewName = "TopOfWell.Node 10.E"; + break; + default: + break; + } + } + + changeView(_viewName); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/exit_lift.h b/engines/titanic/moves/exit_lift.h new file mode 100644 index 0000000000..93d760c35a --- /dev/null +++ b/engines/titanic/moves/exit_lift.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_EXIT_LIFT_H +#define TITANIC_EXIT_LIFT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CExitLift : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + CString _viewName; +public: + CLASSDEF; + CExitLift(); + + /** + * 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_EXIT_LIFT_H */ diff --git a/engines/titanic/moves/exit_pellerator.cpp b/engines/titanic/moves/exit_pellerator.cpp new file mode 100644 index 0000000000..12ca2c1e3c --- /dev/null +++ b/engines/titanic/moves/exit_pellerator.cpp @@ -0,0 +1,137 @@ +/* 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/moves/exit_pellerator.h" +#include "titanic/game/transport/pellerator.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CExitPellerator, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(ChangeSeasonMsg) +END_MESSAGE_MAP() + +CExitPelleratorStatics *CExitPellerator::_statics; + +void CExitPellerator::init() { + _statics = new CExitPelleratorStatics(); +} + +void CExitPellerator::deinit() { + delete _statics; +} + +void CExitPellerator::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_statics->_v1, indent); + file->writeNumberLine(_statics->_v2, indent); + file->writeNumberLine(_statics->_isWinter, indent); + + CGameObject::save(file, indent); +} + +void CExitPellerator::load(SimpleFile *file) { + file->readNumber(); + _statics->_v1 = file->readString(); + _statics->_v2 = file->readNumber(); + _statics->_isWinter = file->readNumber(); + + CGameObject::load(file); +} + +bool CExitPellerator::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CString name = getName(); + + if (name == "ExitPellerator") { + if (_statics->_v2 != 2) { + switch (getRandomNumber(2)) { + case 0: + CPellerator::_soundHandle = queueSound("z#457.wav", CPellerator::_soundHandle); + break; + case 1: + CPellerator::_soundHandle = queueSound("z#458.wav", CPellerator::_soundHandle); + break; + default: + CPellerator::_soundHandle = queueSound("z#464.wav", CPellerator::_soundHandle); + break; + } + } + + switch (_statics->_v2) { + case 0: + changeView("PromenadeDeck.Node 1.W"); + break; + case 1: + changeView("MusicRoomLobby.Node 1.S"); + break; + case 4: + changeView("TopOfWell.Node 6.N"); + break; + case 5: + changeView("1stClassRestaurant.Lobby Node.E"); + break; + case 6: + changeView(_statics->_isWinter ? "FrozenArboretum.Node 4.S" : "Arboretum.Node 4.W"); + break; + default: + petDisplayMessage(2, "Please exit from the other side."); + CPellerator::_soundHandle = queueSound("z#438.wav", CPellerator::_soundHandle); + + } + } else if (name == "ExitPellerator2") { + if (_statics->_v2 == 2) { + switch (getRandomNumber(2)) { + case 0: + CPellerator::_soundHandle = queueSound("z#457.wav", CPellerator::_soundHandle); + break; + case 1: + CPellerator::_soundHandle = queueSound("z#458.wav", CPellerator::_soundHandle); + break; + default: + CPellerator::_soundHandle = queueSound("z#464.wav", CPellerator::_soundHandle); + break; + } + } + + if (_statics->_v2 == 2) { + changeView("Bar.Node 1.N"); + } else { + petDisplayMessage(2, "Please exit from the other side."); + CPellerator::_soundHandle = queueSound("z#438.wav", CPellerator::_soundHandle); + } + } + + return true; +} + +bool CExitPellerator::StatusChangeMsg(CStatusChangeMsg *msg) { + _statics->_v2 = msg->_newStatus; + return true; +} + +bool CExitPellerator::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + _statics->_isWinter = msg->_season == "Winter"; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/exit_pellerator.h b/engines/titanic/moves/exit_pellerator.h new file mode 100644 index 0000000000..8819d64355 --- /dev/null +++ b/engines/titanic/moves/exit_pellerator.h @@ -0,0 +1,61 @@ +/* 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_EXIT_PELLERATOR_H +#define TITANIC_EXIT_PELLERATOR_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +struct CExitPelleratorStatics { + CString _v1; + int _v2; + bool _isWinter; +}; + +class CExitPellerator : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); +private: + static CExitPelleratorStatics *_statics; +public: + CLASSDEF; + static void init(); + static void deinit(); + + /** + * 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_EXIT_PELLERATOR_H */ diff --git a/engines/titanic/moves/exit_state_room.cpp b/engines/titanic/moves/exit_state_room.cpp new file mode 100644 index 0000000000..f0b0534c12 --- /dev/null +++ b/engines/titanic/moves/exit_state_room.cpp @@ -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. + * + */ + +#include "titanic/moves/exit_state_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CExitStateRoom, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CExitStateRoom::CExitStateRoom() : CMovePlayerTo() { +} + +void CExitStateRoom::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMovePlayerTo::save(file, indent); +} + +void CExitStateRoom::load(SimpleFile *file) { + file->readNumber(); + CMovePlayerTo::load(file); +} + +bool CExitStateRoom::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + changeView(_destination); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/exit_state_room.h b/engines/titanic/moves/exit_state_room.h new file mode 100644 index 0000000000..19322ced7f --- /dev/null +++ b/engines/titanic/moves/exit_state_room.h @@ -0,0 +1,50 @@ +/* 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_EXIT_STATE_ROOM_H +#define TITANIC_EXIT_STATE_ROOM_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CExitStateRoom : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + CLASSDEF; + CExitStateRoom(); + + /** + * 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_EXIT_STATE_ROOM_H */ diff --git a/engines/titanic/moves/exit_tiania.cpp b/engines/titanic/moves/exit_tiania.cpp new file mode 100644 index 0000000000..fb0f149ba9 --- /dev/null +++ b/engines/titanic/moves/exit_tiania.cpp @@ -0,0 +1,73 @@ +/* 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/moves/exit_tiania.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CExitTiania, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CExitTiania::CExitTiania() : CMovePlayerTo(), _fieldC8(0) { + _viewNames[0] = _viewNames[1] = _viewNames[2] = "NULL"; +} + +void CExitTiania::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeQuotedLine(_viewNames[0], indent); + file->writeQuotedLine(_viewNames[1], indent); + file->writeQuotedLine(_viewNames[2], indent); + + CMovePlayerTo::save(file, indent); +} + +void CExitTiania::load(SimpleFile *file) { + file->readNumber(); + _fieldC8 = file->readNumber(); + _viewNames[0] = file->readString(); + _viewNames[1] = file->readString(); + _viewNames[2] = file->readString(); + + CMovePlayerTo::load(file); +} + +bool CExitTiania::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (getPassengerClass() == 4) { + petDisplayMessage(1, "For mysterious and unknowable reasons, " + "this transport is temporarily out of order."); + } else { + lockMouse(); + for (int idx = 0; idx < 3; ++idx) + changeView(_viewNames[idx]); + changeView("Titania.Node 16.N"); + changeView("Dome.Node 4.N"); + changeView("Dome.Node 3.N"); + changeView("Dome.Node 3.S"); + unlockMouse(); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/exit_tiania.h b/engines/titanic/moves/exit_tiania.h new file mode 100644 index 0000000000..b911e102d1 --- /dev/null +++ b/engines/titanic/moves/exit_tiania.h @@ -0,0 +1,53 @@ +/* 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_EXIT_TIANIA_H +#define TITANIC_EXIT_TIANIA_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CExitTiania : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + int _fieldC8; + CString _viewNames[3]; +public: + CLASSDEF; + CExitTiania(); + + /** + * 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_EXIT_TIANIA_H */ diff --git a/engines/titanic/moves/move_player_in_parrot_room.cpp b/engines/titanic/moves/move_player_in_parrot_room.cpp new file mode 100644 index 0000000000..1ef2e96e92 --- /dev/null +++ b/engines/titanic/moves/move_player_in_parrot_room.cpp @@ -0,0 +1,61 @@ +/* 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/moves/move_player_in_parrot_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMovePlayerInParrotRoom, CMovePlayerTo) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CMovePlayerInParrotRoom::CMovePlayerInParrotRoom() : CMovePlayerTo() { +} + +void CMovePlayerInParrotRoom::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMovePlayerTo::save(file, indent); +} + +void CMovePlayerInParrotRoom::load(SimpleFile *file) { + file->readNumber(); + CMovePlayerTo::load(file); +} + +bool CMovePlayerInParrotRoom::ActMsg(CActMsg *msg) { + if (msg->_action == "PanAwayFromParrot") { + unlockMouse(); + changeView(_destination); + } + + return true; +} + +bool CMovePlayerInParrotRoom::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + lockMouse(); + CPanningAwayFromParrotMsg awayMsg(this); + awayMsg.execute("PerchedParrot"); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/move_player_in_parrot_room.h b/engines/titanic/moves/move_player_in_parrot_room.h new file mode 100644 index 0000000000..54dc2eb992 --- /dev/null +++ b/engines/titanic/moves/move_player_in_parrot_room.h @@ -0,0 +1,51 @@ +/* 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_MOVE_PLAYER_IN_PARROT_ROOM_H +#define TITANIC_MOVE_PLAYER_IN_PARROT_ROOM_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CMovePlayerInParrotRoom : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +public: + CLASSDEF; + CMovePlayerInParrotRoom(); + + /** + * 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_MOVE_PLAYER_IN_PARROT_ROOM_H */ diff --git a/engines/titanic/moves/move_player_to.cpp b/engines/titanic/moves/move_player_to.cpp new file mode 100644 index 0000000000..a91215b539 --- /dev/null +++ b/engines/titanic/moves/move_player_to.cpp @@ -0,0 +1,63 @@ +/* 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/moves/move_player_to.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMovePlayerTo, CGameObject) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +CMovePlayerTo::CMovePlayerTo() : CGameObject() { +} + +void CMovePlayerTo::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_destination, indent); + + CGameObject::save(file, indent); +} + +void CMovePlayerTo::load(SimpleFile *file) { + file->readNumber(); + _destination = file->readString(); + + CGameObject::load(file); +} + +bool CMovePlayerTo::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CGameManager *gameManager = getGameManager(); + if (gameManager) + changeView(_destination); + + return true; +} + +bool CMovePlayerTo::ActMsg(CActMsg *msg) { + _destination = msg->_action; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/move_player_to.h b/engines/titanic/moves/move_player_to.h new file mode 100644 index 0000000000..822df69422 --- /dev/null +++ b/engines/titanic/moves/move_player_to.h @@ -0,0 +1,53 @@ +/* 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_MOVE_PLAYER_TO_H +#define TITANIC_MOVE_PLAYER_TO_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CMovePlayerTo : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool ActMsg(CActMsg *msg); +protected: + CString _destination; +public: + CLASSDEF; + CMovePlayerTo(); + + /** + * 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_MOVE_PLAYER_TO_H */ diff --git a/engines/titanic/moves/move_player_to_from.cpp b/engines/titanic/moves/move_player_to_from.cpp new file mode 100644 index 0000000000..c57cc2cf51 --- /dev/null +++ b/engines/titanic/moves/move_player_to_from.cpp @@ -0,0 +1,63 @@ +/* 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/moves/move_player_to_from.h" +#include "titanic/core/view_item.h" +#include "titanic/core/link_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMovePlayerToFrom, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CMovePlayerToFrom::CMovePlayerToFrom() : CMovePlayerTo() { +} + +void CMovePlayerToFrom::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_string2, indent); + + CGameObject::save(file, indent); +} + +void CMovePlayerToFrom::load(SimpleFile *file) { + file->readNumber(); + _string2 = file->readString(); + + CGameObject::load(file); +} + +bool CMovePlayerToFrom::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_string2.empty()) { + changeView(_destination); + } else { + CViewItem *view = parseView(_string2); + CViewItem *destView = parseView(_destination); + CLinkItem *link = view->findLink(destView); + changeView(_destination, link->getName()); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/move_player_to_from.h b/engines/titanic/moves/move_player_to_from.h new file mode 100644 index 0000000000..fde4e94ab5 --- /dev/null +++ b/engines/titanic/moves/move_player_to_from.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_MOVE_PLAYER_TO_FROM_H +#define TITANIC_MOVE_PLAYER_TO_FROM_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CMovePlayerToFrom : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + CString _string2; +public: + CLASSDEF; + CMovePlayerToFrom(); + + /** + * 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_MOVE_PLAYER_TO_FROM_H */ diff --git a/engines/titanic/moves/multi_move.cpp b/engines/titanic/moves/multi_move.cpp new file mode 100644 index 0000000000..4ca4fdb8f3 --- /dev/null +++ b/engines/titanic/moves/multi_move.cpp @@ -0,0 +1,60 @@ +/* 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/moves/multi_move.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMultiMove, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CMultiMove::CMultiMove() : CMovePlayerTo() { +} + +void CMultiMove::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + for (int idx = 0; idx < 5; ++idx) + file->writeQuotedLine(_viewNames[idx], indent); + + CMovePlayerTo::save(file, indent); +} + +void CMultiMove::load(SimpleFile *file) { + file->readNumber(); + for (int idx = 0; idx < 5; ++idx) + _viewNames[idx] = file->readString(); + + CMovePlayerTo::load(file); +} + +bool CMultiMove::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + lockMouse(); + + for (int idx = 0; idx < 5 && _viewNames[idx] != "NULL"; ++idx) + changeView(_viewNames[idx]); + + unlockMouse(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/multi_move.h b/engines/titanic/moves/multi_move.h new file mode 100644 index 0000000000..12dd246823 --- /dev/null +++ b/engines/titanic/moves/multi_move.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_MULTI_MOVE_H +#define TITANIC_MULTI_MOVE_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CMultiMove : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +private: + CString _viewNames[5]; +public: + CLASSDEF; + CMultiMove(); + + /** + * 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_MULTI_MOVE_H */ diff --git a/engines/titanic/moves/pan_from_pel.cpp b/engines/titanic/moves/pan_from_pel.cpp new file mode 100644 index 0000000000..ca48e888c1 --- /dev/null +++ b/engines/titanic/moves/pan_from_pel.cpp @@ -0,0 +1,56 @@ +/* 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/moves/pan_from_pel.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CPanFromPel, CMovePlayerTo) + ON_MESSAGE(MouseButtonDownMsg) +END_MESSAGE_MAP() + +CPanFromPel::CPanFromPel() : CMovePlayerTo(), _closeLeft(false) { +} + +void CPanFromPel::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_closeLeft, indent); + file->writeQuotedLine(_target, indent); + + CMovePlayerTo::save(file, indent); +} + +void CPanFromPel::load(SimpleFile *file) { + file->readNumber(); + _closeLeft = file->readNumber(); + _target = file->readString(); + + CMovePlayerTo::load(file); +} + +bool CPanFromPel::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + CActMsg actMsg(_closeLeft ? "CloseLeft" : "CloseRight"); + actMsg.execute(_target); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/pan_from_pel.h b/engines/titanic/moves/pan_from_pel.h new file mode 100644 index 0000000000..0a01aefea3 --- /dev/null +++ b/engines/titanic/moves/pan_from_pel.h @@ -0,0 +1,53 @@ +/* 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_PAN_FROM_PEL_H +#define TITANIC_PAN_FROM_PEL_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CPanFromPel : public CMovePlayerTo { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); +protected: + bool _closeLeft; + CString _target; +public: + CLASSDEF; + CPanFromPel(); + + /** + * 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_PAN_FROM_PEL_H */ diff --git a/engines/titanic/moves/restaurant_pan_handler.cpp b/engines/titanic/moves/restaurant_pan_handler.cpp new file mode 100644 index 0000000000..92f55b46cc --- /dev/null +++ b/engines/titanic/moves/restaurant_pan_handler.cpp @@ -0,0 +1,47 @@ +/* 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/moves/restaurant_pan_handler.h" + +namespace Titanic { + +int CRestaurantPanHandler::_v1; + +void CRestaurantPanHandler::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeQuotedLine(_string1, indent); + file->writeQuotedLine(_string2, indent); + + CMovePlayerTo::save(file, indent); +} + +void CRestaurantPanHandler::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _string1 = file->readString(); + _string2 = file->readString(); + + CMovePlayerTo::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/restaurant_pan_handler.h b/engines/titanic/moves/restaurant_pan_handler.h new file mode 100644 index 0000000000..4925aa685b --- /dev/null +++ b/engines/titanic/moves/restaurant_pan_handler.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_RESTAURANT_PAN_HANDLER_H +#define TITANIC_RESTAURANT_PAN_HANDLER_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CRestaurantPanHandler : public CMovePlayerTo { +protected: + static int _v1; + + CString _string1; + CString _string2; +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_RESTAURANT_PAN_HANDLER_H */ diff --git a/engines/titanic/moves/restricted_move.cpp b/engines/titanic/moves/restricted_move.cpp new file mode 100644 index 0000000000..5f18dab8ff --- /dev/null +++ b/engines/titanic/moves/restricted_move.cpp @@ -0,0 +1,44 @@ +/* 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/moves/restricted_move.h" + +namespace Titanic { + +CRestrictedMove::CRestrictedMove() : CMovePlayerTo(), _fieldC8(0) { +} + +void CRestrictedMove::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldC8, indent); + + CMovePlayerTo::save(file, indent); +} + +void CRestrictedMove::load(SimpleFile *file) { + file->readNumber(); + _fieldC8 = file->readNumber(); + + CMovePlayerTo::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/restricted_move.h b/engines/titanic/moves/restricted_move.h new file mode 100644 index 0000000000..bdf093c353 --- /dev/null +++ b/engines/titanic/moves/restricted_move.h @@ -0,0 +1,50 @@ +/* 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_RESTRICTED_MOVE_H +#define TITANIC_RESTRICTED_MOVE_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CRestrictedMove : public CMovePlayerTo { +protected: + int _fieldC8; +public: + CLASSDEF; + CRestrictedMove(); + + /** + * 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_RESTRICTED_MOVE_H */ diff --git a/engines/titanic/moves/scraliontis_table.cpp b/engines/titanic/moves/scraliontis_table.cpp new file mode 100644 index 0000000000..77d2f9df60 --- /dev/null +++ b/engines/titanic/moves/scraliontis_table.cpp @@ -0,0 +1,51 @@ +/* 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/moves/scraliontis_table.h" + +namespace Titanic { + +CScraliontisTable::CScraliontisTable() : CRestaurantPanHandler(), + _fieldE0(0), _fieldE4(0), _fieldE8(0), _fieldEC(0) { +} + +void CScraliontisTable::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldE0, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_fieldE8, indent); + file->writeNumberLine(_fieldEC, indent); + + CRestaurantPanHandler::save(file, indent); +} + +void CScraliontisTable::load(SimpleFile *file) { + file->readNumber(); + _fieldE0 = file->readNumber(); + _fieldE4 = file->readNumber(); + _fieldE8 = file->readNumber(); + _fieldEC = file->readNumber(); + + CRestaurantPanHandler::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/scraliontis_table.h b/engines/titanic/moves/scraliontis_table.h new file mode 100644 index 0000000000..2ce3745654 --- /dev/null +++ b/engines/titanic/moves/scraliontis_table.h @@ -0,0 +1,53 @@ +/* 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_SCRALIONTIS_TABLE_H +#define TITANIC_SCRALIONTIS_TABLE_H + +#include "titanic/moves/restaurant_pan_handler.h" + +namespace Titanic { + +class CScraliontisTable : public CRestaurantPanHandler { +private: + int _fieldE0; + int _fieldE4; + int _fieldE8; + int _fieldEC; +public: + CLASSDEF; + CScraliontisTable(); + + /** + * 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_SCRALIONTIS_TABLE_H */ diff --git a/engines/titanic/moves/trip_down_canal.cpp b/engines/titanic/moves/trip_down_canal.cpp new file mode 100644 index 0000000000..c8051dda03 --- /dev/null +++ b/engines/titanic/moves/trip_down_canal.cpp @@ -0,0 +1,40 @@ +/* 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/moves/trip_down_canal.h" + +namespace Titanic { + +CTripDownCanal::CTripDownCanal() : CMovePlayerTo() { +} + +void CTripDownCanal::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CMovePlayerTo::save(file, indent); +} + +void CTripDownCanal::load(SimpleFile *file) { + file->readNumber(); + CMovePlayerTo::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/moves/trip_down_canal.h b/engines/titanic/moves/trip_down_canal.h new file mode 100644 index 0000000000..736caf4131 --- /dev/null +++ b/engines/titanic/moves/trip_down_canal.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_TRIP_DOWN_CANAL_H +#define TITANIC_TRIP_DOWN_CANAL_H + +#include "titanic/moves/move_player_to.h" + +namespace Titanic { + +class CTripDownCanal : public CMovePlayerTo { +public: + CLASSDEF; + CTripDownCanal(); + + /** + * 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_TRIP_DOWN_CANAL_H */ diff --git a/engines/titanic/npcs/barbot.cpp b/engines/titanic/npcs/barbot.cpp new file mode 100644 index 0000000000..2524a835f8 --- /dev/null +++ b/engines/titanic/npcs/barbot.cpp @@ -0,0 +1,733 @@ +/* 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/npcs/barbot.h" +#include "titanic/titanic.h" + +namespace Titanic { + +int CBarbot::_v0; + +BEGIN_MESSAGE_MAP(CBarbot, CTrueTalkNPC) + ON_MESSAGE(ActMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(TrueTalkSelfQueueAnimSetMsg) + ON_MESSAGE(TrueTalkQueueUpAnimSetMsg) + ON_MESSAGE(TrueTalkGetStateValueMsg) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(LoadSuccessMsg) + ON_MESSAGE(MovieFrameMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CBarbot::FrameRanges::FrameRanges() : Common::Array<FrameRange>() { + resize(60); + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource("FRAMES/BARBOT"); + for (int idx = 0; idx < 60; ++idx) { + (*this)[idx]._startFrame = stream->readUint32LE(); + (*this)[idx]._endFrame = stream->readUint32LE(); + } + + delete stream; +} + +/*------------------------------------------------------------------------*/ + +CBarbot::CBarbot() : CTrueTalkNPC() { + _field108 = 0; + _field10C = 0; + _field110 = 0; + _field114 = 0; + _field118 = 0; + _field11C = 0; + _field120 = 0; + _field124 = 0; + _field128 = 0; + _field12C = 0; + _field130 = 0; + _field134 = 0; + _field138 = 0; + _field13C = -1; + _volume = 30; + _frameNum = -1; + _field148 = -1; + _field14C = 0; + _field150 = 0; + _field154 = 0; + _field158 = -1; + _field15C = 0; + _field160 = 0; +} + +void CBarbot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field108, indent); + file->writeNumberLine(_field10C, indent); + file->writeNumberLine(_field110, indent); + file->writeNumberLine(_field114, indent); + file->writeNumberLine(_field118, indent); + file->writeNumberLine(_field11C, indent); + file->writeNumberLine(_field120, indent); + file->writeNumberLine(_field124, indent); + file->writeNumberLine(_field128, indent); + + file->writeNumberLine(_v0, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_field130, indent); + file->writeNumberLine(_field134, indent); + file->writeNumberLine(_field138, indent); + file->writeNumberLine(_field13C, indent); + file->writeNumberLine(_volume, indent); + file->writeNumberLine(_frameNum, indent); + file->writeNumberLine(_field148, indent); + file->writeNumberLine(_field14C, indent); + file->writeNumberLine(_field150, indent); + file->writeNumberLine(_field154, indent); + file->writeNumberLine(_field158, indent); + file->writeNumberLine(_field15C, indent); + file->writeNumberLine(_field160, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CBarbot::load(SimpleFile *file) { + file->readNumber(); + _field108 = file->readNumber(); + _field10C = file->readNumber(); + _field110 = file->readNumber(); + _field114 = file->readNumber(); + _field118 = file->readNumber(); + _field11C = file->readNumber(); + _field120 = file->readNumber(); + _field124 = file->readNumber(); + _field128 = file->readNumber(); + + _v0 = file->readNumber(); + _field12C = file->readNumber(); + _field130 = file->readNumber(); + _field134 = file->readNumber(); + _field138 = file->readNumber(); + _field13C = file->readNumber(); + _volume = file->readNumber(); + _frameNum = file->readNumber(); + _field148 = file->readNumber(); + _field14C = file->readNumber(); + _field150 = file->readNumber(); + _field154 = file->readNumber(); + _field158 = file->readNumber(); + _field15C = file->readNumber(); + _field160 = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CBarbot::ActMsg(CActMsg *msg) { + if (msg->_action == "Vodka") { + if (!_field12C) { + playRange(_frames[47], MOVIE_NOTIFY_OBJECT); + playRange(_frames[46]); + playRange(_frames[40]); + playRange(_frames[7]); + playRange(_frames[13]); + playRange(_frames[8]); + playRange(_frames[40]); + playRange(_frames[7]); + playRange(_frames[13]); + playRange(_frames[8]); + playRange(_frames[7]); + playRange(_frames[40]); + playRange(_frames[13]); + playRange(_frames[40]); + playRange(_frames[7]); + playRange(_frames[8]); + playRange(_frames[13]); + playRange(_frames[40], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _frameNum = _frames[40]._endFrame; + } + } else if (msg->_action == "GiveBackVisCentre") { + if (_field134) { + playRange(_frames[27]); + _frameNum = _frames[27]._endFrame; + } + } else if (msg->_action == "Bird") { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 2; + statusMsg.execute("PickUpGlass"); + _field158 = 3; + + playRange(_frames[32], MOVIE_NOTIFY_OBJECT); + playRange(_frames[30], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[30]._endFrame; + + if (!_field114 || !_field118 || !_field12C) { + playRange(_frames[42], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[42]._endFrame; + } + + CActMsg actMsg("InTitilator"); + actMsg.execute("BeerGlass"); + } else if (msg->_action == "None") { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 2; + statusMsg.execute("PickUpGlass"); + _field158 = 0; + + playRange(_frames[55], MOVIE_NOTIFY_OBJECT); + playRange(_frames[54], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[54]._endFrame; + } else if (msg->_action == "Mustard" || msg->_action == "Tomato") { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 2; + statusMsg.execute("PickUpGlass"); + _field158 = 1; + + playRange(_frames[55], MOVIE_NOTIFY_OBJECT); + playRange(_frames[54], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[54]._endFrame; + + CActMsg actMsg("InTitilator"); + actMsg.execute("BeerGlass"); + } else if (msg->_action == "Fruit") { + if (!_field114) { + CActMsg visibleMsg; + visibleMsg.execute("LemonOnBar"); + startTalking(this, 250576); + _field114 = 1; + + playRange(_frames[36], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[36]._endFrame; + + if (!_field11C || !_field118 || _field12C) { + playRange(_frames[43], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[43]._endFrame; + } + + CRemoveFromGameMsg removeMsg; + removeMsg.execute("Lemon"); + } + } else if (msg->_action == "CrushedTV") { + if (!_field118) { + CVisibleMsg visibleMsg; + visibleMsg.execute("TVOnBar"); + startTalking(this, 250584); + _field160 = 1; + + playSound("c#5.wav", _volume); + playRange(_frames[35], MOVIE_NOTIFY_OBJECT); + playRange(_frames[34]); + playRange(_frames[33], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[33]._endFrame; + + if (!_field11C || !_field114 || !_field12C) { + playRange(_frames[41], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[41]._endFrame; + } + + CRemoveFromGameMsg removeMsg; + removeMsg.execute("CrushedTV"); + } + } else if (msg->_action == "PlayerTakesGlass") { + playRange(_frames[53]); + _field124 = 0; + + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PickUpGlass"); + } else if (msg->_action == "PlayerTakesVisCentre") { + _field128 = 0; + loadFrame(0); + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PickUpVisCentre"); + } else if (msg->_action == "BellRing1") { + startTalking(this, 251105); + } else if (msg->_action == "BellRing2") { + startTalking(this, 251107); + } else if (msg->_action == "BellRing3") { + startTalking(this, 250285); + } else if (msg->_action == "GoRingBell") { + startTalking(this, 250285); + } else if (msg->_action == "ClickOnVision") { + startTalking(this, 251858); + } + + return true; +} + +bool CBarbot::EnterViewMsg(CEnterViewMsg *msg) { + // I think this is a remnant of early debugging code + if (getName() != "Barbot") + playMovie(MOVIE_REPEAT); + + return true; +} + +bool CBarbot::EnterRoomMsg(CEnterRoomMsg *msg) { + // I think this is a remnant of early debugging code + if (getName() != "Barbot") + addTimer(g_vm->getRandomNumber(20000)); + + return true; +} + +bool CBarbot::TurnOn(CTurnOn *msg) { + if (!_fieldC4) { + _field13C = -1; + setVisible(true); + + CGameObject *glass = findInRoom("BeerGlass"); + if (!_field130) { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("BarShelfVisCentre"); + } + + if (glass && !_field11C) { + playRange(_frames[38], MOVIE_NOTIFY_OBJECT); + playRange(_frames[58], MOVIE_NOTIFY_OBJECT); + playRange(_frames[57], MOVIE_NOTIFY_OBJECT); + playRange(_frames[56], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _frameNum = _frames[56]._endFrame; + } else { + playRange(_frames[38]); + playRange(_frames[23], MOVIE_NOTIFY_OBJECT); + playRange(_frames[21], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[21]._endFrame; + + switch (g_vm->getRandomNumber(2)) { + case 0: + playRange(_frames[10], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[10]._endFrame; + break; + case 1: + playRange(_frames[12], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[12]._endFrame; + break; + default: + break; + } + _field124 = 0; + } + + _fieldC4 = 1; + ++_v0; + petSetArea(PET_CONVERSATION); + endTalking(this, true); + } + + return true; +} + +bool CBarbot::TurnOff(CTurnOff *msg) { + if (_fieldC4) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PickUpGlass"); + statusMsg.execute("PickUpVisCentre"); + + if (_field124) { + playRange(_frames[17], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[17]._endFrame; + _field124 = 0; + } + + if (_field128) { + playRange(_frames[28], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _frameNum = _frames[28]._endFrame; + _field128 = 0; + _field134 = 1; + } + + playRange(_frames[29], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + movieEvent(_frames[29]._startFrame); + _frameNum = _frames[29]._endFrame; + _fieldC4 = 0; + } + + return true; +} + +bool CBarbot::LeaveViewMsg(CLeaveViewMsg *msg) { + CTurnOff offMsg; + offMsg.execute(this); + return true; +} + +bool CBarbot::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == _frameNum) { + _frameNum = -1; + _field14C = getTicksCount(); + } + + if (msg->_endFrame == _field148) { + _field148 = -1; + _field150 = getTicksCount(); + } + + if (msg->_endFrame == _field13C) { + if (_field124) + playMovie(_frames[53]._startFrame, _frames[53]._startFrame, 0); + else if (_field128) + playMovie(_frames[27]._endFrame, _frames[27]._endFrame, 0); + + _field13C = -1; + return true; + } + + if (msg->_endFrame == _frames[58]._endFrame || msg->_endFrame == _frames[21]._endFrame) { + CVisibleMsg visibleMsg(true); + visibleMsg.execute("BarShelfVisCentre"); + } + + if (msg->_endFrame == _frames[57]._endFrame) { + startTalking(this, 250575); + playSound("c#10.wav", _volume); + return true; + } + + if (msg->_endFrame == _frames[55]._endFrame) { + playSound("c#10.wav", _volume); + return true; + } + + if (msg->_endFrame == _frames[56]._endFrame + || msg->_endFrame == _frames[54]._endFrame) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("PickUpGlass"); + CMoveToStartPosMsg moveMsg; + moveMsg.execute("BeerGlass"); + return true; + } + + if (msg->_endFrame == _frames[30]._endFrame) { + _field124 = 0; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PickUpGlass"); + } + + if (msg->_endFrame == _frames[45]._endFrame) { + if (!_field130) { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("BarShelfVisCentre"); + } + + return true; + } + + if (msg->_endFrame == _frames[44]._endFrame) { + _field128 = _field130 = 1; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("PickUpVisCentre"); + CPuzzleSolvedMsg solvedMsg; + solvedMsg.execute("VisionCentre"); + } + + if (msg->_endFrame == _frames[46]._endFrame) { + if (!_field130 && !_field12C && _field11C && _field114 && _field118) + startTalking(this, 250571); + return true; + } + + if (msg->_endFrame == _frames[43]._endFrame + || msg->_endFrame == _frames[42]._endFrame + || msg->_endFrame == _frames[41]._endFrame) { + if (_field124) + playMovie(_frames[53]._startFrame, _frames[53]._startFrame, 0); + return true; + } + + if (msg->_endFrame == _frames[38]._endFrame || msg->_endFrame == _frames[23]._endFrame) { + playSound("c#3.wav", _volume); + } else if (msg->_endFrame == _frames[36]._endFrame) { + playSound("c#6.wav", _volume); + } + else if (msg->_endFrame == _frames[35]._endFrame) { + playSound("c#8.wav", _volume); + } + else if (msg->_endFrame == _frames[33]._endFrame) { + playSound("c#4.wav", _volume); + } else if (msg->_endFrame == _frames[32]._endFrame) { + startTalking(this, 145); + playSound("c#9.wav", _volume); + } else if (msg->_endFrame == _frames[47]._endFrame) { + playSound("c#9.wav", _volume); + _field12C = _field15C = 1; + } else if (msg->_endFrame == _frames[30]._endFrame) { + playSound("c#4.wav", 60); + } else if (msg->_endFrame == _frames[29]._endFrame) { + if (!_fieldC4) { + performAction(true, nullptr); + setVisible(false); + CActMsg actMsg("ResetCount"); + actMsg.execute("BarBell"); + } + } else if (msg->_endFrame == _frames[27]._endFrame) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("PickUpVisCentre"); + _field128 = 1; + _field134 = 0; + startTalking(this, 250586); + } + + return true; +} + +bool CBarbot::TrueTalkSelfQueueAnimSetMsg(CTrueTalkSelfQueueAnimSetMsg *msg) { + return true; +} + +bool CBarbot::TrueTalkQueueUpAnimSetMsg(CTrueTalkQueueUpAnimSetMsg *msg) { + return true; +} + +bool CBarbot::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) { + switch (msg->_stateNum) { + case 2: + if (!_field130) { + if (_field15C) { + msg->_stateVal = _field134 | 1; + return true; + } + } + + msg->_stateVal = _field134; + break; + + case 3: + msg->_stateVal = 0; + if (_field114) + msg->_stateVal = 1; + if (_field11C) + msg->_stateVal |= 4; + if (_field118) + msg->_stateVal |= 8; + if (_field12C) + msg->_stateVal |= 2; + break; + + case 9: + msg->_stateVal = _field15C ? 1 : 0; + break; + + default: + break; + } + + return true; +} + +bool CBarbot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + switch (msg->_action) { + case 6: + if (_field134) { + playRange(_frames[27], MOVIE_NOTIFY_OBJECT); + _frameNum = _frames[27]._endFrame; + } else if (!_field130 && _field15C) { + playRange(_frames[45], MOVIE_NOTIFY_OBJECT); + playRange(_frames[44], MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + _frameNum = _frames[44]._endFrame; + } + break; + + case 7: { + CActMsg actMsg("Vodka"); + actMsg.execute(this); + break; + } + + case 30: + _field11C = 1; + break; + + default: + break; + } + + return true; +} + +bool CBarbot::FrameMsg(CFrameMsg *msg) { + if (!_fieldC4 || _frameNum != -1 || _field148 != -1 + || (msg->_ticks - _field14C) <= 5000 + || (msg->_ticks - _field150) <= 1000) + return true; + + if (!_field15C) { + if (++_field154 > 2) { + playRange(_frames[0]); + playRange(_frames[1], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[1]._endFrame; + _field154 = 0; + + return true; + } + + switch (g_vm->getRandomNumber(5)) { + case 0: + playRange(_frames[4], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[4]._endFrame; + break; + + case 1: + playRange(_frames[10], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[10]._endFrame; + break; + + case 2: + playRange(_frames[7], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[7]._endFrame; + break; + + case 3: + playRange(_frames[0]); + playRange(_frames[1], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[1]._endFrame; + break; + + case 4: + playRange(_frames[3], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[3]._endFrame; + break; + + case 5: + if (!_field160 && !_field128) { + playRange(_frames[15], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[15]._endFrame; + } + break; + + default: + break; + } + } else { + static const int CASES[23] = { + 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7 + }; + switch (CASES[g_vm->getRandomNumber(22)]) { + case 0: + playRange(_frames[13], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[13]._endFrame; + break; + + case 1: + playRange(_frames[4], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[4]._endFrame; + break; + + case 2: + playRange(_frames[8], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[8]._endFrame; + break; + + case 3: + playRange(_frames[7], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[7]._endFrame; + break; + + case 4: + playRange(_frames[10], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[10]._endFrame; + break; + + case 5: + playRange(_frames[2], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[2]._endFrame; + break; + + case 6: + playRange(_frames[6], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[6]._endFrame; + break; + + default: + playRange(_frames[3], MOVIE_NOTIFY_OBJECT); + _field148 = _frames[3]._endFrame; + break; + } + } + + return true; +} + +bool CBarbot::LoadSuccessMsg(CLoadSuccessMsg *msg) { + _field14C = _field150 = getTicksCount(); + _frameNum = -1; + _field148 = -1; + + return true; +} + +bool CBarbot::MovieFrameMsg(CMovieFrameMsg *msg) { + if (msg->_frameNumber == _frames[29]._startFrame) { + playSound("c#2.wav", _volume); + + } else if (msg->_frameNumber == _frames[55]._startFrame + || msg->_frameNumber == _frames[32]._startFrame) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PickUpGlass"); + + if (_field158 == 0) { + startTalking(this, 250574); + } else if (_field158 > 0 && _field158 <= 3) { + startTalking(this, 250580); + petSetArea(PET_CONVERSATION); + } + + _field158 = -1; + + } else if (msg->_frameNumber == _frames[36]._startFrame) { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("LemonOnBar"); + + } else if (msg->_frameNumber == _frames[35]._startFrame) { + CVisibleMsg visibleMsg(false); + visibleMsg.execute("TVOnBar"); + } + + return true; +} + +bool CBarbot::TimerMsg(CTimerMsg *msg) { + if (!_fieldC4 && compareRoomNameTo("Bar")) { + CParrotSpeakMsg speakMsg("Barbot", "AskForDrink"); + speakMsg.execute("PerchedParrot"); + addTimer(10000 + getRandomNumber(20000)); + } + + return true; +} + +void CBarbot::playRange(const FrameRange &range, uint flags) { + playMovie(range._startFrame, range._endFrame, flags); +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/barbot.h b/engines/titanic/npcs/barbot.h new file mode 100644 index 0000000000..2bd4cb2f1e --- /dev/null +++ b/engines/titanic/npcs/barbot.h @@ -0,0 +1,107 @@ +/* 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_BARBOT_H +#define TITANIC_BARBOT_H + +#include "titanic/npcs/true_talk_npc.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CBarbot : public CTrueTalkNPC { + struct FrameRange { + int _startFrame; + int _endFrame; + FrameRange() : _startFrame(0), _endFrame(0) {} + }; + class FrameRanges : public Common::Array<FrameRange> { + public: + FrameRanges(); + }; + + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool TrueTalkSelfQueueAnimSetMsg(CTrueTalkSelfQueueAnimSetMsg *msg); + bool TrueTalkQueueUpAnimSetMsg(CTrueTalkQueueUpAnimSetMsg *msg); + bool TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool TimerMsg(CTimerMsg *msg); +private: + static int _v0; +private: + FrameRanges _frames; + int _field108; + int _field10C; + int _field110; + int _field114; + int _field118; + int _field11C; + int _field120; + int _field124; + int _field128; + int _field12C; + int _field130; + int _field134; + int _field138; + int _field13C; + int _volume; + int _frameNum; + int _field148; + int _field14C; + int _field150; + int _field154; + int _field158; + int _field15C; + int _field160; +private: + /** + * Plays a given range of movie frames + */ + void playRange(const FrameRange &range, uint flags = 0); +public: + CLASSDEF; + CBarbot(); + + /** + * 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_BARBOT_H */ diff --git a/engines/titanic/npcs/bellbot.cpp b/engines/titanic/npcs/bellbot.cpp new file mode 100644 index 0000000000..ac6881a45c --- /dev/null +++ b/engines/titanic/npcs/bellbot.cpp @@ -0,0 +1,277 @@ +/* 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/npcs/bellbot.h" +#include "titanic/carry/carry.h" +#include "titanic/core/room_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBellBot, CTrueTalkNPC) + ON_MESSAGE(OnSummonBotMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(Use) + ON_MESSAGE(DismissBotMsg) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(MovieFrameMsg) + ON_MESSAGE(PutBotBackInHisBoxMsg) + ON_MESSAGE(NPCPlayIdleAnimationMsg) + ON_MESSAGE(NPCPlayTalkingAnimationMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(TrueTalkGetStateValueMsg) + ON_MESSAGE(TrueTalkNotifySpeechEndedMsg) +END_MESSAGE_MAP() + +CBellBot::CBellBot() : CTrueTalkNPC(), _field108(0) { +} + +void CBellBot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field108, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CBellBot::load(SimpleFile *file) { + file->readNumber(); + _field108 = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CBellBot::OnSummonBotMsg(COnSummonBotMsg *msg) { + if (msg->_value == 1) { + _npcFlags |= NPCFLAG_40000; + } else { + static const char *const ROOM_WAVES[8][2] = { + { "EmbLobby", "z#193.wav" }, + { "PromenadeDeck", "z#191.wav" }, + { "Arboretum", "z#195.wav" }, + { "Frozen Arboretum", "z#195.wav" }, + { "Bar", "z#194.wav" }, + { "MusicRoom", "z#192.wav" }, + { "MusicRoomLobby", "z#192.wav" }, + { "1stClassRestaurant", "z#190.wav" } + }; + + int idx; + for (idx = 0; idx < 8; ++idx) { + if (compareRoomNameTo(ROOM_WAVES[idx][0])) { + playSound(ROOM_WAVES[idx][1]); + + } + } + if (idx == 8) + playSound("z#147.wav"); + + sleep(2000); + _npcFlags &= ~NPCFLAG_40000; + } + + playClip("Walk On", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + movieEvent(); + _npcFlags |= NPCFLAG_10000; + + return true; +} + +bool CBellBot::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_npcFlags & NPCFLAG_10000) { + performAction(1); + _npcFlags &= ~NPCFLAG_4; + CDismissBotMsg dismissMsg; + dismissMsg.execute(this); + } + + return true; +} + +bool CBellBot::MovieEndMsg(CMovieEndMsg *msg) { + if (!(_npcFlags & NPCFLAG_10000)) { + CTrueTalkNPC::MovieEndMsg(msg); + } else if (clipExistsByEnd("Walk On", msg->_endFrame)) { + setPosition(Point(80, 10)); + loadFrame(543); + _npcFlags |= NPCFLAG_4; + if (_npcFlags & NPCFLAG_40000) { + startTalking(this, 157); + _npcFlags &= ~NPCFLAG_40000; + } + + endTalking(this, true); + petSetArea(PET_CONVERSATION); + } else if (clipExistsByEnd("Walk Off", msg->_endFrame)) { + CPutBotBackInHisBoxMsg boxMsg; + boxMsg.execute(this); + + if (_npcFlags & NPCFLAG_20000) + startAnimTimer("SummonDoorbot", 1500); + } else { + CTrueTalkNPC::MovieEndMsg(msg); + } + + return true; +} + +bool CBellBot::Use(CUse *msg) { + error("TODO: Figure out what msg->_item points to"); + // msg->_item = "Bellbot"; + return true; +} + +bool CBellBot::DismissBotMsg(CDismissBotMsg *msg) { + if (_npcFlags & NPCFLAG_10000) { + playClip("Walk Off", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + if (_npcFlags & NPCFLAG_4) { + _npcFlags &= ~NPCFLAG_4; + performAction(true); + } else { + performAction(false); + } + + CActMsg actMsg("BellbotDismissed"); + actMsg.execute("BotIdleSummons"); + } + + return true; +} + +bool CBellBot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + switch (msg->_action) { + case 1: + case 28: { + _npcFlags &= ~NPCFLAG_2; + CDismissBotMsg dismissMsg; + dismissMsg.execute(this); + break; + } + + case 5: + _npcFlags &= ~NPCFLAG_20000; + playClip("Walk Off", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + movieEvent(); + break; + + case 17: { + CActMsg actMsg("ThrowTVDownWell"); + actMsg.execute("ThrowTVDownWellControl"); + break; + } + + case 29: { + CActMsg actMsg("BellbotGetLight"); + actMsg.execute("BellbotGetLightCutScene"); + startTalking(this, 158); + break; + } + + default: + break; + } + + return true; +} + +bool CBellBot::MovieFrameMsg(CMovieFrameMsg *msg) { + if (clipExistsByStart("Walk Off", msg->_frameNumber) + || clipExistsByStart("Walk On", msg->_frameNumber)) { + setPosition(Point(20, 10)); + } + + return true; +} + +bool CBellBot::PutBotBackInHisBoxMsg(CPutBotBackInHisBoxMsg *msg) { + petMoveToHiddenRoom(); + _npcFlags &= ~NPCFLAG_4; + return true; +} + +bool CBellBot::NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg) { + static const char *const NAMES[] = { + "Sway Side To Side", "Hit Head", "Hands On Hips", "Sway", + "Hand Wave", "Slow Sway", "Lean Backwards", + "Sway Side To Side 2", "Bob Up And Down", nullptr + }; + + msg->_names = NAMES; + return true; +} + +bool CBellBot::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) { + static const char *const NAMES[] = { + "Hand On Hip Talking", "Hand On Hip Talking", "Hand On Hip Talking", + "Sway Side To Side", "Lean Forward", "Hit Head", "Confidential Talking", + "Hands On Hips", "Hands On Hips", "Hands On Hips", "Sway", "Laugh", + "Hand Wave", "Slow Sway", "Lean Backwards", "Sway Side To Side 2", + "Bob Up And Down", "Elbow In Hand", "Elbow In Hand", "Elbow In Hand", + nullptr + }; + + if (msg->_value2 == 2) + playClip("Mother Frame", 0); + else + msg->_names = NAMES; + + return true; +} + +bool CBellBot::TimerMsg(CTimerMsg *msg) { + if (msg->_action == "SummonDoorbot") { + CTrueTalkNPC::TimerMsg(msg); + } else { + CRoomItem *room = getRoom(); + if (room) { + CSummonBotMsg botMsg; + botMsg._npcName = "Doorbot"; + botMsg._value = 2; + botMsg.execute(room); + } + + _npcFlags &= ~NPCFLAG_20000; + } + + return true; +} + +bool CBellBot::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) { + CPetControl *pet = getPetControl(); + bool flag = pet ? pet->isRoom59706() : false; + + if (msg->_stateNum == 7) + msg->_stateVal = flag ? 1 : 0; + + return true; +} + +bool CBellBot::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) { + CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(msg); + + if (msg->_dialogueId == 20991) + petDismissBot("DoorBot"); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/bellbot.h b/engines/titanic/npcs/bellbot.h new file mode 100644 index 0000000000..c246901cfe --- /dev/null +++ b/engines/titanic/npcs/bellbot.h @@ -0,0 +1,64 @@ +/* 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_BELLBOT_H +#define TITANIC_BELLBOT_H + +#include "titanic/npcs/true_talk_npc.h" + +namespace Titanic { + +class CBellBot : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool OnSummonBotMsg(COnSummonBotMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool Use(CUse *msg); + bool DismissBotMsg(CDismissBotMsg *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); + bool PutBotBackInHisBoxMsg(CPutBotBackInHisBoxMsg *msg); + bool NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg); + bool NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg); + bool TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg); +private: + int _field108; +public: + CLASSDEF; + CBellBot(); + + /** + * 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_BELLBOT_H */ diff --git a/engines/titanic/npcs/bilge_succubus.cpp b/engines/titanic/npcs/bilge_succubus.cpp new file mode 100644 index 0000000000..16064bf212 --- /dev/null +++ b/engines/titanic/npcs/bilge_succubus.cpp @@ -0,0 +1,467 @@ +/* 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/npcs/bilge_succubus.h" +#include "titanic/carry/chicken.h" +#include "titanic/core/view_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBilgeSuccUBus, CSuccUBus) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(PETReceiveMsg) + ON_MESSAGE(PETDeliverMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(SubAcceptCCarryMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(TrueTalkGetStateValueMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +CBilgeSuccUBus::CBilgeSuccUBus() : CSuccUBus(), + _bilgeStartFrame1(-1), _bilgeEndFrame1(-1), + _bilgeStartFrame2(-1), _bilgeEndFrame2(-1) { +} + +void CBilgeSuccUBus::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_bilgeStartFrame1, indent); + file->writeNumberLine(_bilgeEndFrame1, indent); + file->writeNumberLine(_bilgeStartFrame2, indent); + file->writeNumberLine(_bilgeEndFrame2, indent); + + CSuccUBus::save(file, indent); +} + +void CBilgeSuccUBus::load(SimpleFile *file) { + file->readNumber(); + _bilgeStartFrame1 = file->readNumber(); + _bilgeEndFrame1 = file->readNumber(); + _bilgeStartFrame2 = file->readNumber(); + _bilgeEndFrame2 = file->readNumber(); + + CSuccUBus::load(file); +} + +bool CBilgeSuccUBus::FrameMsg(CFrameMsg *msg) { + return true; +} + +bool CBilgeSuccUBus::PETReceiveMsg(CPETReceiveMsg *msg) { + CPetControl *pet = getPetControl(); + + if (_v2) { + if (_startFrame4 >= 0) + playMovie(_startFrame4, _endFrame4, MOVIE_GAMESTATE); + if (_startFrame5 >= 0) + playMovie(_startFrame5, _endFrame5, MOVIE_GAMESTATE); + + playSound("z#28.wav", 70); + } else if (!_enabled) { + petDisplayMessage(2, "The Succ-U-Bus is in Standby, or \"Off\" mode at present."); + return false; + } else if (!pet) { + return false; + } else { + uint roomFlags = pet->getRoomFlags(); + CGameObject *mailObject = findMailByFlags( + _v3 && compareRoomNameTo("Titania") ? 3 : _field140, + roomFlags); + + if (mailObject) { + _mailP = mailObject; + if (_startFrame4 >= 0) + playMovie(_startFrame4, _endFrame4, MOVIE_GAMESTATE); + } else { + petDisplayMessage(2, "There is currently nothing to deliver."); + } + } + + return true; +} + +bool CBilgeSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) { + CPetControl *pet = getPetControl(); + if (!_enabled || !pet) + return true; + + uint petRoomFlags = pet->getRoomFlags(); + CGameObject *mailObject = findMail(petRoomFlags); + + if (!mailObject) { + petDisplayMessage(2, "There is currently nothing in the tray to send."); + return true; + } + + _field19C = 0; + _mailP = mailObject; + + uint roomFlags = _roomFlags; + if (!pet->testRooms5(roomFlags) || + getPassengerClass() > pet->getMailDest(roomFlags)) { + roomFlags = pet->getSpecialRoomFlags("BilgeRoom"); + _field19C = 1; + } + + _isChicken = mailObject->getName() == "Chicken"; + _isFeathers = mailObject->getName() == "Feathers"; + _field158 = 0; + + if (_v2) { + if (_isFeathers) { + startTalking(this, 230022); + _field158 = 1; + + if (_startFrame3 >= 0) + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT); + + if (_bilgeStartFrame1 >= 0) { + playMovie(_startFrame12, _endFrame12, MOVIE_GAMESTATE); + playMovie(_bilgeStartFrame2, _bilgeEndFrame2, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + playMovie(_bilgeStartFrame1, _bilgeEndFrame1, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + inc54(); + } + } else { + startTalking(this, 230012); + _field158 = 2; + if (_startFrame3 >= 0) + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + if (_startFrame4 >= 0) + playMovie(_startFrame4, _endFrame4, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + if (_startFrame5 >= 0) + playMovie(_startFrame5, _endFrame5, MOVIE_GAMESTATE); + } + } else { + if (_isFeathers) { + startTalking(this, 230022); + _field158 = 3; + + if (_startFrame3 >= 0) + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + if (_startFrame4 >= 0) + playMovie(_startFrame4, _endFrame4, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + if (_startFrame5 >= 0) + playMovie(_startFrame5, _endFrame5, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } else { + removeMail(petRoomFlags, roomFlags); + startTalking(this, 230012); + if (_startFrame3 >= 0) { + _field158 = 4; + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + } + } + + return true; +} + +bool CBilgeSuccUBus::MovieEndMsg(CMovieEndMsg *msg) { + CPetControl *pet = getPetControl(); + + if (msg->_endFrame == _endFrame12) { + if (_startFrame10 >= 0) + playSound("z#27.wav"); + } else if (msg->_endFrame == _endFrame10) { + if (_startFrame11 >= 0) + playSound("z#30.wav"); + } else { + if (_endFrame9 == _endFrame10 && pet) { + if (_v2) { + startTalking(this, getRandomNumber(1) ? 230062 : 230063); + } else if (!findMail(pet->getRoomFlags())) { + switch (getRandomNumber(4)) { + case 0: + startTalking(this, 230001); + break; + case 1: + startTalking(this, 230002); + break; + case 2: + startTalking(this, 230003); + break; + default: + break; + } + } + } + + if (msg->_endFrame == _endFrame3) { + switch (_field158) { + case 1: + stopSound(_soundHandle); + _soundHandle = playSound("z#3.wav"); + break; + case 2: + stopSound(_soundHandle); + _soundHandle = playSound("z#12.wav"); + break; + case 3: + if (_isChicken) { + startTalking(this, 230018); + _isChicken = false; + } else { + startTalking(this, 230013); + } + break; + case 4: + startTalking(this, 230017); + break; + default: + break; + } + + CSUBTransition transMsg; + transMsg.execute(this); + + } else if (msg->_endFrame == _bilgeEndFrame2) { + playSound("z#25.wav", 70); + playSound("z#24.wav", 70); + + } else if (msg->_endFrame == _endFrame4) { + if (_mailP) { + _mailP->petAddToInventory(); + CVisibleMsg visibleMsg(true); + visibleMsg.execute(_mailP); + + _mailP = nullptr; + petSetArea(PET_INVENTORY); + + CSUBTransition transMsg; + transMsg.execute(this); + } + + } else if (msg->_endFrame == _bilgeEndFrame1) { + changeView("BilgeRoomWith.Node 1.N", ""); + _v2 = 0; + resetMail(); + + if (_mailP) { + _mailP->petAddToInventory(); + CVisibleMsg visibleMsg(true); + visibleMsg.execute(_mailP); + + _mailP = nullptr; + petSetArea(PET_INVENTORY); + } + + startTalking(this, 150); + CBodyInBilgeRoomMsg bodyMsg; + bodyMsg.execute("Service Elevator Entity"); + dec54(); + _field158 = 0; + + } else { + _field158 = 0; + } + } + + return true; +} + +bool CBilgeSuccUBus::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_enabled) { + switch (getRandomNumber(4)) { + case 0: + case 4: { + _enabled = false; + CTurnOff offMsg; + offMsg.execute(this); + break; + } + + case 1: + startTalking(this, 230055); + break; + + case 2: + startTalking(this, 230067); + break; + + case 3: + startTalking(this, 230045); + break; + + default: + break; + } + } else { + CTurnOn onMsg; + onMsg.execute(this); + _enabled = true; + } + + return true; +} + +bool CBilgeSuccUBus::SubAcceptCCarryMsg(CSubAcceptCCarryMsg *msg) { + CPetControl *pet = getPetControl(); + if (!msg->_item) + return false; + + CCarry *item = dynamic_cast<CCarry *>(msg->_item); + if (!_enabled || !pet || !item) { + item->petAddToInventory(); + return true; + } + + uint petRoomFlags = pet->getRoomFlags(); + if (mailExists(petRoomFlags)) { + petDisplayMessage(2, "The Succ-U-Bus is a Single Entity Delivery Device."); + item->petAddToInventory(); + return true; + } + + petContainerRemove(item); + pet->phonographAction(""); + playSound("z#23.wav"); + + CChicken *chicken = dynamic_cast<CChicken *>(item); + bool chickenFlag = chicken ? chicken->_string6 == "None" : false; + + if (chickenFlag) { + if (_startFrame2 >= 0) { + startTalking(this, 70219); + playMovie(_startFrame2, _endFrame2, 0); + } + + if (_startFrame3 >= 0) { + _field158 = 5; + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT); + } + + CViewItem *view = parseView(item->_fullViewName); + if (view) { + item->setVisible(false); + setPosition(item->_origPos); + item->moveUnder(view); + + CSUBTransition transMsg; + transMsg.execute(this); + } else { + return false; + } + } else { + item->addMail(petRoomFlags); + if (_startFrame2 >= 0) + playMovie(_startFrame2, _endFrame2, 0); + + petSetArea(PET_REMOTE); + CSUBTransition transMsg; + transMsg.execute(this); + } + + return true; +} + +bool CBilgeSuccUBus::EnterViewMsg(CEnterViewMsg *msg) { + petSetRemoteTarget(); + _mailP = nullptr; + + if (_startFrame8 >= 0) + loadFrame(_startFrame8); + + return true; +} + +bool CBilgeSuccUBus::LeaveViewMsg(CLeaveViewMsg *msg) { + petDisplayMessage(2, ""); + petClear(); + + if (_soundHandle != -1) { + stopSound(_soundHandle); + _soundHandle = -1; + } + + if (_enabled) { + _enabled = false; + if (_startFrame10 >= 0) + playSound("z#27.wav"); + } + + performAction(true); + CSUBTransition transMsg; + transMsg.execute(this); + + return true; +} + +bool CBilgeSuccUBus::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) { + if (msg->_stateNum == 1) + msg->_stateVal = _enabled; + + return true; +} + +bool CBilgeSuccUBus::TurnOn(CTurnOn *msg) { + CPetControl *pet = getPetControl(); + + if (pet) { + if (_startFrame9 >= 0) { + playMovie(_startFrame9, _endFrame9, MOVIE_NOTIFY_OBJECT); + playSound("z#26.wav"); + } + + if (mailExists(pet->getRoomFlags()) && _startFrame2 >= 0) + playMovie(_startFrame2, _endFrame2, 0); + + _enabled = true; + CSUBTransition transMsg; + transMsg.execute(this); + + endTalking(this, true); + petSetArea(PET_REMOTE); + petHighlightGlyph(16); + } + + return true; +} + +bool CBilgeSuccUBus::TurnOff(CTurnOff *msg) { + CPetControl *pet = getPetControl(); + + if (pet && mailExists(pet->getRoomFlags()) && _startFrame12 >= 0) + playMovie(_startFrame12, _endFrame12, MOVIE_NOTIFY_OBJECT); + else if (_endFrame12 >= 0) + playMovie(_endFrame12, _endFrame12, MOVIE_NOTIFY_OBJECT); + + if (_soundHandle != -1) { + stopSound(_soundHandle); + _soundHandle = -1; + } + + if (_startFrame10 >= 0) + playMovie(_startFrame10, _endFrame10, MOVIE_NOTIFY_OBJECT); + + _enabled = false; + performAction(true); + + CSUBTransition transMsg; + transMsg.execute(this); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/bilge_succubus.h b/engines/titanic/npcs/bilge_succubus.h new file mode 100644 index 0000000000..754949a306 --- /dev/null +++ b/engines/titanic/npcs/bilge_succubus.h @@ -0,0 +1,65 @@ +/* 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_BILGE_SUCCUBUS_H +#define TITANIC_BILGE_SUCCUBUS_H + +#include "titanic/npcs/succubus.h" + +namespace Titanic { + +class CBilgeSuccUBus : public CSuccUBus { + DECLARE_MESSAGE_MAP; + bool FrameMsg(CFrameMsg *msg); + bool PETReceiveMsg(CPETReceiveMsg *msg); + bool PETDeliverMsg(CPETDeliverMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool SubAcceptCCarryMsg(CSubAcceptCCarryMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); +public: + int _bilgeStartFrame1; + int _bilgeEndFrame1; + int _bilgeStartFrame2; + int _bilgeEndFrame2; +public: + CLASSDEF; + CBilgeSuccUBus(); + + /** + * 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_BILGE_SUCCUBUS_H */ diff --git a/engines/titanic/npcs/callbot.cpp b/engines/titanic/npcs/callbot.cpp new file mode 100644 index 0000000000..4af9876b35 --- /dev/null +++ b/engines/titanic/npcs/callbot.cpp @@ -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. + * + */ + +#include "titanic/npcs/callbot.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCallBot, CGameObject) + ON_MESSAGE(TurnOn) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CCallBot::CCallBot() : CGameObject(), _enabled(0) { +} + +void CCallBot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_npcName, indent); + file->writeNumberLine(_enabled, indent); + + CGameObject::save(file, indent); +} + +void CCallBot::load(SimpleFile *file) { + file->readNumber(); + _npcName = file->readString(); + _enabled = file->readNumber(); + + CGameObject::load(file); +} + +bool CCallBot::TurnOn(CTurnOn *msg) { + _enabled = true; + return true; +} + +bool CCallBot::EnterViewMsg(CEnterViewMsg *msg) { + if (_enabled) { + CRoomItem *room = getRoom(); + + if (room) { + CSummonBotQueryMsg queryMsg; + queryMsg._npcName = _npcName; + if (queryMsg.execute(room)) + petOnSummonBot(_npcName, 0); + } + + _enabled = false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/callbot.h b/engines/titanic/npcs/callbot.h new file mode 100644 index 0000000000..ca0e0c55b2 --- /dev/null +++ b/engines/titanic/npcs/callbot.h @@ -0,0 +1,54 @@ +/* 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_CALLBOT_H +#define TITANIC_CALLBOT_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CCallBot : public CGameObject { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool EnterViewMsg(CEnterViewMsg *msg); +protected: + CString _npcName; + bool _enabled; +public: + CLASSDEF; + CCallBot(); + + /** + * 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_CALLBOT_H */ diff --git a/engines/titanic/npcs/character.cpp b/engines/titanic/npcs/character.cpp new file mode 100644 index 0000000000..2713a6a1aa --- /dev/null +++ b/engines/titanic/npcs/character.cpp @@ -0,0 +1,79 @@ +/* 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/npcs/character.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CCharacter, CGameObject) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +CCharacter::CCharacter() : CGameObject(), _startFrame(0), _endFrame(0), _fieldC4(1) { +} + +void CCharacter::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_startFrame, indent); + file->writeNumberLine(_endFrame, indent); + file->writeNumberLine(_fieldC4, indent); + file->writeQuotedLine(_charName, indent); + + CGameObject::save(file, indent); +} + +void CCharacter::load(SimpleFile *file) { + file->readNumber(); + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + _fieldC4 = file->readNumber(); + _charName = file->readString(); + + CGameObject::load(file); +} + +bool CCharacter::LeaveViewMsg(CLeaveViewMsg *msg) { + CTurnOff offMsg; + offMsg.execute(this); + + return true; +} + +bool CCharacter::TurnOn(CTurnOn *msg) { + if (!_fieldC4) + _fieldC4 = 1; + + return true; +} + +bool CCharacter::TurnOff(CTurnOff *msg) { + CString charName = getName(); + if (charName == "Deskbot" || charName == "Barbot" || charName == "SuccUBus") { + _fieldC4 = 0; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/character.h b/engines/titanic/npcs/character.h new file mode 100644 index 0000000000..e27cf4ec35 --- /dev/null +++ b/engines/titanic/npcs/character.h @@ -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. + * + */ + +#ifndef TITANIC_CHARACTER_H +#define TITANIC_CHARACTER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CCharacter : public CGameObject { + DECLARE_MESSAGE_MAP; + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); +protected: + int _startFrame; + int _endFrame; + int _fieldC4; + CString _charName; +public: + CLASSDEF; + CCharacter(); + + /** + * 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_CHARACTER_H */ diff --git a/engines/titanic/npcs/deskbot.cpp b/engines/titanic/npcs/deskbot.cpp new file mode 100644 index 0000000000..d11b135983 --- /dev/null +++ b/engines/titanic/npcs/deskbot.cpp @@ -0,0 +1,310 @@ +/* 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/npcs/deskbot.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +static const char *const TALKING_NAMES[] = { + "NeutralTalking", "HandFidget1", "HandFidget2", "LookingAround", + "FriendlyTalking", "MoreRudeness", "HandUp", "TapFingers", + "WaveOn", "WaveArmsAround", "HandsOverEdge" +}; + +static const char *const IDLE_NAMES[] = { + "WaveOn", "HandFidget1", "HandFidget2", "TapFingers", "HandsOverEdge" +}; + +BEGIN_MESSAGE_MAP(CDeskbot, CTrueTalkNPC) + ON_MESSAGE(TurnOn) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(NPCPlayTalkingAnimationMsg) + ON_MESSAGE(NPCPlayIdleAnimationMsg) + ON_MESSAGE(TrueTalkNotifySpeechStartedMsg) + ON_MESSAGE(TrueTalkNotifySpeechEndedMsg) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +int CDeskbot::_v1; +int CDeskbot::_v2; + +CDeskbot::CDeskbot() : CTrueTalkNPC(), _deskbotActive(false), _classNum(0) { +} + +void CDeskbot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_deskbotActive, indent); + file->writeNumberLine(_classNum, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CDeskbot::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + _deskbotActive = file->readNumber(); + _classNum = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CDeskbot::TurnOn(CTurnOn *msg) { + if (!_deskbotActive) { + setVisible(true); + playClip("BellRinging", 4); + playSound("b#69.wav"); + petSetArea(PET_CONVERSATION); + + _npcFlags |= NPCFLAG_20000; + _deskbotActive = true; + } + + return true; +} + +bool CDeskbot::EnterViewMsg(CEnterViewMsg *msg) { + setVisible(false); + _deskbotActive = false; + _fieldC4 = 0; + loadFrame(625); + + return true; +} + +bool CDeskbot::ActMsg(CActMsg *msg) { + if (msg->_action == "2ndClassUpgrade" && getPassengerClass() > 2) { + startTalking(this, 140, findView()); + } + + return true; +} + +bool CDeskbot::MovieEndMsg(CMovieEndMsg *msg) { + bool flag = false; + if (_npcFlags & NPCFLAG_10000) { + if (_classNum) { + petSetArea(PET_ROOMS); + dec54(); + unlockMouse(); + playSound("z#47.wav", 100, 0, 0); + _classNum = false; + } + + _npcFlags &= ~NPCFLAG_10000; + flag = true; + } + + if (_npcFlags & NPCFLAG_40000) { + _deskbotActive = false; + _npcFlags &= ~(NPCFLAG_40000 | NPCFLAG_20000); + + if (_npcFlags & NPCFLAG_80000) { + CTurnOn turnOn; + turnOn.execute("EmbBellbotTrigger"); + unlockMouse(); + changeView("EmbLobby.Node 4.N", ""); + } else if (_npcFlags & NPCFLAG_100000) { + CTurnOn turnOn; + turnOn.execute("EmbDoorBotTrigger"); + unlockMouse(); + changeView("EmbLobby.Node 4.N", ""); + } + + _npcFlags &= ~(NPCFLAG_80000 | NPCFLAG_100000); + flag = true; + } + + if (_npcFlags & NPCFLAG_20000) { + _npcFlags &= ~(NPCFLAG_40000 | NPCFLAG_20000); + endTalking(this, 1, findView()); + + _npcFlags |= NPCFLAG_4; + flag = true; + } + + if (!flag) + CTrueTalkNPC::MovieEndMsg(msg); + + return true; +} + +bool CDeskbot::LeaveViewMsg(CLeaveViewMsg *msg) { + if (_deskbotActive) { + CTurnOff turnOff; + turnOff.execute(this); + } + + return true; +} + +bool CDeskbot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + switch (msg->_action) { + case 19: + inc54(); + lockMouse(); + petSetArea(PET_CONVERSATION); + playClip("ReprogramPETInHand", 4); + _npcFlags |= NPCFLAG_10000; + _classNum = msg->_param1; + + switch (_classNum) { + case 1: + petDisplayMessage("You have been upgraded to 1st Class status. Enjoy hugely."); + setPassengerClass(_classNum); + petReassignRoom(_classNum); + break; + case 2: + petDisplayMessage("You have been upgraded to 2nd Class status. Enjoy."); + setPassengerClass(_classNum); + petReassignRoom(_classNum); + break; + case 3: + setPassengerClass(3); + petReassignRoom(_classNum); + break; + default: + break; + } + + case 20: + if (getPassengerClass() == 1) { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->changeLocationClass(4); + } + break; + + case 21: + if (getPassengerClass() == 1) { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->changeLocationClass(3); + } + break; + + case 22: + if (getPassengerClass() == 1) { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->changeLocationClass(2); + } + break; + + case 23: + if (getPassengerClass() == 1) { + CPetControl *petControl = getPetControl(); + if (petControl) + petControl->changeLocationClass(1); + } + break; + + case 26: + _npcFlags |= NPCFLAG_80000; + CTurnOff turnOff; + turnOff.execute(this); + lockMouse(); + break; + } + + return true; +} + +bool CDeskbot::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) { + if (msg->_value2 != 2) + msg->_names = TALKING_NAMES; + + return true; +} + +bool CDeskbot::NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg) { + msg->_names = IDLE_NAMES; + return true; +} + +bool CDeskbot::TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg) { + if (_npcFlags & NPCFLAG_40000) + return true; + + CTrueTalkNPC::TrueTalkNotifySpeechStartedMsg(msg); + switch (msg->_dialogueId) { + case 41684: + case 41686: + case 41787: + case 41788: + case 41789: + lockMouse(); + break; + default: + break; + } + + return true; +} + +bool CDeskbot::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) { + if (_npcFlags & NPCFLAG_40000) + return true; + + CTurnOff turnOff; + CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(msg); + + switch (msg->_dialogueId) { + case 41684: + case 41787: + case 41788: + case 41789: + _npcFlags |= NPCFLAG_80000; + turnOff.execute(this); + + case 41686: + _npcFlags |= NPCFLAG_100000; + turnOff.execute(this); + break; + + default: + break; + } + + return true; +} + +bool CDeskbot::TurnOff(CTurnOff *msg) { + if (_deskbotActive) { + stopMovie(); + performAction(1, findView()); + + _npcFlags = (_npcFlags & ~(NPCFLAG_SPEAKING | NPCFLAG_2 | NPCFLAG_4)) | NPCFLAG_40000; + playClip("Closing", 0x14); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/deskbot.h b/engines/titanic/npcs/deskbot.h new file mode 100644 index 0000000000..ab48d63546 --- /dev/null +++ b/engines/titanic/npcs/deskbot.h @@ -0,0 +1,66 @@ +/* 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_DESKBOT_H +#define TITANIC_DESKBOT_H + +#include "titanic/npcs/true_talk_npc.h" + +namespace Titanic { + +class CDeskbot : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg); + bool NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg); + bool TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg); + bool TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg); + bool TurnOff(CTurnOff *msg); +private: + static int _v1; + static int _v2; +public: + bool _deskbotActive; + int _classNum; +public: + CLASSDEF; + CDeskbot(); + + /** + * 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_DESKBOT_H */ diff --git a/engines/titanic/npcs/doorbot.cpp b/engines/titanic/npcs/doorbot.cpp new file mode 100644 index 0000000000..4a5f3690c0 --- /dev/null +++ b/engines/titanic/npcs/doorbot.cpp @@ -0,0 +1,570 @@ +/* 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/npcs/doorbot.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CDoorbot, CTrueTalkNPC) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(OnSummonBotMsg) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(DoorbotNeededInHomeMsg) + ON_MESSAGE(DoorbotNeededInElevatorMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(NPCPlayTalkingAnimationMsg) + ON_MESSAGE(NPCPlayIdleAnimationMsg) + ON_MESSAGE(PutBotBackInHisBoxMsg) + ON_MESSAGE(DismissBotMsg) + ON_MESSAGE(MovieFrameMsg) + ON_MESSAGE(TrueTalkNotifySpeechEndedMsg) + ON_MESSAGE(TextInputMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +int CDoorbot::_v1; +int CDoorbot::_v2; + +CDoorbot::CDoorbot() : CTrueTalkNPC() { + _field108 = 0; + _timerId = 0; + _field110 = 0; + _field114 = 0; +} + +void CDoorbot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + + file->writeNumberLine(_field108, indent); + file->writeNumberLine(_timerId, indent); + file->writeNumberLine(_field110, indent); + file->writeNumberLine(_field114, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CDoorbot::load(SimpleFile *file) { + file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + + _field108 = file->readNumber(); + _timerId = file->readNumber(); + _field110 = file->readNumber(); + _field114 = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CDoorbot::MovieEndMsg(CMovieEndMsg *msg) { + if (_npcFlags & NPCFLAG_8000000) { + switch (_field108) { + case 3: + startTalking(this, 221482); + _field108 = 4; + break; + + case 6: + if (clipExistsByEnd("Cloak On", msg->_endFrame)) { + petShow(); + setState1C(true); + changeView("ServiceElevator.Node 1.S"); + changeView("ServiceElevator.Node 1.N"); + } + break; + + case 7: + startTalking(this, 221467); + _field108 = 8; + break; + + case 9: + startTalking(this, 221468); + break; + + case 11: + changeView("ServiceElevator.Node 1.S"); + changeView("MoonEmbLobby.Node 1.NE"); + break; + + default: + break; + } + + CTrueTalkNPC::MovieEndMsg(msg); + } else if (_npcFlags & NPCFLAG_100000) { + if (clipExistsByEnd("Cloak Off", msg->_endFrame)) { + _npcFlags = (_npcFlags & ~NPCFLAG_8) | NPCFLAG_4; + endTalking(this, false); + startTalking(this, 221474); + _npcFlags &= ~NPCFLAG_8000000; + _field108 = 0; + } else if (clipExistsByEnd("Cloak On", msg->_endFrame)) { + petShow(); + setState1C(true); + changeView("ServiceElevator.Node 1.S"); + } else { + CTrueTalkNPC::MovieEndMsg(msg); + } + } else if (_npcFlags & NPCFLAG_400000) { + if (clipExistsByEnd("Whizz On Left", msg->_endFrame) + || clipExistsByEnd("Whizz On Right", msg->_endFrame)) { + setPosition(Point((600 - _bounds.width()) / 2 + 18, 42)); + loadFrame(0); + endTalking(this, true); + _npcFlags |= NPCFLAG_4; + petSetArea(PET_CONVERSATION); + } else if (clipExistsByEnd("Whizz Off Left", msg->_endFrame) + || clipExistsByEnd("Whizz Off Right", msg->_endFrame)) { + CPutBotBackInHisBoxMsg boxMsg; + boxMsg.execute(this); + if (_npcFlags & NPCFLAG_4000000) + startAnimTimer("SummonBellbot", 1500); + } else { + CTrueTalkNPC::MovieEndMsg(msg); + } + } else { + CTrueTalkNPC::MovieEndMsg(msg); + } + + return true; +} + +bool CDoorbot::OnSummonBotMsg(COnSummonBotMsg *msg) { + const char *const ROOM_WAVES[8][2] = { + { "EmbLobby", "z#186.wav" }, + { "PromenadeDeck", "z#184.wav" }, + { "Arboretum", "z#188.wav" }, + { "Frozen Arboretum", "z#188.wav" }, + { "Bar", "z#187.wav" }, + { "MusicRoom", "z#185.wav" }, + { "MusicRoomLobby", "z#185.wav" }, + { "1stClassRestaurant", "z#183.wav" }, + }; + + if (msg->_value != -1) { + int idx; + for (idx = 0; idx < 8; ++idx) { + if (compareRoomNameTo(ROOM_WAVES[idx][0])) { + playSound(ROOM_WAVES[idx][1]); + + } + } + if (idx == 8) + playSound("z#146.wav"); + + sleep(2000); + } + + playClip(getRandomNumber(1) ? "Whizz On Left" : "Whizz On Right", + MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + movieEvent(); + _npcFlags |= NPCFLAG_400000; + + return true; +} + +bool CDoorbot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + switch (msg->_action) { + case 3: + playClip("Cloak On", MOVIE_NOTIFY_OBJECT); + break; + + case 4: + _npcFlags = (_npcFlags & ~NPCFLAG_2) | NPCFLAG_4000000; + playClip("Whizz Off Left", MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + break; + + case 28: { + _npcFlags &= ~(NPCFLAG_2 | NPCFLAG_4); + CDismissBotMsg dismissMsg; + dismissMsg.execute(this); + break; + } + } + + return true; +} + +bool CDoorbot::DoorbotNeededInHomeMsg(CDoorbotNeededInHomeMsg *msg) { + moveToView(); + setPosition(Point(90, 42)); + _npcFlags = NPCFLAG_100000; + + stopMovie(); + playClip("Cloak Off", MOVIE_NOTIFY_OBJECT); + + _npcFlags |= NPCFLAG_8; + return true; +} + +bool CDoorbot::DoorbotNeededInElevatorMsg(CDoorbotNeededInElevatorMsg *msg) { + moveToView("ServiceElevator.Node 1.N"); + setPosition(Point(100, 42)); + + if (_npcFlags & NPCFLAG_8000000) { + _field108 = 7; + _npcFlags |= NPCFLAG_200000; + loadFrame(797); + } else { + _npcFlags = 0; + if (msg->_value) + endTalking(this, true); + } + + return true; +} + +bool CDoorbot::LeaveViewMsg(CLeaveViewMsg *msg) { + if (!(_npcFlags & NPCFLAG_8000000) && (_npcFlags & NPCFLAG_400000)) { + performAction(true); + _npcFlags &= ~NPCFLAG_4; + } + + return true; +} + +bool CDoorbot::TimerMsg(CTimerMsg *msg) { + if (msg->_action == "NPCIdleAnim") { + return CTrueTalkNPC::TimerMsg(msg); + } else if (_npcFlags & NPCFLAG_8000000) { + switch (msg->_actionVal) { + case 0: + startTalking(this, 221475); + break; + + case 1: + startTalking(this, 221476); + break; + + case 2: + startTalking(this, 221477); + break; + + case 3: + playClip("DoubleTake Start", 0); + playClip("DoubleTake End", 0); + playClip("DoubleTake Start", 0); + playClip("DoubleTake End", MOVIE_NOTIFY_OBJECT); + _field108 = 3; + break; + + case 4: + startTalking(this, 221483); + lockInputHandler(); + _field114 = true; + break; + + case 5: + lockInputHandler(); + mouseLockE4(); + _field114 = true; + startTalking(this, 221485); + break; + + case 6: + CMouseButtonDownMsg::generate(); + mouseSaveState(200, 430, 2500); + _timerId = addTimer(7, 2500, 0); + break; + + case 7: + CMouseButtonDownMsg::generate(); + startTalking(this, 221486); + mouseUnlockE4(); + unlockInputHandler(); + _field114 = false; + disableMouse(); + break; + + default: + break; + } + } else if (msg->_action == "SummonBellbot") { + CRoomItem *room = getRoom(); + if (room) { + CSummonBotMsg botMsg; + botMsg._npcName = "Bellbot"; + botMsg.execute(room); + } + + _npcFlags &= ~NPCFLAG_4000000; + } + + return true; +} + +bool CDoorbot::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) { + const char *const NAMES1[] = { + "Mutter Aside", "Rub Chin", "Drunken Eye Roll", "Drunken Head Move", + "Look down and mutter", "Look side to side", "Gesture forward and around", + "Arms behind back", "Look down", "Rolling around", "Hold face", + "Touch chin", "Cross hands in front", nullptr + }; + const char *const NAMES2[] = { + "SE Talking 1", "SE Talking 2", "SE Talking 3", "SE Talking 4" + }; + const char *const NAMES3[] = { + "SE Ask For Help", nullptr + }; + + if (msg->_value2 != 2) { + if (_npcFlags & NPCFLAG_200000) { + if (_field108 == 8 || _field110) { + msg->_names = NAMES2; + } else if (_field108 == 9) { + msg->_names = NAMES3; + _field108 = 10; + } + } else if (_npcFlags & (NPCFLAG_100000 | NPCFLAG_400000)) { + msg->_names = NAMES1; + } + } + + return true; +} + +bool CDoorbot::NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg) { + const char *const NAMES[] = { + "Hand swivel", "Prompt Push", "Eye Roll", "Say something", nullptr + }; + + if (!(_npcFlags & (NPCFLAG_100000 | NPCFLAG_200000)) + && (_npcFlags & NPCFLAG_400000)) + msg->_names = NAMES; + + return true; +} + +bool CDoorbot::PutBotBackInHisBoxMsg(CPutBotBackInHisBoxMsg *msg) { + petMoveToHiddenRoom(); + _npcFlags &= ~(NPCFLAG_4 | NPCFLAG_100000 | NPCFLAG_200000 | NPCFLAG_8000000); + if (msg->_value) + performAction(true); + + return true; +} + +bool CDoorbot::DismissBotMsg(CDismissBotMsg *msg) { + if (_npcFlags & NPCFLAG_400000) { + playClip(getRandomNumber(1) ? "Whizz Off Left" : "Whizz Off Right", + MOVIE_STOP_PREVIOUS | MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + movieEvent(); + + if (_npcFlags & NPCFLAG_4) { + _npcFlags &= ~NPCFLAG_4; + performAction(true); + } else { + performAction(false); + } + + CActMsg actMsg("DoorbotDismissed"); + actMsg.execute("BotIdleSummons"); + } + + return true; +} + +bool CDoorbot::MovieFrameMsg(CMovieFrameMsg *msg) { + if (clipExistsByStart("Whizz Off Left", msg->_frameNumber) + || clipExistsByStart("Whizz On Left", msg->_frameNumber)) { + setPosition(Point(20, 42)); + } else if (clipExistsByStart("Whizz Off Right", msg->_frameNumber) + || clipExistsByStart("Whizz On Right", msg->_frameNumber)) { + setPosition(Point(620 - _bounds.width(), 42)); + } + + return true; +} + +bool CDoorbot::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) { + if (_npcFlags & NPCFLAG_8000000) { + switch (msg->_dialogueId) { + case 10552: + playClip("SE Try Buttons", MOVIE_NOTIFY_OBJECT); + _field108 = 9; + break; + + case 10553: + enableMouse(); + break; + + case 10557: + playClip("SE Move To Right", MOVIE_NOTIFY_OBJECT); + _field108 = 11; + break; + + case 10559: + stopAnimTimer(_timerId); + _timerId = addTimer(0, 2500, 0); + break; + + case 10560: + petShow(); + petSetArea(PET_CONVERSATION); + stopAnimTimer(_timerId); + _timerId = addTimer(1, 1000, 0); + break; + + case 10561: + enableMouse(); + _field108 = 1; + stopAnimTimer(_timerId); + _timerId = addTimer(2, 10000, 0); + break; + + case 10562: + if (_field108 == 1) { + stopAnimTimer(_timerId); + _timerId = addTimer(2, getRandomNumber(5000), 0); + } + break; + + case 10563: + case 10564: + disableMouse(); + startTalking(this, 221480); + break; + + case 10565: + startTalking(this, 221481); + break; + + case 10566: + stopAnimTimer(_timerId); + _timerId = 0; + if (_field110 == 2) { + playClip("Cloak On", MOVIE_NOTIFY_OBJECT); + _field108 = 6; + } else { + _timerId = addTimer(3, 2000, 0); + } + break; + + case 10567: { + CActMsg actMsg("BecomeGettable"); + actMsg.execute("Photograph"); + enableMouse(); + stopAnimTimer(_timerId); + _timerId = addTimer(4, 5000, 0); + break; + } + + case 10568: + mouseLockE4(); + mouseSaveState(600, 250, 2500); + _timerId = addTimer(6, 2500, 0); + break; + + case 10569: + if (_field110 != 2) { + stopAnimTimer(_timerId); + _timerId = addTimer(5, 3000, 0); + } + break; + + case 10570: + mouseSaveState(200, 430, 2500); + _timerId = addTimer(7, 3000, 0); + break; + + case 10571: + playClip("Cloak On", MOVIE_NOTIFY_OBJECT); + _field108 = 6; + break; + + default: + break; + } + } + + return true; +} + +bool CDoorbot::TextInputMsg(CTextInputMsg *msg) { + if (!(_npcFlags & NPCFLAG_8000000)) + return CTrueTalkNPC::TextInputMsg(msg); + + if (_field108 == 1) { + stopAnimTimer(_timerId); + _field108 = 2; + _timerId = 0; + + if (msg->_input == "yes" || msg->_input == "yeah" + || msg->_input == "yea" || msg->_input == "yup" + || msg->_input == "yep" || msg->_input == "sure" + || msg->_input == "alright" || msg->_input == "all right" + || msg->_input == "ok") { + startTalking(this, 221479); + } else { + startTalking(this, 221478); + } + } + + return true; +} + +bool CDoorbot::EnterViewMsg(CEnterViewMsg *msg) { + if ((_npcFlags & NPCFLAG_8000000) && _field108 == 7) + playClip("SE Move And Turn", MOVIE_NOTIFY_OBJECT); + + return true; +} + +bool CDoorbot::ActMsg(CActMsg *msg) { + if (msg->_action == "DoorbotPlayerPressedTopButton") { + disableMouse(); + startTalking(this, 221471); + } else if (msg->_action == "DoorbotPlayerPressedMiddleButton") { + startTalking(this, 221470); + } + else if (msg->_action == "DoorbotPlayerPressedBottomButton") { + startTalking(this, 221469); + } else if (msg->_action == "DoorbotReachedEmbLobby") { + startTalking(this, 221472); + } else if (msg->_action == "PlayerPicksUpPhoto") { + _field110 = 1; + if (!_field114 && _field108 == 4) { + stopAnimTimer(_timerId); + _timerId = 0; + _field108 = 5; + startTalking(this, 221484); + } + } else if (msg->_action == "PlayerPutsPhotoInPet") { + _field110 = 2; + if (!_field114 && _field108 == 5) { + stopAnimTimer(_timerId); + _timerId = 0; + startTalking(this, 221486); + disableMouse(); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/doorbot.h b/engines/titanic/npcs/doorbot.h new file mode 100644 index 0000000000..9095ebc7e7 --- /dev/null +++ b/engines/titanic/npcs/doorbot.h @@ -0,0 +1,73 @@ +/* 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_DOORBOT_H +#define TITANIC_DOORBOT_H + +#include "titanic/npcs/true_talk_npc.h" + +namespace Titanic { + +class CDoorbot : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool MovieEndMsg(CMovieEndMsg *msg); + bool OnSummonBotMsg(COnSummonBotMsg *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool DoorbotNeededInHomeMsg(CDoorbotNeededInHomeMsg *msg); + bool DoorbotNeededInElevatorMsg(CDoorbotNeededInElevatorMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg); + bool NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg); + bool PutBotBackInHisBoxMsg(CPutBotBackInHisBoxMsg *msg); + bool DismissBotMsg(CDismissBotMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); + bool TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg); + bool TextInputMsg(CTextInputMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool ActMsg(CActMsg *msg); +private: + static int _v1; + static int _v2; +private: + int _field108; + int _timerId; + int _field110; + int _field114; +public: + CLASSDEF; + CDoorbot(); + + /** + * 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_DOORBOT_H */ diff --git a/engines/titanic/npcs/liftbot.cpp b/engines/titanic/npcs/liftbot.cpp new file mode 100644 index 0000000000..272617ee62 --- /dev/null +++ b/engines/titanic/npcs/liftbot.cpp @@ -0,0 +1,187 @@ +/* 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/npcs/liftbot.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CLiftBot, CTrueTalkNPC) + ON_MESSAGE(TextInputMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(TurnOff) + ON_MESSAGE(TurnOn) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(TrueTalkGetStateValueMsg) + ON_MESSAGE(NPCPlayTalkingAnimationMsg) + ON_MESSAGE(ActMsg) +END_MESSAGE_MAP() + +bool CLiftBot::_flag; +bool CLiftBot::_enabled; + +CLiftBot::CLiftBot() : CTrueTalkNPC(), _field108(1) { +} + +void CLiftBot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + file->writeNumberLine(_field108, indent); + file->writeNumberLine(_enabled, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CLiftBot::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + _field108 = file->readNumber(); + _enabled = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CLiftBot::TextInputMsg(CTextInputMsg *msg) { + CPetControl *pet = getPetControl(); + if (_enabled || pet->getRoomsElevatorNum() != 4) { + if (getName() != "LiftBot") { + CViewItem *view = findView(); + processInput(msg, view); + } + } + + return true; +} + +bool CLiftBot::EnterViewMsg(CEnterViewMsg *msg) { + CPetControl *pet = getPetControl(); + if (!_enabled && pet->getRoomsElevatorNum() == 4) { + loadFrame(700); + } else if (!_flag) { + if (getName() != "LiftBot") { + CViewItem *view = findView(); + endTalking(this, true, view); + petSetArea(PET_CONVERSATION); + _flag = 1; + } + } + + return true; +} + +bool CLiftBot::EnterRoomMsg(CEnterRoomMsg *msg) { + _flag = 0; + changeView("Lift.Node 1.W", ""); + return true; +} + +bool CLiftBot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + if (msg->_action == 2 && msg->_param1 != _field108) { + CStatusChangeMsg statusMsg(_field108, msg->_param1, false); + statusMsg.execute("Well"); + + _field108 = msg->_param1; + } + + return true; +} + +bool CLiftBot::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (getName() != "LiftBot") + performAction(false); + + return true; +} + +bool CLiftBot::TurnOff(CTurnOff *msg) { + _enabled = false; + return true; +} + +bool CLiftBot::TurnOn(CTurnOn *msg) { + _enabled = true; + if (!_flag) { + if (isEquals("LiftBotTalking")) { + endTalking(this, MOVIE_REPEAT, findView()); + petSetArea(PET_CONVERSATION); + _flag = true; + } + } + + return true; +} + +bool CLiftBot::LeaveViewMsg(CLeaveViewMsg *msg) { + return true; +} + +bool CLiftBot::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) { + if (msg->_stateNum == 4) { + CPetControl *pet = getPetControl(); + if (pet) + msg->_stateVal = pet->getAssignedFloorNum(); + } else if (msg->_stateNum == 5) { + msg->_stateVal = _field108; + } else if (msg->_stateNum == 6) { + CPetControl *pet = getPetControl(); + if (pet) + msg->_stateVal = pet->getRoomsElevatorNum(); + } else { + msg->_stateVal = _field108; + } + + return true; +} + +bool CLiftBot::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) { + const char *const NAMES[] = { + "Groaning", "Groaning 2", "Talking 1", "Talking 2", "Talking 3", + "Happy Talking", "Complaining", "Aggressive", "Explaining", + "Happy Talking 2", "Happy Talking 3", "Happy Talking 4" + "Confidential", nullptr + }; + + if (msg->_value2 == 2) + playClip("At Rest", 0); + else + msg->_names = NAMES; + return true; +} + +bool CLiftBot::ActMsg(CActMsg *msg) { + if (msg->_action == "ActivateLift") { + _enabled = true; + CViewItem *view = findView(); + endTalking(this, true, view); + startTalking(this, 155, view); + } else if (msg->_action == "LiftArrive") { + CViewItem *view = findView(); + startTalking(this, 156, view); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/liftbot.h b/engines/titanic/npcs/liftbot.h new file mode 100644 index 0000000000..ccac53d5c7 --- /dev/null +++ b/engines/titanic/npcs/liftbot.h @@ -0,0 +1,66 @@ +/* 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_LIFTBOT_H +#define TITANIC_LIFTBOT_H + +#include "titanic/npcs/true_talk_npc.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CLiftBot : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool TextInputMsg(CTextInputMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool TurnOff(CTurnOff *msg); + bool TurnOn(CTurnOn *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg); + bool NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg); + bool ActMsg(CActMsg *msg); +private: + static bool _flag; + static bool _enabled; +private: + int _field108; +public: + CLASSDEF; + CLiftBot(); + + /** + * 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_LIFTBOT_H */ diff --git a/engines/titanic/npcs/maitre_d.cpp b/engines/titanic/npcs/maitre_d.cpp new file mode 100644 index 0000000000..09444f5611 --- /dev/null +++ b/engines/titanic/npcs/maitre_d.cpp @@ -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. + * + */ + +#include "titanic/npcs/maitre_d.h" +#include "titanic/core/room_item.h" +#include "titanic/sound/music_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMaitreD, CTrueTalkNPC) + ON_MESSAGE(RestaurantMusicChanged) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(NPCPlayTalkingAnimationMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(TrueTalkNotifySpeechStartedMsg) + ON_MESSAGE(TrueTalkNotifySpeechEndedMsg) + ON_MESSAGE(LoadSuccessMsg) + ON_MESSAGE(TextInputMsg) + ON_MESSAGE(TriggerNPCEvent) +END_MESSAGE_MAP() + +int CMaitreD::_v1; + +CMaitreD::CMaitreD() : CTrueTalkNPC(), + _string2("z#40.wav"), _string3("z#40.wav"), _field108(0), _field118(1), + _field11C(0), _field12C(0), _field130(1), _field134(0), _timerId(0) { +} + +void CMaitreD::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field108, indent); + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_field118, indent); + file->writeNumberLine(_field11C, indent); + file->writeQuotedLine(_string3, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_field130, indent); + + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_field134, indent); + file->writeNumberLine(_timerId, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CMaitreD::load(SimpleFile *file) { + file->readNumber(); + _field108 = file->readNumber(); + _string2 = file->readString(); + _field118 = file->readNumber(); + _field11C = file->readNumber(); + _string3 = file->readString(); + _field12C = file->readNumber(); + _field130 = file->readNumber(); + + _v1 = file->readNumber(); + _field134 = file->readNumber(); + _timerId = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CMaitreD::RestaurantMusicChanged(CRestaurantMusicChanged *msg) { + if (msg->_value.empty()) { + _field118 = 0; + } else { + _string3 = msg->_value; + _field118 = _field11C = 1; + } + + return true; +} + +bool CMaitreD::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + if (msg->_action == 8) { + _field12C = 1; + stopAnimTimer(_timerId); + _timerId = startAnimTimer("MD Fight", 3500, 0); + } else if (msg->_action == 9) { + stopAnimTimer(_timerId); + _timerId = 0; + } else if (msg->_action == 10) { + _field12C = 0; + _v1 = 1; + stopAnimTimer(_timerId); + _timerId = 0; + + CMaitreDDefeatedMsg defeatedMsg; + defeatedMsg.execute(findRoom()); + } + + return true; +} + +bool CMaitreD::EnterViewMsg(CEnterViewMsg *msg) { + endTalking(this, true, findView()); + _field12C = _field134; + + if (_string3 == "STMusic" && (!_field11C || _string2 == _string3)) + return true; + + if (_string3.contains("nasty ambient")) + startTalking(this, 111, findView()); + else if (!CMusicRoom::_musicHandler->checkSound(1)) + startTalking(this, 114, findView()); + else if (!CMusicRoom::_musicHandler->checkSound(3)) + startTalking(this, 113, findView()); + else if (!CMusicRoom::_musicHandler->checkSound(2)) + startTalking(this, 115, findView()); + else { + startTalking(this, 110, findView()); + CMaitreDHappyMsg happyMsg; + happyMsg.execute("MaitreD Left Arm"); + happyMsg.execute("MaitreD Right Arm"); + } + + return true; +} + +bool CMaitreD::LeaveViewMsg(CLeaveViewMsg *msg) { + _field134 = _field12C; + performAction(true); + stopAnimTimer(_timerId); + _timerId = 0; + + _field12C = 0; + return true; +} + +bool CMaitreD::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) { + static const char *const NAMES[] = { + "Talking0", "Talking1", "Talking2", "Talking3", "Talking4", + "Talking5", "Talking6", "Talking7", nullptr + }; + + if (msg->_value2 != 2) { + msg->_names = NAMES; + + CAnimateMaitreDMsg animMsg; + if (_field12C) + animMsg._value = 0; + animMsg.execute(this); + } + + return true; +} + +bool CMaitreD::TimerMsg(CTimerMsg *msg) { + if (msg->_action == "MD Fight") { + if (_field12C && compareViewNameTo("1stClassRestaurant.MaitreD Node.N")) { + startTalking(this, 131, findView()); + } + } else { + CTrueTalkNPC::TimerMsg(msg); + } + + return true; +} + +bool CMaitreD::TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg) { + if (_field12C) { + stopAnimTimer(_timerId); + _timerId = 0; + } + + CTrueTalkNPC::TrueTalkNotifySpeechStartedMsg(msg); + return true; +} + +bool CMaitreD::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) { + if (_field12C) { + stopAnimTimer(_timerId); + _timerId = startAnimTimer("MD Fight", 3000 + getRandomNumber(3000)); + } + + CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(msg); + return true; +} + +bool CMaitreD::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_field12C) { + _timerId = startAnimTimer("MD Fight", 3000 + getRandomNumber(3000)); + } + + return true; +} + +bool CMaitreD::TextInputMsg(CTextInputMsg *msg) { + CTrueTalkNPC::processInput(msg, findView()); + return true; +} + +bool CMaitreD::TriggerNPCEvent(CTriggerNPCEvent *msg) { + startTalking(this, msg->_value, findView()); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/maitre_d.h b/engines/titanic/npcs/maitre_d.h new file mode 100644 index 0000000000..878c32cc0b --- /dev/null +++ b/engines/titanic/npcs/maitre_d.h @@ -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. + * + */ + +#ifndef TITANIC_MAITRED_H +#define TITANIC_MAITRED_H + +#include "titanic/npcs/true_talk_npc.h" + +namespace Titanic { + +class CMaitreD : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool RestaurantMusicChanged(CRestaurantMusicChanged *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg); + bool TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); + bool TextInputMsg(CTextInputMsg *msg); + bool TriggerNPCEvent(CTriggerNPCEvent *msg); +private: + static int _v1; +private: + int _field108; + CString _string2; + int _field118; + int _field11C; + CString _string3; + int _field12C; + int _field130; + int _field134; + int _timerId; +public: + CLASSDEF; + CMaitreD(); + + /** + * 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_MAITRED_H */ diff --git a/engines/titanic/npcs/mobile.cpp b/engines/titanic/npcs/mobile.cpp new file mode 100644 index 0000000000..8a45f9e3cf --- /dev/null +++ b/engines/titanic/npcs/mobile.cpp @@ -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. + * + */ + +#include "titanic/npcs/mobile.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CMobile, CCharacter); + +CMobile::CMobile() : CCharacter(), _fieldDC(0) { +} + +void CMobile::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writePoint(_pos1, indent); + file->writeNumberLine(_fieldDC, indent); + + CCharacter::save(file, indent); +} + +void CMobile::load(SimpleFile *file) { + file->readNumber(); + _pos1 = file->readPoint(); + _fieldDC = file->readNumber(); + + CCharacter::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/mobile.h b/engines/titanic/npcs/mobile.h new file mode 100644 index 0000000000..68e74a5afe --- /dev/null +++ b/engines/titanic/npcs/mobile.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_MOBILE_H +#define TITANIC_MOBILE_H + +#include "titanic/npcs/character.h" + +namespace Titanic { + +class CMobile : public CCharacter { + DECLARE_MESSAGE_MAP; +private: + Point _pos1; + int _fieldDC; +public: + CLASSDEF; + CMobile(); + + /** + * 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_MOBILE_H */ diff --git a/engines/titanic/npcs/parrot.cpp b/engines/titanic/npcs/parrot.cpp new file mode 100644 index 0000000000..53e6884415 --- /dev/null +++ b/engines/titanic/npcs/parrot.cpp @@ -0,0 +1,756 @@ +/* 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/npcs/parrot.h" +#include "titanic/core/project_item.h" +#include "titanic/carry/carry.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrot, CTrueTalkNPC) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(TrueTalkTriggerActionMsg) + ON_MESSAGE(MouseDragStartMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(ParrotSpeakMsg) + ON_MESSAGE(NPCPlayTalkingAnimationMsg) + ON_MESSAGE(NPCPlayIdleAnimationMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(MovieFrameMsg) + ON_MESSAGE(PutParrotBackMsg) + ON_MESSAGE(PreEnterViewMsg) + ON_MESSAGE(PanningAwayFromParrotMsg) + ON_MESSAGE(LeaveRoomMsg) +END_MESSAGE_MAP() + +int CParrot::_v1; +int CParrot::_v2; +int CParrot::_v3; +int CParrot::_v4; +int CParrot::_v5; + +CParrot::CParrot() : CTrueTalkNPC() { + _field108 = 0; + _string2 = "CarryParrot"; + _field118 = 1; + _field11C = 25; + _field120 = 0; + _field124 = 73; + _field128 = 58; + _field12C = 0; + _field130 = 0; + _field134 = nullptr; + _field138 = 851; + _field13C = 851; + _field140 = 265; + _field144 = 274; + _field148 = 726; + _field14C = 730; + _field150 = 510; + _field154 = 570; + _field158 = 569; + _field15C = 689; + _field160 = 690; + _field164 = 725; + _field168 = 375; + _field16C = 508; + _field170 = 363; + _field174 = 375; + _field178 = 303; + _field17C = 313; + _field180 = 279; + _field184 = 302; + _field188 = 260; + _field18C = 264; + _field190 = 315; + _field194 = 327; + _field198 = 330; + _field19C = 360; + _field1A0 = 175; + _field1A4 = 259; + _field1A8 = 175; + _field1AC = 175; + _field1B0 = 162; + _field1B4 = 175; + _field1B8 = 150; + _field1BC = 162; + _field1C0 = 135; + _field1C4 = 150; + _field1C8 = 95; + _field1CC = 135; + _field1D0 = 76; + _field1D4 = 95; + _field1D8 = 55; + _field1DC = 76; + _field1E0 = 30; + _field1E4 = 55; + _field1E8 = 0; + _field1EC = 30; + + _assetName = "z454.dlg"; + _assetNumber = 0x13880; +} + +void CParrot::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_assetNumber, indent); + + file->writeQuotedLine(_assetName, indent); + file->writeNumberLine(_field108, indent); + file->writeNumberLine(_v1, indent); + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_v3, indent); + + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_field118, indent); + file->writeNumberLine(_field11C, indent); + file->writeNumberLine(_field120, indent); + file->writeNumberLine(_field124, indent); + file->writeNumberLine(_field128, indent); + file->writeNumberLine(_field12C, indent); + file->writeNumberLine(_field130, indent); + file->writeNumberLine(_v4, indent); + file->writeNumberLine(_v5, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CParrot::load(SimpleFile *file) { + file->readNumber(); + _assetNumber = file->readNumber(); + + _assetName = file->readString(); + _field108 = file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + _v3 = file->readNumber(); + + _string2 = file->readString(); + _field118 = file->readNumber(); + _field11C = file->readNumber(); + _field120 = file->readNumber(); + _field124 = file->readNumber(); + _field128 = file->readNumber(); + _field12C = file->readNumber(); + _field130 = file->readNumber(); + _v4 = file->readNumber(); + _v5 = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CParrot::ActMsg(CActMsg *msg) { + if (msg->_action == "PistaccioEaten") { + CActMsg actMsg("NutsEaten"); + actMsg.execute("Ear2"); + } else if (msg->_action == "Chicken") { + // Nothing to do + } else if (msg->_action == "CarryParrotLeftView") { + if (!_v2) { + _v1 = 0; + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("PerchCoreHolder"); + } + } else if (msg->_action == "StartChickenDrag") { + if (!_v4) { + stopMovie(); + startTalking(this, 280275, findView()); + _field12C = 0; + } + } else if (msg->_action == "EnteringFromTOW" && + (_v4 == 0 || _v4 == 2)) { + if (_v2) { + _v2 = 2; + } else { + setVisible(true); + CTreeItem *cageBar = getRoot()->findByName("CageBar"); + detach(); + attach(cageBar); + + _v4 = 0; + CActMsg actMsg1("OpenNow"); + actMsg1.execute("ParrotCage"); + CActMsg actMsg2("GainParrot"); + actMsg2.execute("ParrotLobbyController"); + } + } + + return true; +} + +bool CParrot::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!(_npcFlags & NPCFLAG_2000000) && _field100 <= 0) { + CTrueTalkTriggerActionMsg triggerMsg(280250, 280250, 1); + triggerMsg.execute(this); + } + + return true; +} + +bool CParrot::MovieEndMsg(CMovieEndMsg *msg) { + if ((_npcFlags & NPCFLAG_2000000) && clipExistsByEnd("Take Off", msg->_endFrame)) { + setVisible(false); + moveUnder(findRoom()); + stopMovie(); + + CActMsg actMsg1("LoseParrot"); + actMsg1.execute("ParrotLobbyController"); + + if (_field134) { + CActMsg actMsg2("PanAwayFromParrot"); + actMsg2.execute(_field134); + _field134 = nullptr; + } else { + CActMsg actMsg2("Shut"); + actMsg2.execute("ParrotCage"); + } + + _npcFlags &= ~NPCFLAG_2000000; + _v4 = 2; + } else if (_npcFlags & NPCFLAG_10000) { + if (_npcFlags & NPCFLAG_20000) { + _npcFlags = (_npcFlags & ~NPCFLAG_20000) | NPCFLAG_40000; + if (_npcFlags & NPCFLAG_100000) { + playClip("Walk Left Loop", MOVIE_NOTIFY_OBJECT); + movieEvent(236); + } else { + playClip("Walk Right Loop", MOVIE_NOTIFY_OBJECT); + } + } else if (_npcFlags & NPCFLAG_40000) { + int xp = _bounds.left + _bounds.width() / 2; + + if (_npcFlags & NPCFLAG_100000) { + if ((xp - _field128) > 32) { + setPosition(Point(_bounds.left - 40, _bounds.top)); + playClip("Walk Left Loop", MOVIE_NOTIFY_OBJECT); + movieEvent(236); + } else { + setPosition(Point(_bounds.left - 10, _bounds.top)); + playClip("Walk Left Outro", MOVIE_NOTIFY_OBJECT); + _npcFlags = (_npcFlags & ~NPCFLAG_40000) | NPCFLAG_80000; + } + } else { + if ((_field128 - xp) > 32) { + playClip("Walk Right Loop", MOVIE_NOTIFY_OBJECT); + movieEvent(244); + } else { + playClip("Walk Right Outro", MOVIE_NOTIFY_OBJECT); + _npcFlags = (_npcFlags & NPCFLAG_40000) | NPCFLAG_80000; + } + } + } else if (_npcFlags & NPCFLAG_80000) { + loadFrame(0); + if (_npcFlags & NPCFLAG_100000) + setPosition(Point(_bounds.left - 30, _bounds.top)); + else + setPosition(Point(_bounds.left + 14, _bounds.top)); + + _npcFlags &= ~(NPCFLAG_10000 | NPCFLAG_80000 | NPCFLAG_100000 | NPCFLAG_200000); + CTrueTalkNPC::MovieEndMsg(msg); + } else { + if (_npcFlags & NPCFLAG_1000000) { + Point pt = getMousePos(); + if (pt.x > 70 || pt.y < 90 || pt.y > 280) { + stopMovie(); + loadFrame(0); + _npcFlags &= ~NPCFLAG_1000000; + } + + if (clipExistsByEnd("Walk Left Loop", msg->_endFrame)) { + playClip("Lean Over To Chicken", MOVIE_NOTIFY_OBJECT); + setPosition(Point(_bounds.left - 55, _bounds.top)); + _field130 = (-100 - _bounds.left) / 5; + movieEvent(261); + movieEvent(262); + movieEvent(265); + movieEvent(268); + movieEvent(271); + return true; + + } else if (clipExistsByEnd("Lean Over To Chicken", msg->_endFrame)) { + playClip("Eat Chicken", 0); + playClip("Eat Chicken 2", MOVIE_NOTIFY_OBJECT); + _v1 = 1; + + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 0; + statusMsg.execute("PerchCoreHolder"); + + CTrueTalkTriggerActionMsg actionMsg; + actionMsg._param1 = 280266; + actionMsg._param2 = 1; + actionMsg.execute(this); + + CCarry *chicken = dynamic_cast<CCarry *>(findUnder(getRoot(), "Chicken")); + if (chicken) { + CActMsg actMsg("Eaten"); + actMsg.execute(chicken); + } + + _npcFlags &= ~NPCFLAG_1000000; + return true; + } + } + + if (clipExistsByEnd("Eat Chicken 2", msg->_endFrame)) { + CStatusChangeMsg statusMsg; + statusMsg._newStatus = 1; + statusMsg.execute("PerchCoreHolder"); + + if (_v2) { + loadMovie("z168.avi", false); + playClip("Take Off", MOVIE_NOTIFY_OBJECT); + setPosition(Point(20, 10)); + _npcFlags |= NPCFLAG_2000000; + } else { + _npcFlags &= ~(NPCFLAG_10000 | NPCFLAG_20000 | NPCFLAG_40000 | NPCFLAG_80000 | NPCFLAG_100000 | NPCFLAG_200000); + _npcFlags |= NPCFLAG_400000; + stopMovie(); + loadFrame(0); + setPosition(Point(-90, _bounds.top)); + } + } else { + CTrueTalkNPC::MovieEndMsg(msg); + } + } + } + + return true; +} + +bool CParrot::EnterViewMsg(CEnterViewMsg *msg) { + static const char *const NAMES[] = { + "Talking0", "Talking1", "Talking2", "Talking3", "Talking4", + "Talking5", "Talking6", "Talking7", nullptr + }; + + if (!_v4) { + setPosition(Point(_field124, _bounds.top)); + _field118 = 1; + _npcFlags &= ~(NPCFLAG_10000 | NPCFLAG_20000 | NPCFLAG_40000 | NPCFLAG_80000 | NPCFLAG_100000 | NPCFLAG_200000 | NPCFLAG_400000); + loadFrame(0); + endTalking(this, true, findView()); + + if (_field100 > 0) { + playRandomClip(NAMES, MOVIE_NOTIFY_OBJECT); + } else { + startTalking(this, 280258, findView()); + } + + petSetArea(PET_CONVERSATION); + _field12C = 0; + _npcFlags |= NPCFLAG_4; + } + + return true; +} + +bool CParrot::TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg) { + if (_v4) { + CViewItem *view = msg->_param2 ? findView() : nullptr; + startTalking(this, msg->_action, view); + } + + return true; +} + +bool CParrot::MouseDragStartMsg(CMouseDragStartMsg *msg) { + if (_field118 && !_v4 && checkPoint(msg->_mousePos, false, true)) { + setVisible(false); + CRoomItem *room = findRoom(); + + moveUnder(room); + startTalking(this, 280129); + performAction(true); + + CCarry *item = static_cast<CCarry *>(getRoot()->findByName(_string2)); + if (item) { + item->_fieldE0 = 1; + CPassOnDragStartMsg passMsg; + passMsg._mousePos = msg->_mousePos; + passMsg.execute(item); + msg->_dragItem = item; + + CActMsg actMsg("LoseParrot"); + actMsg.execute("ParrotLobbyController"); + } + } + + return true; +} + +bool CParrot::LeaveViewMsg(CLeaveViewMsg *msg) { + performAction(true); + _npcFlags &= ~NPCFLAG_4; + + return true; +} + +bool CParrot::ParrotSpeakMsg(CParrotSpeakMsg *msg) { + const char *const ROOM_NAMES[] = { + "SGTState", "SGTLittleLift", "SecClassLittleLift", "SecClassState", + "Lift", "ServiceElevator", "Dome", "Home", "MoonEmbLobby", nullptr + }; + + if (!stateGet24() || _v4 == 3 || compareViewNameTo("Titania.Node 18.N")) + return true; + + // Check for rooms not to speak in + for (const char *const *s = &ROOM_NAMES[0]; *s; ++s) { + if (isEquals(*s)) + return true; + } + + // Don't have the parrot speak too often + if ((getTicksCount() - _field120) < 20000 || _field100) + return true; + + playSound("z#475.wav", 50); + + if (msg->_target == "Bomb") { + startTalking("PerchedParrot", 280236); + } else if (msg->_target == "Announcements") { + startTalking("PerchedParrot", 280263); + } else if (msg->_target == "Television") { + startTalking("PerchedParrot", 280264); + } else if (msg->_target == "Barbot") { + if (msg->_action == "AskForDrink") + startTalking("PerchedParrot", 280262); + } else if (msg->_target == "SuccUBus") { + if (msg->_action == "TurnOn") + startTalking("PerchedParrot", 80161); + else if (msg->_action == "EnterView") + startTalking("PerchedParrot", 80159); + } else if (msg->_target == "Cellpoints") { + if (getRandomNumber(2) == 0) { + switch (getRandomNumber(2)) { + case 0: + startTalking("PerchedParrot", 80193); + break; + case 1: + startTalking("PerchedParrot", 80197); + break; + case 2: + startTalking("PerchedParrot", 80198); + break; + default: + break; + } + } else if (msg->_action == "DoorBot") { + startTalking("PerchedParrot", 80195); + } else if (msg->_action == "DeskBot") { + startTalking("PerchedParrot", 80194); + } else if (msg->_action == "BarBot") { + startTalking("PerchedParrot", 80191); + } else if (msg->_action == "BellBot") { + startTalking("PerchedParrot", 80192); + } else if (msg->_action == "LiftBot") { + startTalking("PerchedParrot", 80196); + } + } + + _field120 = getTicksCount(); + return true; +} + +bool CParrot::NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg) { + const char *const NAMES[] = { + "Talking0", "Talking1", "Talking2", "Talking3", "Talking4", + "Talking5", "Talking6", "Talking7", nullptr + }; + + if (!(_npcFlags & (NPCFLAG_10000 | NPCFLAG_20000 | NPCFLAG_40000 | NPCFLAG_80000 | NPCFLAG_100000 | NPCFLAG_200000 | NPCFLAG_400000)) + && _visible && !_v4) { + if (!compareViewNameTo("ParrotLobby.Node 1.N")) + msg->_names = NAMES; + } + + return true; +} + +bool CParrot::NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg) { + const char *const NAMES[] = { + "Idle0", "Idle1", "Peck At Feet", "Peck At Feet Left" + "Peck At Feet Right", nullptr + }; + + if (!(_npcFlags & (NPCFLAG_10000 | NPCFLAG_20000 | NPCFLAG_40000 | NPCFLAG_80000 | NPCFLAG_100000 | NPCFLAG_200000 | NPCFLAG_400000)) + && _visible && !_v4 && !compareViewNameTo("ParrotLobby.Node 1.N")) { + CGameObject *dragItem = getDraggingObject(); + if (!dragItem || dragItem->getName() == "Chicken") { + if (!_v5 ||getRandomNumber(3) != 0) { + if (getRandomNumber(1)) { + startTalking(this, 280267, findView()); + } else { + msg->_names = NAMES; + } + } else { + int id = -1; + switch (stateGet38()) { + case 0: + id = 280107; + break; + case 1: + id = 280106; + break; + case 2: + id = 280115; + break; + case 3: + id = 280114; + break; + case 4: + id = 280113; + break; + case 5: + id = 280112; + break; + case 6: + id = 280111; + break; + case 7: + id = 280110; + break; + case 8: + id = 280109; + break; + case 9: + id = 280108; + break; + case 10: + id = 280105; + break; + case 11: + id = 280000; + break; + default: + break; + } + + if (id != -1) + startTalking(this, id, findView()); + + CActMsg actMsg("FlashCore"); + actMsg.execute("PerchCoreHolder"); + } + } + } + + return true; +} + +bool CParrot::FrameMsg(CFrameMsg *msg) { + if (compareViewNameTo("ParrotLobby.Node 1.N")) + return false; + if (_v4) + return true; + + Point pt = getMousePos(); + CGameObject *dragObject = getDraggingObject(); + int xp = _bounds.left + _bounds.width() / 2; + + if ((_npcFlags & NPCFLAG_400000) && !hasActiveMovie()) { + _field128 = xp - (_field124 + _bounds.width() / 2); + + if (xp < 64) { + if (_field134) { + CActMsg actMsg("PanAwayFromParrot"); + actMsg.execute(_field134); + } + + _npcFlags &= ~(NPCFLAG_10000 | NPCFLAG_20000 | NPCFLAG_40000 + | NPCFLAG_80000 | NPCFLAG_100000 | NPCFLAG_200000 | NPCFLAG_400000); + return true; + } + } + + bool chickenFlag = dragObject && dragObject->isEquals("Chicken"); + + if (_npcFlags & NPCFLAG_1000000) { + if (!chickenFlag || pt.x > 70 || pt.y < 90 || pt.y > 280) { + stopMovie(); + loadFrame(0); + setPosition(Point(-90, _bounds.top)); + } + } else { + if (!chickenFlag) + return false; + } + + _field128 = CLIP((int)pt.x, 230, 480); + if ((_npcFlags & NPCFLAG_10000) || hasActiveMovie()) + return true; + + if (_field128 > 64) { + _npcFlags |= NPCFLAG_10000 | NPCFLAG_20000; + + if (_field128 >= xp) { + setPosition(Point(_bounds.left + 30, _bounds.top)); + _npcFlags |= NPCFLAG_200000; + playClip("Walk Right Intro", MOVIE_NOTIFY_OBJECT); + } else { + _npcFlags |= NPCFLAG_100000; + playClip("Walk Left Intro", MOVIE_NOTIFY_OBJECT); + } + } else if (chickenFlag && pt.y >= 90 && pt.y <= 280 && !_field12C) { + CParrotTriesChickenMsg triesMsg; + triesMsg.execute(dragObject); + + CTrueTalkTriggerActionMsg triggerMsg; + int id; + switch (triesMsg._value2) { + case 1: + id = 280056 + (triesMsg._value1 ? 234 : 0); + break; + case 2: + id = 280055 + (triesMsg._value1 ? 234 : 0); + break; + case 3: + id = 280054 + (triesMsg._value1 ? 234 : 0); + break; + default: + id = 280053 + (triesMsg._value1 ? 234 : 0); + break; + } + + if (id < 280266) { + if (pt.x < 75) { + _npcFlags |= NPCFLAG_1000000; + playClip("Walk Left Intro", MOVIE_STOP_PREVIOUS); + playClip("Walk Left Loop", MOVIE_NOTIFY_OBJECT); + movieEvent(236); + chickenFlag = false; + } else if ((pt.x - xp) > 15) { + _npcFlags |= NPCFLAG_800000; + playClip("Peck At Feet Right", MOVIE_NOTIFY_OBJECT); + movieEvent(170); + } else if ((xp - pt.x) > 15) { + _npcFlags |= NPCFLAG_800000; + playClip("Peck At Feet Left", MOVIE_NOTIFY_OBJECT); + movieEvent(142); + } else { + _npcFlags |= NPCFLAG_800000; + playClip("Peck At Feet", MOVIE_NOTIFY_OBJECT); + movieEvent(157); + } + } + + if (chickenFlag) { + triggerMsg._param2 = 1; + triggerMsg.execute(this); + _field12C = 1; + } + } + + return true; +} + +bool CParrot::MovieFrameMsg(CMovieFrameMsg *msg) { + if (_npcFlags & NPCFLAG_800000) { + CCarry *chicken = dynamic_cast<CCarry *>(findUnder(getRoot(), "Chicken")); + if (chicken) { + CActMsg actMsg("Eaten"); + actMsg.execute(chicken); + } + + _npcFlags &= ~NPCFLAG_800000; + } + + switch (msg->_frameNumber) { + case 244: + setPosition(Point(_bounds.left, _bounds.top + 45)); + break; + case 261: + case 262: + case 265: + case 268: + case 271: + setPosition(Point(_bounds.left + _field130, _bounds.top)); + break; + default: + break; + } + + return true; +} + +bool CParrot::PutParrotBackMsg(CPutParrotBackMsg *msg) { + const char *const NAMES[] = { + "Talking0", "Talking1", "Talking2", "Talking3", "Talking4", + "Talking5", "Talking6", "Talking7", nullptr + }; + + int xp = CLIP(msg->_value, 230, 480); + setVisible(true); + moveToView(); + _v4 = 0; + + setPosition(Point(xp - _bounds.width() / 2, _bounds.top)); + playRandomClip(NAMES, MOVIE_NOTIFY_OBJECT); + + CActMsg actMsg("GainParrot"); + actMsg.execute("ParrotLobbyController"); + + return true; +} + +bool CParrot::PreEnterViewMsg(CPreEnterViewMsg *msg) { + if (!_v4) { + loadMovie("z167.avi", false); + loadFrame(0); + } + + return true; +} + +bool CParrot::PanningAwayFromParrotMsg(CPanningAwayFromParrotMsg *msg) { + if (_v4) { + CActMsg actMsg("PanAwayFromParrot"); + actMsg.execute(msg->_target); + _field134 = 0; + } else if (_v2) { + _field134 = msg->_target; + loadMovie("z168.avi", false); + stopMovie(); + playClip("Take Off", MOVIE_NOTIFY_OBJECT); + _npcFlags |= NPCFLAG_2000000; + } else { + _npcFlags |= NPCFLAG_400000; + _field134 = msg->_target; + stopMovie(); + } + + return true; +} + +bool CParrot::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (!_v4) + startTalking(this, 280259); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/parrot.h b/engines/titanic/npcs/parrot.h new file mode 100644 index 0000000000..93e0643857 --- /dev/null +++ b/engines/titanic/npcs/parrot.h @@ -0,0 +1,128 @@ +/* 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_PARROT_H +#define TITANIC_PARROT_H + +#include "titanic/npcs/true_talk_npc.h" + +namespace Titanic { + +class CParrot : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool TrueTalkTriggerActionMsg(CTrueTalkTriggerActionMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool ParrotSpeakMsg(CParrotSpeakMsg *msg); + bool NPCPlayTalkingAnimationMsg(CNPCPlayTalkingAnimationMsg *msg); + bool NPCPlayIdleAnimationMsg(CNPCPlayIdleAnimationMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); + bool PutParrotBackMsg(CPutParrotBackMsg *msg); + bool PreEnterViewMsg(CPreEnterViewMsg *msg); + bool PanningAwayFromParrotMsg(CPanningAwayFromParrotMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); +public: + static int _v1; + static int _v2; + static int _v3; + static int _v4; + static int _v5; +private: + int _field108; + CString _string2; + int _field118; + int _field11C; + int _field120; + int _field124; + int _field128; + int _field12C; + int _field130; + CTreeItem *_field134; + int _field138; + int _field13C; + int _field140; + int _field144; + int _field148; + int _field14C; + int _field150; + int _field154; + int _field158; + int _field15C; + int _field160; + int _field164; + int _field168; + int _field16C; + int _field170; + int _field174; + int _field178; + int _field17C; + int _field180; + int _field184; + int _field188; + int _field18C; + int _field190; + int _field194; + int _field198; + int _field19C; + int _field1A0; + int _field1A4; + int _field1A8; + int _field1AC; + int _field1B0; + int _field1B4; + int _field1B8; + int _field1BC; + int _field1C0; + int _field1C4; + int _field1C8; + int _field1CC; + int _field1D0; + int _field1D4; + int _field1D8; + int _field1DC; + int _field1E0; + int _field1E4; + int _field1E8; + int _field1EC; +public: + CLASSDEF; + CParrot(); + + /** + * 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_PARROT_H */ diff --git a/engines/titanic/npcs/parrot_succubus.cpp b/engines/titanic/npcs/parrot_succubus.cpp new file mode 100644 index 0000000000..d285c219b5 --- /dev/null +++ b/engines/titanic/npcs/parrot_succubus.cpp @@ -0,0 +1,152 @@ +/* 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/npcs/parrot_succubus.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/carry/hose.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CParrotSuccUBus, CSuccUBus) + ON_MESSAGE(HoseConnectedMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(LeaveNodeMsg) +END_MESSAGE_MAP() + +CParrotSuccUBus::CParrotSuccUBus() : CSuccUBus(), _field1DC(0), + _field1EC(0), _field1F0(376), _field1F4(393) { +} + +void CParrotSuccUBus::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_field1DC, indent); + file->writeQuotedLine(_string3, indent); + file->writeNumberLine(_field1EC, indent); + + CSuccUBus::save(file, indent); +} + +void CParrotSuccUBus::load(SimpleFile *file) { + file->readNumber(); + _field1DC = file->readNumber(); + _string3 = file->readString(); + _field1EC = file->readNumber(); + + CSuccUBus::load(file); +} + +bool CParrotSuccUBus::HoseConnectedMsg(CHoseConnectedMsg *msg) { + CPetControl *pet = getPetControl(); + if (msg->_value == _field1DC) + return true; + if (mailExists(pet->getRoomFlags())) + return false; + + _field1DC = msg->_value; + if (_field1DC) { + CGameObject *item = msg->_object; + _string3 = item->getName(); + CHoseConnectedMsg hoseMsg(1, this); + hoseMsg.execute(msg->_object); + item->petMoveToHiddenRoom(); + + CPumpingMsg pumpingMsg(1, this); + pumpingMsg.execute(this); + _field1DC = 1; + + if (_enabled) { + _enabled = false; + } else { + playMovie(_startFrame9, _endFrame9, 0); + playSound("z#26.wav"); + } + + playMovie(_field1C4, _field1C8, MOVIE_NOTIFY_OBJECT); + } else { + stopMovie(); + stopSound(_field1EC); + playMovie(_field1F0, _field1F4, MOVIE_NOTIFY_OBJECT); + + CPumpingMsg pumpingMsg(0, this); + pumpingMsg.execute(_string3); + + CGameObject *obj = getHiddenObject(_string3); + if (obj) { + obj->petAddToInventory(); + obj->setVisible(true); + } + + _enabled = true; + CTurnOff offMsg; + offMsg.execute(this); + } + + return true; +} + +bool CParrotSuccUBus::EnterViewMsg(CEnterViewMsg *msg) { + if (_field1DC) { + playMovie(_field1CC, _field1D0, MOVIE_REPEAT); + return true; + } else { + return CSuccUBus::EnterViewMsg(msg); + } +} + +bool CParrotSuccUBus::MovieEndMsg(CMovieEndMsg *msg) { + if (msg->_endFrame == _field1C8) { + playMovie(_field1CC, _field1D0, MOVIE_REPEAT); + _field1EC = playSound("z#472.wav"); + return true; + } else { + return CSuccUBus::MovieEndMsg(msg); + } +} + +bool CParrotSuccUBus::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_field1DC) { + CHoseConnectedMsg hoseMsg; + hoseMsg._value = 0; + hoseMsg.execute(this); + return true; + } else { + return CSuccUBus::MouseButtonDownMsg(msg); + } +} + +bool CParrotSuccUBus::LeaveNodeMsg(CLeaveNodeMsg *msg) { + if (_field1DC) { + getHiddenObject(_string3); + if (CHose::_statics->_actionTarget.empty()) { + playSound("z#51.wav"); + CHoseConnectedMsg hoseMsg; + hoseMsg._value = 0; + hoseMsg.execute(this); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/parrot_succubus.h b/engines/titanic/npcs/parrot_succubus.h new file mode 100644 index 0000000000..74a4a032eb --- /dev/null +++ b/engines/titanic/npcs/parrot_succubus.h @@ -0,0 +1,60 @@ +/* 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_PARROT_SUCCUBUS_H +#define TITANIC_PARROT_SUCCUBUS_H + +#include "titanic/npcs/succubus.h" + +namespace Titanic { + +class CParrotSuccUBus : public CSuccUBus { + DECLARE_MESSAGE_MAP; + bool HoseConnectedMsg(CHoseConnectedMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool LeaveNodeMsg(CLeaveNodeMsg *msg); +public: + int _field1DC; + CString _string3; + int _field1EC; + int _field1F0; + int _field1F4; +public: + CLASSDEF; + CParrotSuccUBus(); + + /** + * 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_PARROT_SUCCUBUS_H */ diff --git a/engines/titanic/npcs/robot_controller.cpp b/engines/titanic/npcs/robot_controller.cpp new file mode 100644 index 0000000000..34c75e30eb --- /dev/null +++ b/engines/titanic/npcs/robot_controller.cpp @@ -0,0 +1,60 @@ +/* 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/npcs/robot_controller.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CRobotController, CGameObject) + ON_MESSAGE(SummonBotMsg) + ON_MESSAGE(SummonBotQueryMsg) +END_MESSAGE_MAP() + +CRobotController::CRobotController() : CGameObject(), _robotName("BellBot") { +} + +void CRobotController::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_robotName, indent); + + CGameObject::save(file, indent); +} + +void CRobotController::load(SimpleFile *file) { + file->readNumber(); + _robotName = file->readString(); + + CGameObject::load(file); +} + +bool CRobotController::SummonBotMsg(CSummonBotMsg *msg) { + if (!petDismissBot(msg->_npcName)) + petOnSummonBot(msg->_npcName, msg->_value); + + return true; +} + +bool CRobotController::SummonBotQueryMsg(CSummonBotQueryMsg *msg) { + return _robotName == msg->_npcName; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/robot_controller.h b/engines/titanic/npcs/robot_controller.h new file mode 100644 index 0000000000..326c2280dd --- /dev/null +++ b/engines/titanic/npcs/robot_controller.h @@ -0,0 +1,53 @@ +/* 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_ROBOT_CONTROLLER_H +#define TITANIC_ROBOT_CONTROLLER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CRobotController : public CGameObject { + DECLARE_MESSAGE_MAP; + bool SummonBotMsg(CSummonBotMsg *msg); + bool SummonBotQueryMsg(CSummonBotQueryMsg *msg); +protected: + CString _robotName; +public: + CLASSDEF; + CRobotController(); + + /** + * 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_ROBOT_CONTROLLER_H */ diff --git a/engines/titanic/npcs/starlings.cpp b/engines/titanic/npcs/starlings.cpp new file mode 100644 index 0000000000..7e5907f577 --- /dev/null +++ b/engines/titanic/npcs/starlings.cpp @@ -0,0 +1,63 @@ +/* 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/npcs/starlings.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CStarlings, CCharacter) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +CStarlings::CStarlings() : CCharacter(), _enabled(false) { +} + +void CStarlings::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_enabled, indent); + + CCharacter::save(file, indent); +} + +void CStarlings::load(SimpleFile *file) { + file->readNumber(); + _enabled = file->readNumber(); + + CCharacter::load(file); +} + +bool CStarlings::EnterViewMsg(CEnterViewMsg *msg) { + if (_enabled) + setVisible(false); + else + playMovie(MOVIE_REPEAT); + return true; +} + +bool CStarlings::StatusChangeMsg(CStatusChangeMsg *msg) { + _enabled = msg->_newStatus == 1; + setVisible(!_enabled); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/starlings.h b/engines/titanic/npcs/starlings.h new file mode 100644 index 0000000000..1998e6490d --- /dev/null +++ b/engines/titanic/npcs/starlings.h @@ -0,0 +1,53 @@ +/* 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_STARLINGS_H +#define TITANIC_STARLINGS_H + +#include "titanic/npcs/character.h" + +namespace Titanic { + +class CStarlings : public CCharacter { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +private: + bool _enabled; +public: + CLASSDEF; + CStarlings(); + + /** + * 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_STARLING_H */ diff --git a/engines/titanic/npcs/succubus.cpp b/engines/titanic/npcs/succubus.cpp new file mode 100644 index 0000000000..5588d862c3 --- /dev/null +++ b/engines/titanic/npcs/succubus.cpp @@ -0,0 +1,786 @@ +/* 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/npcs/succubus.h" +#include "titanic/carry/carry.h" +#include "titanic/carry/chicken.h" +#include "titanic/core/view_item.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSuccUBus, CTrueTalkNPC) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(SubAcceptCCarryMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) + ON_MESSAGE(PETDeliverMsg) + ON_MESSAGE(PETReceiveMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(TrueTalkGetStateValueMsg) + ON_MESSAGE(SignalObject) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(SUBTransition) + ON_MESSAGE(SetChevRoomBits) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MouseDragStartMsg) +END_MESSAGE_MAP() + +bool CSuccUBus::_enabled; +int CSuccUBus::_v1; +int CSuccUBus::_v2; +int CSuccUBus::_v3; +int CSuccUBus::_v4; + +CSuccUBus::CSuccUBus() : CTrueTalkNPC() { + _startFrame8 = -1; + _endFrame8 = -1; + _startFrame11 = -1; + _endFrame11 = -1; + _startFrame3 = 68; + _endFrame3 = 168; + _startFrame4 = 168; + _endFrame4 = 248; + _startFrame9 = 0; + _endFrame9 = 0x0E; + _startFrame10 = 0x0E; + _endFrame10 = 27; + _startFrame2 = 40; + _endFrame2 = 68; + _field140 = 1; + _mailP = nullptr; + _startFrame5 = 0; + _endFrame5 = 0; + _startFrame12 = 224; + _endFrame12 = 248; + _field158 = 0; + _field15C = 0; + _string2 = "NULL"; + _startFrame1 = 28; + _endFrame1 = 40; + _rect1 = Rect(82, 284, 148, 339); + _field184 = 15; + _field188 = 0; + _rect2 = Rect(0, 0, 240, 340); + _field19C = 0; + _soundHandle = -1; + _isChicken = false; + _isFeathers = false; + _field1AC = 0; + _field1B0 = 0; + _startFrame6 = 303; + _endFrame6 = 312; + _startFrame7 = 313; + _endFrame7 = 325; + _field1C4 = 326; + _field1C8 = 347; + _field1CC = 348; + _field1D0 = 375; + _field1D4 = 1; + _field1D8 = 0; +} + +void CSuccUBus::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + + file->writeNumberLine(_enabled, indent); + file->writeNumberLine(_startFrame8, indent); + file->writeNumberLine(_endFrame8, indent); + file->writeNumberLine(_startFrame11, indent); + file->writeNumberLine(_endFrame11, indent); + file->writeNumberLine(_startFrame3, indent); + file->writeNumberLine(_endFrame3, indent); + file->writeNumberLine(_startFrame4, indent); + file->writeNumberLine(_endFrame4, indent); + file->writeNumberLine(_startFrame9, indent); + file->writeNumberLine(_endFrame9, indent); + file->writeNumberLine(_startFrame10, indent); + file->writeNumberLine(_endFrame10, indent); + file->writeNumberLine(_startFrame2, indent); + file->writeNumberLine(_endFrame2, indent); + file->writeNumberLine(_field140, indent); + + file->writeNumberLine(_v2, indent); + file->writeNumberLine(_startFrame5, indent); + file->writeNumberLine(_endFrame5, indent); + file->writeNumberLine(_startFrame12, indent); + file->writeNumberLine(_endFrame12, indent); + file->writeNumberLine(_field158, indent); + file->writeNumberLine(_field15C, indent); + + file->writeQuotedLine(_string2, indent); + file->writeNumberLine(_startFrame1, indent); + file->writeNumberLine(_endFrame1, indent); + file->writeNumberLine(_rect1.left, indent); + file->writeNumberLine(_rect1.top, indent); + file->writeNumberLine(_rect1.right, indent); + file->writeNumberLine(_rect1.bottom, indent); + file->writeNumberLine(_field184, indent); + file->writeNumberLine(_field188, indent); + file->writeNumberLine(_rect2.left, indent); + file->writeNumberLine(_rect2.top, indent); + file->writeNumberLine(_rect2.right, indent); + file->writeNumberLine(_rect2.bottom, indent); + file->writeNumberLine(_field19C, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_isChicken, indent); + file->writeNumberLine(_isFeathers, indent); + file->writeNumberLine(_field1AC, indent); + file->writeNumberLine(_field1B0, indent); + file->writeNumberLine(_startFrame6, indent); + file->writeNumberLine(_endFrame6, indent); + file->writeNumberLine(_startFrame7, indent); + file->writeNumberLine(_endFrame7, indent); + file->writeNumberLine(_field1C4, indent); + file->writeNumberLine(_field1C8, indent); + file->writeNumberLine(_field1CC, indent); + file->writeNumberLine(_field1D0, indent); + file->writeNumberLine(_field1D4, indent); + + file->writeNumberLine(_v3, indent); + file->writeNumberLine(_field1D8, indent); + file->writeNumberLine(_field104, indent); + + CTrueTalkNPC::save(file, indent); +} + +void CSuccUBus::load(SimpleFile *file) { + file->readNumber(); + + _enabled = file->readNumber(); + _startFrame8 = file->readNumber(); + _endFrame8 = file->readNumber(); + _startFrame11 = file->readNumber(); + _endFrame11 = file->readNumber(); + _startFrame3 = file->readNumber(); + _endFrame3 = file->readNumber(); + _startFrame4 = file->readNumber(); + _endFrame4 = file->readNumber(); + _startFrame9 = file->readNumber(); + _endFrame9 = file->readNumber(); + _startFrame10 = file->readNumber(); + _endFrame10 = file->readNumber(); + _startFrame2 = file->readNumber(); + _endFrame2 = file->readNumber(); + _field140 = file->readNumber(); + + _v2 = file->readNumber(); + _startFrame5 = file->readNumber(); + _endFrame5 = file->readNumber(); + _startFrame12 = file->readNumber(); + _endFrame12 = file->readNumber(); + _field158 = file->readNumber(); + _field15C = file->readNumber(); + + _string2 = file->readString(); + _startFrame1 = file->readNumber(); + _endFrame1 = file->readNumber(); + _rect1.left = file->readNumber(); + _rect1.top = file->readNumber(); + _rect1.right = file->readNumber(); + _rect1.bottom = file->readNumber(); + _field184 = file->readNumber(); + _field188 = file->readNumber(); + _rect2.left = file->readNumber(); + _rect2.top = file->readNumber(); + _rect2.right = file->readNumber(); + _rect2.bottom = file->readNumber(); + _field19C = file->readNumber(); + _soundHandle = file->readNumber(); + _isChicken = file->readNumber(); + _isFeathers = file->readNumber(); + _field1AC = file->readNumber(); + _field1B0 = file->readNumber(); + _startFrame6 = file->readNumber(); + _endFrame6 = file->readNumber(); + _startFrame7 = file->readNumber(); + _endFrame7 = file->readNumber(); + _field1C4 = file->readNumber(); + _field1C8 = file->readNumber(); + _field1CC = file->readNumber(); + _field1D0 = file->readNumber(); + _field1D4 = file->readNumber(); + + _v3 = file->readNumber(); + _field1D8 = file->readNumber(); + _field104 = file->readNumber(); + + CTrueTalkNPC::load(file); +} + +bool CSuccUBus::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (!_field1D8) { + Rect tempRect = _rect1; + tempRect.translate(_bounds.left, _bounds.top); + + if (!_enabled || (_field188 && tempRect.contains(msg->_mousePos))) { + CTurnOn onMsg; + onMsg.execute(this); + _enabled = true; + } else if (getRandomNumber(256) < 130) { + _enabled = false; + CTurnOff offMsg; + offMsg.execute(this); + } else { + switch (getRandomNumber(2)) { + case 0: + startTalking(this, 230055, findView()); + break; + case 1: + startTalking(this, 230067, findView()); + break; + case 2: + startTalking(this, 230045, findView()); + break; + default: + break; + } + } + } + + return true; +} + +bool CSuccUBus::SubAcceptCCarryMsg(CSubAcceptCCarryMsg *msg) { + if (!msg->_item) + return false; + + CPetControl *pet = getPetControl(); + CCarry *item = dynamic_cast<CCarry *>(msg->_item); + Rect tempRect = _rect2; + tempRect.translate(_bounds.left, _bounds.top); + uint roomFlags = pet ? pet->getRoomFlags() : 0; + + if (!_enabled || !pet || !item || !tempRect.contains(item->getControid())) { + item->petAddToInventory(); + } else if (mailExists(roomFlags)) { + petDisplayMessage("The Succ-U-Bus is a Single Entity Delivery Device."); + item->petAddToInventory(); + } else { + petContainerRemove(item); + pet->phonographAction(""); + + CChicken *chicken = dynamic_cast<CChicken *>(item); + bool chickenFlag = chicken ? chicken->_string6 != "None" : false; + + item->setVisible(false); + if (_startFrame1 >= 0) { + playSound("z#23.wav"); + playMovie(_startFrame1, _endFrame1, 0); + } + + if (!chickenFlag) { + _field188 = 1; + item->addMail(roomFlags); + petSetArea(PET_REMOTE); + petHighlightGlyph(16); + CSUBTransition transMsg; + transMsg.execute(this); + } else { + if (_startFrame2 >= 0) { + startTalking(this, 70219, findView()); + playMovie(_startFrame2, _endFrame2, 0); + } + + if (_startFrame3 >= 0) { + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT); + _field158 = 2; + } + + CViewItem *view = parseView(chicken->_fullViewName); + if (!view) + return false; + + item->setPosition(item->_origPos); + item->moveUnder(view); + + CSUBTransition transMsg; + transMsg.execute(this); + } + } + + return true; +} + +bool CSuccUBus::EnterViewMsg(CEnterViewMsg *msg) { + if (getRandomNumber(4) == 0 && compareRoomNameTo("PromenadeDeck")) { + CParrotSpeakMsg speakMsg("SuccUBus", "EnterView"); + speakMsg.execute("PerchedParrot"); + } + + petSetRemoteTarget(); + _mailP = nullptr; + if (_startFrame8 >= 0) + loadFrame(_startFrame8); + + return true; +} + +bool CSuccUBus::LeaveViewMsg(CLeaveViewMsg *msg) { + petDisplayMessage(2, ""); + if (_startFrame8 >= 0) + loadFrame(_startFrame8); + else if (!_field15C && _startFrame9 >= 0) + loadFrame(_startFrame9); + + petClear(); + if (_soundHandle != -1) { + stopSound(_soundHandle, 1); + _soundHandle = -1; + } + + if (_enabled) { + _enabled = false; + if (_startFrame10 >= 0) + playSound("z#27.wav", 100); + + if (_field15C) + setVisible(false); + } + + performAction(true, findView()); + CSUBTransition transMsg; + transMsg.execute(this); + + return true; +} + +bool CSuccUBus::PETDeliverMsg(CPETDeliverMsg *msg) { + if (_field1D8) + return true; + + if (!_enabled) { + petDisplayMessage(2, "The Succ-U-Bus is in Standby, or \"Off\" mode at present."); + return true; + } + + CPetControl *pet = getPetControl(); + if (!pet) + return true; + + CGameObject *mailObject = findMail(pet->getRoomFlags()); + if (!mailObject) { + switch (getRandomNumber(2)) { + case 0: + startTalking(this, 70111, findView()); + break; + case 1: + startTalking(this, 70112, findView()); + break; + case 2: + startTalking(this, 70113, findView()); + break; + default: + break; + } + + petDisplayMessage(2, "There is currently nothing in the tray to send."); + } else { + _field19C = 0; + + CRoomFlags roomFlags = _roomFlags; + if (!pet->testRooms5(roomFlags) || getPassengerClass() > 0) { + roomFlags = pet->getSpecialRoomFlags("BilgeRoom"); + _field19C = 1; + } else { + pet->getMailDest(roomFlags); + } + + _isFeathers = mailObject->getName() == "Feathers"; + _isChicken = mailObject->getName() == "Chicken"; + _field158 = 0; + _field188 = 0; + _field1D8 = 1; + inc54(); + + if (_isFeathers) { + _field19C = 0; + removeMail(roomFlags, roomFlags); + pet->phonographAction(""); + + if (_startFrame2 >= 0) { + playMovie(_startFrame2, _endFrame2, 0); + startTalking(this, 230022, findView()); + } + + _field158 = 1; + if (_startFrame3 >= 0) + playMovie(_startFrame3, _endFrame3, 0); + + if (_startFrame4 >= 0) { + _mailP = mailObject; + playMovie(_startFrame4, _endFrame4, MOVIE_NOTIFY_OBJECT); + } + + if (_startFrame5 >= 0) { + playMovie(_startFrame5, _endFrame5, 0); + } + } else { + removeMail(pet->getRoomFlags(), roomFlags); + pet->phonographAction(""); + + if (_startFrame2 >= 0) { + playMovie(_startFrame2, _endFrame2, 0); + startTalking(this, 230012, findView()); + } + + if (_startFrame3 >= 0) + playMovie(_startFrame3, _endFrame3, MOVIE_NOTIFY_OBJECT); + } + } + + return true; +} + +bool CSuccUBus::PETReceiveMsg(CPETReceiveMsg *msg) { + CPetControl *pet = getPetControl(); + + if (_field1D8 || !pet) + return true; + if (!_enabled) { + petDisplayMessage(2, "The Succ-U-Bus is in Standby, or \"Off\" mode at present."); + return true; + } + + uint petRoomFlags = pet->getRoomFlags(); + if (mailExists(petRoomFlags)) { + switch (getRandomNumber(2)) { + case 0: + startTalking(this, 70080, findView()); + break; + case 1: + startTalking(this, 70081, findView()); + break; + case 2: + startTalking(this, 70082, findView()); + break; + default: + break; + } + } else { + CGameObject *mailObject = findMailByFlags(compareRoomNameTo("Titania") + ? 3 : _field140, petRoomFlags); + if (!mailObject) { + if (getRandomNumber(1) == 0) { + startTalking(this, 70104, findView()); + } else { + startTalking(this, 70105, findView()); + } + + playMovie(_startFrame6, _endFrame6, 0); + playMovie(_startFrame7, _endFrame7, 0); + petDisplayMessage(2, "There is currently nothing to deliver."); + } else { + startTalking(this, 230004, findView()); + + if (_startFrame4 >= 0) { + _field158 = 1; + _field1D8 = 1; + inc54(); + playMovie(_startFrame4, _endFrame4, MOVIE_NOTIFY_OBJECT); + } + } + } + + return true; +} + +bool CSuccUBus::MovieEndMsg(CMovieEndMsg *msg) { + CPetControl *pet = getPetControl(); + uint petRoomFlags = pet ? pet->getRoomFlags() : 0; + + if (msg->_endFrame == _endFrame10) { + if (_startFrame11 >= 0) + playSound("z#30.wav", 100); + + if (_field15C) { + _field15C = false; + setVisible(false); + CSignalObject signalMsg; + signalMsg._numValue = 1; + signalMsg.execute(_string2); + } + } + + if (msg->_endFrame == _endFrame9) { + bool flag = false; + + if (pet && mailExists(petRoomFlags)) { + CGameObject *mailObject = _v3 && compareRoomNameTo("Titania") ? + findMailByFlags(3, petRoomFlags) : + findMailByFlags(_field140, petRoomFlags); + + if (mailObject) { + switch (getRandomNumber(4)) { + case 0: + startTalking(this, 70094, findView()); + break; + case 1: + startTalking(this, 70095, findView()); + break; + case 2: + startTalking(this, 70096, findView()); + break; + case 3: + startTalking(this, 70098, findView()); + break; + case 4: + startTalking(this, 70099, findView()); + break; + default: + break; + } + flag = true; + } + } + + if (!_field188 && !flag) { + stopSound(_soundHandle); + _soundHandle = -1; + + switch (getRandomNumber(_v2 ? 7 : 5, &_field1B0)) { + case 2: + startTalking(this, 230001, findView()); + break; + case 3: + startTalking(this, 230002, findView()); + break; + case 4: + startTalking(this, 230003, findView()); + break; + case 5: + startTalking(this, 230064, findView()); + break; + case 6: + startTalking(this, 230062, findView()); + break; + case 7: + startTalking(this, 230063, findView()); + break; + default: + break; + } + } + } + + if (msg->_endFrame == _endFrame3) { + if (_field158 == 1) { + startTalking(this, 230022, findView()); + } else if (_field158 == 2) { + startTalking(this, 230017, findView()); + } else if (_field19C) { + startTalking(this, 230019, findView()); + _field19C = 0; + } else if (_isChicken) { + startTalking(this, 230018, findView()); + _isChicken = false; + } else { + startTalking(this, 230013, findView()); + } + + if (_field1D8) { + _field1D8 = 0; + dec54(); + } + + CSUBTransition transMsg; + transMsg.execute(this); + } + + if (msg->_endFrame == _endFrame4) { + if (pet && _mailP) { + _mailP->setMailId(petRoomFlags); + } + + _field188 = 1; + _mailP = 0; + if (_field1D8) { + _field1D8 = 0; + dec54(); + } + + CSUBTransition transMsg; + transMsg.execute(this); + } + + return true; +} + +bool CSuccUBus::TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg) { + if (msg->_stateNum == 1) + msg->_stateVal = _enabled; + + return true; +} + +bool CSuccUBus::SignalObject(CSignalObject *msg) { + if (msg->_numValue == 1) { + _string2 = msg->_strValue; + _field15C = 1; + setVisible(true); + CTurnOn onMsg; + onMsg.execute(this); + } + + return true; +} + +bool CSuccUBus::TurnOn(CTurnOn *msg) { + if (getRandomNumber(9) == 0) { + CParrotSpeakMsg speakMsg("SuccUBus", "TurnOn"); + speakMsg.execute("PerchedParrot"); + } + + CPetControl *pet = getPetControl(); + if (pet) { + if (!_field15C && _startFrame8 >= 0) { + playMovie(_startFrame8, _endFrame8, 0); + playSound("z#30.wav", 100); + } + + if (_startFrame9 >= 0) { + playMovie(_startFrame9, _endFrame9, MOVIE_NOTIFY_OBJECT); + playSound("z#26.wav", 100); + } + + uint petRoomFlags = pet->getRoomFlags(); + if (mailExists(petRoomFlags) && _endFrame1 >= 0) + playMovie(_endFrame1, _endFrame1, 0); + + _enabled = true; + CSUBTransition transMsg; + transMsg.execute(this); + + endTalking(this, true, findView()); + petSetArea(PET_REMOTE); + petHighlightGlyph(16); + } + + return true; +} + +bool CSuccUBus::TurnOff(CTurnOff *msg) { + if (_soundHandle != -1) { + stopSound(_soundHandle); + _soundHandle = -1; + } + + if (_startFrame10 >= 0) { + playSound("z#27.wav", 100); + playMovie(_startFrame10, _endFrame10, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + } + + if (!_field15C && _startFrame11 >= 0) + playMovie(_startFrame11, _endFrame11, MOVIE_NOTIFY_OBJECT | MOVIE_GAMESTATE); + + _enabled = false; + performAction(true); + CSUBTransition transMsg; + transMsg.execute(this); + + return true; +} + +bool CSuccUBus::SUBTransition(CSUBTransition *msg) { + CPetControl *pet = getPetControl(); + + if (pet) { + uint petRoomFlags = pet->getRoomFlags(); + + if (_enabled) { + CGameObject *mailObject = findMail(petRoomFlags); + if (mailObject) + pet->phonographAction("Send"); + else + pet->phonographAction("Receive"); + } else { + if (pet->isSuccUBusRoom(petRoomFlags)) + pet->phonographAction("Record"); + else + pet->phonographAction(""); + } + } + + return true; +} + +bool CSuccUBus::SetChevRoomBits(CSetChevRoomBits *msg) { + if (_enabled) { + _roomFlags = msg->_roomNum; + playSound("z#98.wav", 100); + } + + return true; +} + +bool CSuccUBus::ActMsg(CActMsg *msg) { + if (msg->_action == "EnableObject") + _v3 = 1; + else if (msg->_action == "DisableObject") + _v3 = 0; + + return true; +} + +bool CSuccUBus::MouseDragStartMsg(CMouseDragStartMsg *msg) { + CPetControl *pet = getPetControl(); + Rect tempRect = _rect1; + tempRect.translate(_bounds.left, _bounds.top); + + if (_field1D8 || !_enabled || !_field188 || !tempRect.contains(msg->_mousePos) + || !pet) + return true; + + uint petRoomFlags = pet->getRoomFlags(); + CGameObject *mailObject = findMail(petRoomFlags); + if (!mailObject) + return true; + + petAddToCarryParcel(mailObject); + CViewItem *view = getView(); + if (!view) + return true; + + mailObject->moveUnder(view); + mailObject->setPosition(Point(msg->_mousePos.x + mailObject->_bounds.width() / 2, + msg->_mousePos.y + mailObject->_bounds.height() / 2)); + + CVisibleMsg visibleMsg(true); + visibleMsg.execute(mailObject); + CPassOnDragStartMsg dragMsg; + dragMsg._mousePos = msg->_mousePos; + dragMsg._value3 = 1; + dragMsg.execute(mailObject); + + if (!dragMsg._value4) + msg->_dragItem = mailObject; + + loadFrame(_field184); + _field188 = 0; + CSUBTransition transMsg; + transMsg.execute(this); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/succubus.h b/engines/titanic/npcs/succubus.h new file mode 100644 index 0000000000..7ca8037a0a --- /dev/null +++ b/engines/titanic/npcs/succubus.h @@ -0,0 +1,120 @@ +/* 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_SUCCUBUS_H +#define TITANIC_SUCCUBUS_H + +#include "titanic/npcs/true_talk_npc.h" +#include "titanic/messages/pet_messages.h" + +namespace Titanic { + +class CSuccUBus : public CTrueTalkNPC { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool SubAcceptCCarryMsg(CSubAcceptCCarryMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); + bool PETDeliverMsg(CPETDeliverMsg *msg); + bool PETReceiveMsg(CPETReceiveMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool TrueTalkGetStateValueMsg(CTrueTalkGetStateValueMsg *msg); + bool SignalObject(CSignalObject *msg); + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool SUBTransition(CSUBTransition *msg); + bool SetChevRoomBits(CSetChevRoomBits *msg); + bool ActMsg(CActMsg *msg); + bool MouseDragStartMsg(CMouseDragStartMsg *msg); +protected: + static bool _enabled; + static int _v1; + static int _v2; + static int _v3; + static int _v4; +protected: + int _startFrame8; + int _endFrame8; + int _startFrame11; + int _endFrame11; + int _startFrame3; + int _endFrame3; + int _startFrame4; + int _endFrame4; + int _startFrame9; + int _endFrame9; + int _startFrame10; + int _endFrame10; + int _startFrame2; + int _endFrame2; + int _field140; + CGameObject *_mailP; + int _startFrame5; + int _endFrame5; + int _startFrame12; + int _endFrame12; + int _field158; + bool _field15C; + CString _string2; + int _startFrame1; + int _endFrame1; + Rect _rect1; + int _field184; + int _field188; + Rect _rect2; + int _field190; + int _field194; + int _field198; + int _field19C; + int _soundHandle; + bool _isChicken; + bool _isFeathers; + int _field1AC; + int _field1B0; + int _startFrame6; + int _endFrame6; + int _startFrame7; + int _endFrame7; + int _field1C4; + int _field1C8; + int _field1CC; + int _field1D0; + int _field1D4; + int _field1D8; +public: + CLASSDEF; + CSuccUBus(); + + /** + * 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_SUCCUBUS_H */ diff --git a/engines/titanic/npcs/summon_bots.cpp b/engines/titanic/npcs/summon_bots.cpp new file mode 100644 index 0000000000..6d71847548 --- /dev/null +++ b/engines/titanic/npcs/summon_bots.cpp @@ -0,0 +1,86 @@ +/* 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/npcs/summon_bots.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSummonBots, CRobotController) + ON_MESSAGE(SummonBotQueryMsg) + ON_MESSAGE(SummonBotMsg) +END_MESSAGE_MAP() + +CSummonBots::CSummonBots() : CRobotController(), _string2("NULL"), + _fieldC8(0), _fieldCC(0) { +} + +void CSummonBots::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldC8, indent); + file->writeNumberLine(_fieldCC, indent); + file->writeQuotedLine(_string2, indent); + + CRobotController::save(file, indent); +} + +void CSummonBots::load(SimpleFile *file) { + file->readNumber(); + _fieldC8 = file->readNumber(); + _fieldCC = file->readNumber(); + _string2 = file->readString(); + + CRobotController::load(file); +} + +bool CSummonBots::SummonBotQueryMsg(CSummonBotQueryMsg *msg) { + if (msg->_npcName == "BellBot") { + if (_fieldC8 && !petCheckNode(_string2)) + return true; + } else if (msg->_npcName == "DoorBot") { + if (_fieldCC && !petCheckNode(_string2)) + return true; + } + + return false; +} + +bool CSummonBots::SummonBotMsg(CSummonBotMsg *msg) { + if (msg->_npcName == "BellBot") { + if (!_fieldC8) + return false; + + if (petDismissBot("BellBot")) + petOnSummonBot("Bellbot", msg->_value); + } else if (msg->_npcName == "DoorBot") { + if (!_fieldCC) + return false; + + if (petDismissBot("Doorbot")) + petOnSummonBot("Doorbot", msg->_value); + } else { + return false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/summon_bots.h b/engines/titanic/npcs/summon_bots.h new file mode 100644 index 0000000000..1da6e68245 --- /dev/null +++ b/engines/titanic/npcs/summon_bots.h @@ -0,0 +1,55 @@ +/* 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_SUMMON_BOTS_H +#define TITANIC_SUMMON_BOTS_H + +#include "titanic/npcs/robot_controller.h" + +namespace Titanic { + +class CSummonBots : public CRobotController { + DECLARE_MESSAGE_MAP; + bool SummonBotQueryMsg(CSummonBotQueryMsg *msg); + bool SummonBotMsg(CSummonBotMsg *msg); +protected: + CString _string2; + int _fieldC8; + int _fieldCC; +public: + CLASSDEF; + CSummonBots(); + + /** + * 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_SUMMON_BOTS_H */ diff --git a/engines/titanic/npcs/titania.cpp b/engines/titanic/npcs/titania.cpp new file mode 100644 index 0000000000..000595f6b7 --- /dev/null +++ b/engines/titanic/npcs/titania.cpp @@ -0,0 +1,225 @@ +/* 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/npcs/titania.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CTitania, CCharacter) + ON_MESSAGE(AddHeadPieceMsg) + ON_MESSAGE(TakeHeadPieceMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(TimerMsg) +END_MESSAGE_MAP() + +CTitania::CTitania() : CCharacter() { + _speechCentre = false; + _olfactoryCentre = false; + _centralCore = false; + _visionCentre = false; + _eye1 = false; + _eye2 = false; + _ear1 = false; + _ear2 = false; + _nose = false; + _mouth = false; + _showIntro = true; +} + +void CTitania::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_speechCentre, indent); + file->writeNumberLine(_olfactoryCentre, indent); + file->writeNumberLine(_auditoryCentre, indent); + file->writeNumberLine(_centralCore, indent); + file->writeNumberLine(_visionCentre, indent); + file->writeNumberLine(_eye1, indent); + file->writeNumberLine(_eye2, indent); + file->writeNumberLine(_ear1, indent); + file->writeNumberLine(_ear2, indent); + file->writeNumberLine(_nose, indent); + file->writeNumberLine(_mouth, indent); + file->writeNumberLine(_showIntro, indent); + + CCharacter::save(file, indent); +} + +void CTitania::load(SimpleFile *file) { + file->readNumber(); + _speechCentre = file->readNumber(); + _olfactoryCentre = file->readNumber(); + _auditoryCentre = file->readNumber(); + _centralCore = file->readNumber(); + _visionCentre = file->readNumber(); + _eye1 = file->readNumber(); + _eye2 = file->readNumber(); + _ear1 = file->readNumber(); + _ear2 = file->readNumber(); + _nose = file->readNumber(); + _mouth = file->readNumber(); + _showIntro = file->readNumber(); + + CCharacter::load(file); +} + +bool CTitania::AddHeadPieceMsg(CAddHeadPieceMsg *msg) { + if (msg->_value == "VisionCentre") { + _visionCentre = true; + } else if (msg->_value == "AuditoryCentre") { + _auditoryCentre = true; + } else if (msg->_value == "OlfactoryCentre") { + _olfactoryCentre = true; + } else if (msg->_value == "SpeechCentre") { + _speechCentre = true; + } else if (msg->_value == "CentralCore") { + _centralCore = true; + } else if (msg->_value == "Eye1") { + _eye1 = true; + } else if (msg->_value == "Eye2") { + _eye2 = true; + } else if (msg->_value == "Ear1") { + _ear1 = true; + } else if (msg->_value == "Ear2") { + _ear2 = true; + } else if (msg->_value == "Mouth") { + _mouth = true; + } else if (msg->_value == "Nose") { + _nose = true; + } + + CActMsg actMsg("CheckHead"); + actMsg.execute(this); + return true; +} + +bool CTitania::TakeHeadPieceMsg(CTakeHeadPieceMsg *msg) { + if (msg->_value == "VisionCentre") { + _visionCentre = false; + } else if (msg->_value == "AuditoryCentre") { + _auditoryCentre = false; + } else if (msg->_value == "OlfactoryCentre") { + _olfactoryCentre = false; + } else if (msg->_value == "SpeechCentre") { + _speechCentre = false; + } else if (msg->_value == "CentralCore") { + _centralCore = false; + } else if (msg->_value == "Eye1") { + _eye1 = false; + } else if (msg->_value == "Eye2") { + _eye2 = false; + } else if (msg->_value == "Ear1") { + _ear1 = false; + } else if (msg->_value == "Ear2") { + _ear2 = false; + } else if (msg->_value == "Mouth") { + _mouth = false; + } else if (msg->_value == "Nose") { + _nose = false; + } + + CActMsg actMsg("CheckHead"); + actMsg.execute(this); + return true; +} + +bool CTitania::ActMsg(CActMsg *msg) { + if (msg->_action == "SleepTitania") { + setVisible(true); + playCutscene(52, 104); + playSound("z#47.wav", 100); + changeView("Titania.Node 7.S", ""); + + petShow(); + enableMouse(); + CSetFrameMsg frameMsg; + frameMsg.execute("Bomb"); + + } else if (msg->_action == "CheckHead") { + CSenseWorkingMsg workingMsg1("Not Working"); + CSenseWorkingMsg workingMsg2("Not Working"); + CSenseWorkingMsg workingMsg3("Not Working"); + CSenseWorkingMsg workingMsg4("Not Working"); + + if (_eye1 && _eye2) { + workingMsg1._value = _visionCentre ? "Working" : "Random"; + } + if (_ear1 && _ear2) { + workingMsg2._value = _auditoryCentre ? "Working" : "Random"; + } + if (_nose) { + workingMsg4._value = _olfactoryCentre ? "Working" : "Random"; + } + if (_mouth) { + workingMsg3._value = _speechCentre ? "Working" : "Random"; + } + + if (_centralCore && _eye1 && _eye2 && _ear1 && _ear2 && _nose && _mouth + && _speechCentre && _olfactoryCentre && _auditoryCentre) { + playSound("z#47.wav"); + + CActMsg actMsg("Woken"); + actMsg.execute("MouthSlot"); + actMsg.execute("VisionCentreSlot"); + setPassengerClass(4); + + addTimer(1000); + } else { + workingMsg1.execute("Eye1Slot"); + workingMsg1.execute("Eye2Slot"); + workingMsg2.execute("Ear1Slot"); + workingMsg2.execute("Ear2Slot"); + workingMsg3.execute("MouthSlot"); + workingMsg4.execute("NoseSlot"); + } + } + + return true; +} + +bool CTitania::EnterViewMsg(CEnterViewMsg *msg) { + if (_showIntro) { + _showIntro = false; + disableMouse(); + petHide(); + + CSetFrameMsg frameMsg; + frameMsg._frameNumber = 25; + frameMsg.execute("Bomb"); + playCutscene(0, 52); + + setVisible(false); + CActMsg actMsg("TitaniaSpeech"); + actMsg.execute("TitaniaSpeech"); + } + + return true; +} + +bool CTitania::TimerMsg(CTimerMsg *msg) { + changeView("Titania.Node 18.N", ""); + startTalking("PerchedParrot", 80022); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/titania.h b/engines/titanic/npcs/titania.h new file mode 100644 index 0000000000..61f8c86018 --- /dev/null +++ b/engines/titanic/npcs/titania.h @@ -0,0 +1,67 @@ +/* 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_TITANIA_H +#define TITANIC_TITANIA_H + +#include "titanic/npcs/character.h" + +namespace Titanic { + +class CTitania : public CCharacter { + DECLARE_MESSAGE_MAP; + bool AddHeadPieceMsg(CAddHeadPieceMsg *msg); + bool TakeHeadPieceMsg(CTakeHeadPieceMsg *msg); + bool ActMsg(CActMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool TimerMsg(CTimerMsg *msg); +private: + bool _speechCentre; + bool _olfactoryCentre; + bool _auditoryCentre; + bool _centralCore; + bool _visionCentre; + bool _eye1; + bool _eye2; + bool _ear1; + bool _ear2; + bool _nose; + bool _mouth; + bool _showIntro; +public: + CLASSDEF; + CTitania(); + + /** + * 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_TITANIA_H */ diff --git a/engines/titanic/npcs/true_talk_npc.cpp b/engines/titanic/npcs/true_talk_npc.cpp new file mode 100644 index 0000000000..5ba68aafbe --- /dev/null +++ b/engines/titanic/npcs/true_talk_npc.cpp @@ -0,0 +1,225 @@ +/* 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/npcs/true_talk_npc.h" +#include "titanic/core/view_item.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CTrueTalkNPC, CCharacter) + ON_MESSAGE(TextInputMsg) + ON_MESSAGE(TrueTalkGetAssetDetailsMsg) + ON_MESSAGE(DismissBotMsg) + ON_MESSAGE(TrueTalkNotifySpeechStartedMsg) + ON_MESSAGE(TrueTalkNotifySpeechEndedMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(NPCQueueIdleAnimMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(NPCPlayAnimationMsg) +END_MESSAGE_MAP() + +CTrueTalkNPC::CTrueTalkNPC() : _assetName("z451.dlg"), + _assetNumber(0x11170), _fieldE4(0), _npcFlags(0), _soundId(0), _fieldF0(0), + _fieldF4(0), _fieldF8(0), _speechTimerId(0), _field100(0), _field104(0) { +} + +void CTrueTalkNPC::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_assetNumber, indent); + file->writeQuotedLine(_assetName, indent); + file->writeNumberLine(_fieldE4, indent); + file->writeNumberLine(_npcFlags, indent); + file->writeNumberLine(_soundId, indent); + file->writeNumberLine(_fieldF0, indent); + file->writeNumberLine(_fieldF4, indent); + file->writeNumberLine(_fieldF8, indent); + file->writeNumberLine(_speechTimerId, indent); + file->writeNumberLine(_field100, indent); + file->writeNumberLine(_field104, indent); + + CCharacter::save(file, indent); +} + +void CTrueTalkNPC::load(SimpleFile *file) { + file->readNumber(); + _assetNumber = file->readNumber(); + _assetName = file->readString(); + _fieldE4 = file->readNumber(); + _npcFlags = file->readNumber(); + _soundId = file->readNumber(); + _fieldF0 = file->readNumber(); + _fieldF4 = file->readNumber(); + _fieldF8 = file->readNumber(); + _speechTimerId = file->readNumber(); + _field100 = file->readNumber(); + _field104 = file->readNumber(); + + CCharacter::load(file); +} + +bool CTrueTalkNPC::TextInputMsg(CTextInputMsg *msg) { + processInput(msg, _field104 ? findView() : nullptr); + return true; +} + +bool CTrueTalkNPC::TrueTalkGetAssetDetailsMsg(CTrueTalkGetAssetDetailsMsg *msg) { + msg->_filename = _assetName; + msg->_numValue = _assetNumber; + return true; +} + +bool CTrueTalkNPC::DismissBotMsg(CDismissBotMsg *msg) { + performAction(1, 0); + return true; +} + +bool CTrueTalkNPC::TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg) { + _npcFlags |= NPCFLAG_SPEAKING; + ++_field100; + + if (!(_npcFlags & NPCFLAG_8)) { + if (_speechTimerId) + stopTimer(_speechTimerId); + + _soundId = msg->_soundId; + _fieldF0 = getTicksCount(); + + if (hasActiveMovie() || (_npcFlags & NPCFLAG_2)) { + _npcFlags &= ~NPCFLAG_2; + stopMovie(); + + CNPCPlayTalkingAnimationMsg msg1(_soundId, 0, 0); + msg1.execute(this); + + if (msg1._names) { + CNPCPlayAnimationMsg msg2(msg1._names, msg1._value1); + msg2.execute(this); + } + } + } + + return true; +} + +bool CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg) { + _npcFlags &= ~NPCFLAG_SPEAKING; + --_field100; + _soundId = 0; + + if (!(_npcFlags & NPCFLAG_8)) { + CNPCPlayTalkingAnimationMsg msg1(0, 2, 0); + msg1.execute(this); + CNPCQueueIdleAnimMsg msg2; + msg2.execute(this); + } + + return true; +} + +bool CTrueTalkNPC::MovieEndMsg(CMovieEndMsg *msg) { + if (_npcFlags & NPCFLAG_2) { + _npcFlags &= ~NPCFLAG_2; + CNPCQueueIdleAnimMsg idleMsg; + idleMsg.execute(this); + return true; + } else if (!(_npcFlags & NPCFLAG_SPEAKING)) { + return false; + } + + int diff = getTicksCount() - _fieldF0; + int ticks = MAX((int)_soundId - diff, 0); + CNPCPlayTalkingAnimationMsg msg1(ticks, ticks > 1000 ? 2 : 1, 0); + msg1.execute(this); + + if (msg1._names) { + CNPCPlayAnimationMsg msg2(msg1._names, msg1._value1); + msg2.execute(this); + } + + return true; +} + +bool CTrueTalkNPC::NPCQueueIdleAnimMsg(CNPCQueueIdleAnimMsg *msg) { + int rndVal = getRandomNumber(_fieldF8 - 1) - (_fieldF8 / 2); + _speechTimerId = startAnimTimer("NPCIdleAnim", _fieldF4 + rndVal, 0); + + return true; +} + +bool CTrueTalkNPC::TimerMsg(CTimerMsg *msg) { + if (_npcFlags & NPCFLAG_4) { + if (_field100 > 0) + return false; + + CNPCPlayIdleAnimationMsg idleMsg; + if (idleMsg.execute(this)) { + if (idleMsg._names) { + CNPCPlayAnimationMsg animMsg(idleMsg._names, 0); + animMsg.execute(this); + } + + _npcFlags &= ~NPCFLAG_2; + } + } + + _speechTimerId = 0; + return true; +} + +bool CTrueTalkNPC::NPCPlayAnimationMsg(CNPCPlayAnimationMsg *msg) { + warning("CTrueTalkNPC::NPCPlayAnimationMsg"); + return true; +} + +void CTrueTalkNPC::processInput(CTextInputMsg *msg, CViewItem *view) { + CTrueTalkManager *talkManager = getGameManager()->getTalkManager(); + if (talkManager) + talkManager->processInput(this, msg, view); +} + +void CTrueTalkNPC::setView(CViewItem *view) { + CTrueTalkManager *talkManager = getGameManager()->getTalkManager(); + if (talkManager) + talkManager->start3(this, view); +} + +void CTrueTalkNPC::startTalker(CViewItem *view) { + CGameManager *gameManager = getGameManager(); + if (gameManager) + gameManager->getTalkManager()->start4(this, view); +} + +void CTrueTalkNPC::performAction(bool startTalkingFlag, CViewItem *destView) { + CPetControl *pet = getPetControl(); + if (pet) + pet->resetActiveNPC(); + + if (startTalkingFlag) + startTalker(destView); + + if (pet) + pet->convResetNPC(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/npcs/true_talk_npc.h b/engines/titanic/npcs/true_talk_npc.h new file mode 100644 index 0000000000..2eea9bdf3d --- /dev/null +++ b/engines/titanic/npcs/true_talk_npc.h @@ -0,0 +1,102 @@ +/* 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_TRUE_TALK_NPC_H +#define TITANIC_TRUE_TALK_NPC_H + +#include "titanic/npcs/character.h" +#include "titanic/messages/messages.h" +#include "titanic/true_talk/tt_talker.h" + +namespace Titanic { + +enum NpcFlag { + NPCFLAG_SPEAKING = 1, NPCFLAG_2 = 2, NPCFLAG_4 = 4, NPCFLAG_8 = 8, + NPCFLAG_10000 = 0x10000, NPCFLAG_20000 = 0x20000, + NPCFLAG_40000 = 0x40000, NPCFLAG_80000 = 0x80000, + NPCFLAG_100000 = 0x100000, NPCFLAG_200000 = 0x200000, + NPCFLAG_400000 = 0x400000, NPCFLAG_800000 = 0x800000, + NPCFLAG_1000000 = 0x1000000, NPCFLAG_2000000 = 0x2000000, + NPCFLAG_4000000 = 0x4000000, NPCFLAG_8000000 = 0x8000000 +}; + +class CViewItem; + +class CTrueTalkNPC : public CCharacter { + DECLARE_MESSAGE_MAP; + bool TextInputMsg(CTextInputMsg *msg); + bool TrueTalkGetAssetDetailsMsg(CTrueTalkGetAssetDetailsMsg *msg); + bool DismissBotMsg(CDismissBotMsg *msg); + bool TrueTalkNotifySpeechStartedMsg(CTrueTalkNotifySpeechStartedMsg *msg); + bool TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool NPCQueueIdleAnimMsg(CNPCQueueIdleAnimMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool NPCPlayAnimationMsg(CNPCPlayAnimationMsg *msg); +protected: + int _assetNumber; + CString _assetName; + int _fieldE4; + uint _npcFlags; + uint _soundId; + int _fieldF0; + int _fieldF4; + int _fieldF8; + int _speechTimerId; + int _field104; +protected: + void processInput(CTextInputMsg *msg, CViewItem *view); + + /** + * Perform an action + */ + void performAction(bool startTalking, CViewItem *view = nullptr); +public: + int _field100; +public: + CLASSDEF; + CTrueTalkNPC(); + + /** + * 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); + + /** + * Set the view for the NPC + */ + void setView(CViewItem *view); + + /** + * Start the talker in the given view + */ + void startTalker(CViewItem *view); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TRUE_TALK_NPC_H */ 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 */ diff --git a/engines/titanic/room_flags.cpp b/engines/titanic/room_flags.cpp new file mode 100644 index 0000000000..9be8ea3d33 --- /dev/null +++ b/engines/titanic/room_flags.cpp @@ -0,0 +1,527 @@ +/* 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/room_flags.h" +#include "titanic/titanic.h" + +namespace Titanic { + +#define ELEVATOR_SHIFT 18 +#define ELEVATOR_MASK 3 +#define PASSENGER_CLASS_SHIFT 16 +#define PASSENGER_CLASS_MASK 3 +#define FLOOR_SHIFT 8 +#define FLOOR_MASK 0xFF +#define ROOM_SHIFT 1 +#define ROOM_MASK 0x7F + +struct TransportFlagsEntry { + const char *const _roomName; + uint _roomFlags; +}; +struct SuccUBusFlagsEntry { + const char *const _roomName; + uint _roomFlags; + uint _succubusNum; +}; + +#define TRANSPORT_ROOMS_SIZE 6 +const TransportFlagsEntry TRANSPORT_ROOMS[TRANSPORT_ROOMS_SIZE] = { + { "TopOfWell", 0xDF4D1 }, + { "Pellerator", 0xC95E9 }, + { "Dome", 0xAD171 }, + { "Lift", 0x96E45 }, + { "SGTLeisure", 0x5D3AD }, + { "ServiceElevator", 0x68797 } +}; + +#define SUCCUBUS_ROOMS_SIZE 17 +const SuccUBusFlagsEntry SUCCUBUS_ROOMS[SUCCUBUS_ROOMS_SIZE] = { + { "ParrotLobby", 0x1D0D9, 3 }, + { "SculptureChamber", 0x465FB, 2 }, + { "Bar", 0x0B3D97, 2 }, + { "EmbLobby", 0x0CC971, 3 }, + { "MoonEmbLobby", 0x0CC971, 3 }, + { "MusicRoom", 0x0F34DB, 2 }, + { "MusicRoomLobby", 0x0F34DB, 2 }, + { "Titania", 0x8A397, 3 }, + { "BottomOfWell", 0x59FAD, 3 }, + { "Arboretum", 0x4D6AF, 1 }, + { "PromenadeDeck", 0x79C45, 2 }, + { "1stClassRestaurant", 0x896B9, 1 }, + { "CreatorsChamber", 0x2F86D, 2 }, + { "CreatorsChamberOn", 0x2F86D, 2 }, + { "BilgeRoom", 0x3D94B, 3 }, + { "BilgeRoomWith", 0x3D94B, 3 }, + { "Bridge", 0x39FCB, 3 } +}; + +int CRoomFlags::getConditionally() const { + if (getRoomArea() != 5 || getRoomCategory() != 5) + return _data; + else + return 5; +} + +bool CRoomFlags::isTransportRoom() const { + for (int idx = 0; idx < TRANSPORT_ROOMS_SIZE; ++idx) { + if (TRANSPORT_ROOMS[idx]._roomFlags == _data) + return true; + } + + return false; +} + +int CRoomFlags::getRoomCategory() const { + if (getRoomNum() == 0) + return false; + + CRoomFlags tempFlags = _data; + tempFlags.setRoomBits(1); + return tempFlags.getRoomArea() != 5; +} + +int CRoomFlags::getRoomArea() const { + if (isSuccUBusRoomFlags()) + return 4; + + if (!getBit0()) { + uint v3 = getFloorNum(); + if (v3 <= 38) { + uint v4 = getRoomNum(); + if (v4 <= 18) { + uint v6 = getElevatorNum(); + + if (v6 >= 1 && v6 <= 4) { + uint v7 = getPassengerClassNum() - 1; + if (v7) { + uint v8 = v7 - 1; + if (v8) { + if (v8 == 1 && is28To38(v3) && (v6 & 1) && v4 >= 1) + return 3; + } else if (is20To27(v3)) { + if (v6 & 1) { + if (v4 >= 1 && v4 <= 3) + return 2; + } else if (v4 >= 1 && v4 <= 4) { + return 2; + } + } + } else if (is2To19(v3) && v4 >= 1 && v4 <= 3) { + return 1; + } + } + } + } + } + + return 5; +} + +CString CRoomFlags::getRoomDesc() const { + switch (getRoomArea()) { + case 1: + case 2: + case 3: { + CString result = getPassengerClassDesc(); + result += ", "; + result += getFloorDesc(); + result += ", "; + result += getElevatorDesc(); + result += ", "; + result += getRoomDesc(); + return result; + } + + case 4: + if (isTransportRoom()) { + switch (_data) { + case 0x68797: + return "The Service Elevator"; + case 0x5D3AD: + return "The Super Galactic Leisure Lounge"; + case 0x96E45: + return "The Elevator"; + case 0xAD171: + return "The Dome"; + case 0xC95E9: + return "The Pellerator"; + case 0xDF4D1: + return "The Top of the Well"; + default: + break; + } + } + + if (getRoomCategory() == 0) { + return "Nowhere you're likely to want to go."; + } else { + CString result = getPassengerClassDesc(); + result += ", "; + result += getFloorDesc(); + return result; + } + break; + + case 5: + switch (_data) { + case 0x1D0D9: + return "The Parrot Lobby"; + case 0x2F86D: + return "The Creators' Chamber"; + case 0x39FCB: + return "The Bridge"; + case 0x3D94B: + return "The Bilge Room"; + case 0x465FB: + return "The Sculpture Chamber"; + case 0x4D6AF: + return "The Arboretum"; + case 0x59FAD: + return "The Bottom of the Well"; + case 0x79C45: + return "The Promenade Deck"; + case 0x896B9: + return "The 1st class restaurant"; + case 0x8A397: + return "Titania's Room"; + case 0xB3D97: + return "The Bar"; + case 0xCC971: + return "The Embarkation Lobby"; + case 0xF34DB: + return "The Music Room"; + default: + break; + } + return "Unknown Room"; + + default: + break; + } + + return "Unknown Room"; +} + +void CRoomFlags::setElevatorBits(uint val) { + _data &= ~(ELEVATOR_MASK << ELEVATOR_SHIFT); + _data |= (val & ELEVATOR_MASK) << ELEVATOR_SHIFT; +} + +uint CRoomFlags::getElevatorBits() const { + return (_data >> ELEVATOR_SHIFT) & ELEVATOR_MASK; +} + +void CRoomFlags::setPassengerClassBits(uint val) { + _data &= ~(PASSENGER_CLASS_MASK << PASSENGER_CLASS_SHIFT); + _data |= (val & PASSENGER_CLASS_MASK) << PASSENGER_CLASS_SHIFT; +} + +uint CRoomFlags::getPassengerClassBits() const { + return (_data >> PASSENGER_CLASS_SHIFT) & PASSENGER_CLASS_MASK; +} + +CString CRoomFlags::getPassengerClassDesc() const { + int classNum = getPassengerClassNum(); + + switch (classNum) { + case 1: + return "1st class"; + case 2: + return "2nd class"; + case 3: + return "SGT class"; + default: + return "no class"; + } +} + +void CRoomFlags::setFloorBits(uint val) { + _data &= ~(FLOOR_MASK << FLOOR_SHIFT); + _data |= (val & FLOOR_MASK) << FLOOR_SHIFT; +} + +uint CRoomFlags::getFloorBits() const { + return (_data >> FLOOR_SHIFT) & FLOOR_MASK; +} + +uint CRoomFlags::decodeFloorBits(uint bits) const { + int base = 0; + int offset = bits & 0xF; + + switch ((bits >> 4) & 0xF) { + case 1: + case 2: + case 3: + base = 40; + break; + case 4: + base = 10; + break; + case 5: + base = 20; + break; + case 6: + base = 30; + break; + default: + break; + } + + return offset >= 10 ? 0 : base + offset; +} + +void CRoomFlags::setFloorNum(uint floorNum) { + uint base = 0; + + switch (floorNum / 10) { + case 0: + base = 0x90; + break; + case 1: + base = 0xD0; + case 2: + base = 0xE0; + case 3: + base = 0xF0; + break; + default: + break; + } + + setFloorBits(base | (floorNum % 10)); +} + +uint CRoomFlags::getFloorNum() const { + return decodeFloorBits(getFloorBits()); +} + +void CRoomFlags::setRoomBits(uint roomBits) { + _data &= ~(ROOM_MASK << ROOM_SHIFT); + _data |= (roomBits & ROOM_MASK) << ROOM_SHIFT; +} + +uint CRoomFlags::getRoomBits() const { + return (_data >> ROOM_SHIFT) & ROOM_MASK; +} + +bool CRoomFlags::isSuccUBusRoomFlags() const { + for (int idx = 0; idx < SUCCUBUS_ROOMS_SIZE; ++idx) { + if (SUCCUBUS_ROOMS[idx]._roomFlags == _data) + return true; + } + + return false; +} + +bool CRoomFlags::getBit0() const { + return _data & 1; +} + +uint CRoomFlags::getSpecialRoomFlags(const CString &roomName) { + for (int idx = 0; idx < SUCCUBUS_ROOMS_SIZE; ++idx) { + if (roomName == SUCCUBUS_ROOMS[idx]._roomName) + return SUCCUBUS_ROOMS[idx]._roomFlags; + } + + for (int idx = 0; idx < TRANSPORT_ROOMS_SIZE; ++idx) { + if (roomName == TRANSPORT_ROOMS[idx]._roomName) + return TRANSPORT_ROOMS[idx]._roomFlags; + } + + return 0; +} + +uint CRoomFlags::getSuccUBusNum(const CString &roomName) const { + for (int idx = 0; idx < SUCCUBUS_ROOMS_SIZE; ++idx) { + if (roomName == SUCCUBUS_ROOMS[idx]._roomName) + return SUCCUBUS_ROOMS[idx]._succubusNum; + } + + return 0; +} + +CString CRoomFlags::getSuccUBusRoomName() const { + for (int idx = 0; idx < SUCCUBUS_ROOMS_SIZE; ++idx) { + if (SUCCUBUS_ROOMS[idx]._roomFlags == _data) + return SUCCUBUS_ROOMS[idx]._roomName; + } + + return CString(); +} + +void CRoomFlags::changeLocation(int action) { + uint floorNum = getFloorNum(); + uint roomNum = getRoomNum(); + uint elevatorNum = getElevatorNum(); + uint classNum = getPassengerClassNum(); + uint v10, v11, v12, v13; + + switch (classNum) { + case 1: + v10 = 2; + v11 = 19; + v12 = 1; + v13 = 3; + break; + + case 2: + v10 = 20; + v11 = 27; + v12 = 1; + v13 = (elevatorNum & 1) ? 3 : 4; + break; + + case 3: + v10 = 28; + v11 = 38; + v12 = 1; + v13 = 18; + break; + + default: + v10 = 0; + v11 = 0; + v12 = 0; + v13 = 0; + break; + } + + // Perform action to change room or floor + switch (action) { + case 1: + if (--roomNum < v12) + roomNum = v12; + break; + + case 2: + if (++roomNum > v13) + roomNum = v13; + break; + + case 3: + if (--floorNum < v10) + floorNum = v10; + break; + + case 4: + if (++floorNum > v11) + floorNum = v11; + } + + // Set new floor and room + setFloorNum(floorNum); + setRoomBits(roomNum); +} + +bool CRoomFlags::compareClassElevator(uint flags1, uint flags2) { + CRoomFlags f1(flags1); + CRoomFlags f2(flags2); + + if (f1.getFloorNum() != f2.getFloorNum()) + return false; + + uint elev1 = f1.getElevatorNum(); + uint elev2 = f2.getElevatorNum(); + uint class1 = f1.getPassengerClassNum(); + uint class2 = f2.getPassengerClassNum(); + + if (class1 > 0 && class1 < 3) { + if (elev1 == 2) + elev1 = 1; + else if (elev1 == 4) + elev1 = 3; + } + if (class2 > 0 && class2 < 3) { + if (elev2 == 2) + elev2 = 1; + else if (elev2 == 4) + elev2 = 3; + } + + return elev1 == elev2; +} + +bool CRoomFlags::compareLocation(uint flags1, uint flags2) { + CRoomFlags f1(flags1); + CRoomFlags f2(flags2); + + return f1.getElevatorNum() == f2.getElevatorBits() && + f1.getFloorNum() == f2.getFloorNum() && + f1.getRoomNum() == f2.getRoomNum(); +} + +bool CRoomFlags::isTitania(uint flags1, uint flags2) { + return flags2 == 0x8A397; +} + +void CRoomFlags::setRandomLocation(int classNum, bool flag) { + uint minRoom, elevNum, maxRoom, maxFloor, minFloor; + + do { + switch (classNum) { + case 1: + minFloor = 2; + maxFloor = 19; + minRoom = 1; + maxRoom = 3; + elevNum = g_vm->getRandomNumber(flag ? 2 : 3); + break; + + case 2: + minFloor = 20; + maxFloor = 27; + elevNum = g_vm->getRandomNumber(flag ? 2 : 3); + minRoom = 1; + maxRoom = ((elevNum - 1) & 1) ? 3 : 4; + break; + + case 3: + minRoom = 1; + minFloor = 28; + maxFloor = 38; + maxRoom = 18; + elevNum = g_vm->getRandomNumber(1); + if (elevNum == 1) + elevNum = 2; + break; + + default: + return; + } + + uint floorNum = minFloor + g_vm->getRandomNumber(maxFloor - minFloor); + uint roomNum = minRoom + g_vm->getRandomNumber(maxRoom - minRoom); + setElevatorBits(elevNum); + setRoomBits(roomNum); + setFloorNum(floorNum); + } while (_data == 0x59706); +} + +int CRoomFlags::whatPassengerClass(int floorNum) { + if (is2To19(floorNum)) + return 1; + + return is20To27(floorNum) ? 2 : 3; +} + +} // End of namespace Titanic diff --git a/engines/titanic/room_flags.h b/engines/titanic/room_flags.h new file mode 100644 index 0000000000..f0f90f80d1 --- /dev/null +++ b/engines/titanic/room_flags.h @@ -0,0 +1,230 @@ +/* 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_ROOM_FLAGS_H +#define TITANIC_ROOM_FLAGS_H + +#include "titanic/support/string.h" + +namespace Titanic { + +class CRoomFlags { +private: + uint _data; +private: + int getConditionally() const; + + /** + * Returns true if the current flags appear in the + * list of transport rooms + */ + bool isTransportRoom() const; + + int getRoomCategory() const; + + int getRoomArea() const; + + /** + * Set the bits for the elevator number + */ + void setElevatorBits(uint val); + + /** + * Set the bits for the floor number + */ + void setFloorBits(uint val); + + /** + * Translates bits for floor into a floor number + */ + uint decodeFloorBits(uint bits) const; + + static bool is2To19(uint v) { return v >= 2 && v <= 19; } + static bool is20To27(uint v) { return v >= 20 && v <= 27; } + static bool is28To38(uint v) { return v >= 28 && v <= 38; } +public: + /** + * Compares the current flags against the specified flags + * for a matching elevator, floor, and room + */ + static bool compareLocation(uint flags1, uint flags2); + + /** + * Compares two room flags together + */ + static bool compareClassElevator(uint flags1, uint flags2); + + /** + * Returns true if the current flags is for Titania's room + */ + static bool isTitania(uint flags1, uint flags2); +public: + CRoomFlags() : _data(0) {} + CRoomFlags(uint data) : _data(data) {} + operator uint() { return _data; } + + /** + * Set the flags value + */ + void set(uint data) { _data = data; } + + /** + * Get the flags value + */ + uint get() const { return _data; } + + /** + * Gets the special flags for a transport or succubus room + */ + static uint getSpecialRoomFlags(const CString &roomName); + + /** + * Returns true if the current flags are in the succubus list + */ + bool isSuccUBusRoomFlags() const; + + /** + * Get a description for the room + */ + CString getRoomDesc() const; + + /** + * Get the bits for the elevator number + */ + uint getElevatorBits() const; + + /** + * Set the elevator number + */ + void setElevatorNum(uint val) { setElevatorBits(val - 1); } + + /** + * Get the elevator number + */ + uint getElevatorNum() const { return getElevatorBits() + 1; } + + /** + * Get a description for the elevator number + */ + CString getElevatorDesc() const { + return CString::format("Elevator %d", getElevatorNum()); + } + + /** + * Gets the bits for the passenger class + */ + uint getPassengerClassBits() const; + + /** + * Set the bits for the passenger class + */ + void setPassengerClassBits(uint val); + + /** + * Gets the passenger class number + */ + uint getPassengerClassNum() const { return getPassengerClassBits(); } + + /** + * Get a description for the passenger class + */ + CString getPassengerClassDesc() const; + + /** + * Gets the bits for the floor number + */ + uint getFloorBits() const; + + /** + * Sets the floor number + */ + void setFloorNum(uint floorNum); + + /** + * Gets the floor number + */ + uint getFloorNum() const; + + /** + * Get a description for the floor number + */ + CString getFloorDesc() const { + return CString::format("Floor %d", getFloorNum()); + } + + /** + * Sets the bits for the room number + */ + void setRoomBits(uint roomBits); + + /** + * Gets the bits for the room number + */ + uint getRoomBits() const; + + /** + * Gets the room number + */ + uint getRoomNum() const { return getRoomBits(); } + + /** + * Gets a string for the room number + */ + CString getRoomNumDesc() const { + return CString::format("Room %d", getRoomNum()); + } + + bool getBit0() const; + + /** + * Change the passenger class + */ + void changeLocation(int action); + + /** + * Sets a random destination in the flags + */ + void setRandomLocation(int classNum, bool flag); + + /** + * Gets the succubus number associated with a given room + */ + uint getSuccUBusNum(const CString &roomName) const; + + /** + * Gets the succubus room name associated with the current room flags + */ + CString getSuccUBusRoomName() const; + + /** + * Returns what passenger class a particular floor number belongs to + */ + static int whatPassengerClass(int floorNum); + + bool not5() const { return getConditionally() != 5; } + + bool is59706() const { return _data == 0x59706; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_ROOM_FLAGS_H */ diff --git a/engines/titanic/sound/auto_music_player.cpp b/engines/titanic/sound/auto_music_player.cpp new file mode 100644 index 0000000000..ce20c33765 --- /dev/null +++ b/engines/titanic/sound/auto_music_player.cpp @@ -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. + * + */ + +#include "titanic/sound/auto_music_player.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAutoMusicPlayer, CAutoMusicPlayerBase) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) +END_MESSAGE_MAP() + +CAutoMusicPlayer::CAutoMusicPlayer() : CAutoMusicPlayerBase() { +} + +void CAutoMusicPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_leaveRoomSound, indent); + + CAutoMusicPlayerBase::save(file, indent); +} + +void CAutoMusicPlayer::load(SimpleFile *file) { + file->readNumber(); + _leaveRoomSound = file->readString(); + + CAutoMusicPlayerBase::load(file); +} + +bool CAutoMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) { + if (!_isRepeated) { + CRoomItem *room = findRoom(); + if (msg->_newRoom == room) + addTimer(2000); + } + + return true; +} + +bool CAutoMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (_isRepeated) { + CRoomItem *room = findRoom(); + if (msg->_oldRoom == room) { + CChangeMusicMsg changeMsg; + changeMsg._flags = 1; + changeMsg.execute(this); + } + } + + if (!_leaveRoomSound.empty()) + playSound(_leaveRoomSound); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/auto_music_player.h b/engines/titanic/sound/auto_music_player.h new file mode 100644 index 0000000000..722aa9cd7f --- /dev/null +++ b/engines/titanic/sound/auto_music_player.h @@ -0,0 +1,54 @@ +/* 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_AUTO_MUSIC_PLAYER_H +#define TITANIC_AUTO_MUSIC_PLAYER_H + +#include "titanic/sound/auto_music_player_base.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CAutoMusicPlayer : public CAutoMusicPlayerBase { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); +private: + CString _leaveRoomSound; +public: + CLASSDEF; + CAutoMusicPlayer(); + + /** + * 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_AUTO_MUSIC_PLAYER_H */ diff --git a/engines/titanic/sound/auto_music_player_base.cpp b/engines/titanic/sound/auto_music_player_base.cpp new file mode 100644 index 0000000000..ad8b848c03 --- /dev/null +++ b/engines/titanic/sound/auto_music_player_base.cpp @@ -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. + * + */ + +#include "titanic/sound/auto_music_player_base.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAutoMusicPlayerBase, CGameObject) + ON_MESSAGE(StatusChangeMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(LoadSuccessMsg) + ON_MESSAGE(ChangeMusicMsg) +END_MESSAGE_MAP() + +CAutoMusicPlayerBase::CAutoMusicPlayerBase() : CGameObject(), + _initialMute(true), _isRepeated(false), _volumeMode(-1), _transition(1) { +} +void CAutoMusicPlayerBase::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_filename, indent); + file->writeNumberLine(_initialMute, indent); + file->writeNumberLine(_isRepeated, indent); + file->writeNumberLine(_volumeMode, indent); + file->writeNumberLine(_transition, indent); + + CGameObject::save(file, indent); +} + +void CAutoMusicPlayerBase::load(SimpleFile *file) { + file->readNumber(); + _filename = file->readString(); + _initialMute = file->readNumber(); + _isRepeated = file->readNumber(); + _volumeMode = file->readNumber(); + _transition = file->readNumber(); + + CGameObject::load(file); +} + +bool CAutoMusicPlayerBase::StatusChangeMsg(CStatusChangeMsg *msg) { + return true; +} + +bool CAutoMusicPlayerBase::TimerMsg(CTimerMsg *msg) { + CChangeMusicMsg musicMsg; + musicMsg._flags = 2; + musicMsg.execute(this); + + return true; +} + +bool CAutoMusicPlayerBase::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_isRepeated) + playGlobalSound(_filename, _volumeMode, _initialMute, true, 0); + + return true; +} + +bool CAutoMusicPlayerBase::ChangeMusicMsg(CChangeMusicMsg *msg) { + if (_isRepeated && msg->_flags == 1) { + _isRepeated = false; + stopGlobalSound(_transition, -1); + } + + if (!msg->_filename.empty()) { + _filename = msg->_filename; + + if (_isRepeated) { + stopGlobalSound(_transition, -1); + playGlobalSound(_filename, _volumeMode, _initialMute, true, 0); + } + } + + if (_isRepeated && msg->_flags == 2) { + _isRepeated = true; + playGlobalSound(_filename, _volumeMode, _initialMute, true, 0); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/auto_music_player_base.h b/engines/titanic/sound/auto_music_player_base.h new file mode 100644 index 0000000000..0623258887 --- /dev/null +++ b/engines/titanic/sound/auto_music_player_base.h @@ -0,0 +1,59 @@ +/* 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_AUTO_MUSIC_PLAYER_BASE_H +#define TITANIC_AUTO_MUSIC_PLAYER_BASE_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CAutoMusicPlayerBase : public CGameObject { + DECLARE_MESSAGE_MAP; + bool StatusChangeMsg(CStatusChangeMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); + bool ChangeMusicMsg(CChangeMusicMsg *msg); +protected: + CString _filename; + bool _initialMute; + bool _isRepeated; + int _volumeMode; + int _transition; +public: + CLASSDEF; + CAutoMusicPlayerBase(); + + /** + * 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_AUTO_MUSIC_PLAYER_BASE_H */ diff --git a/engines/titanic/sound/auto_sound_player.cpp b/engines/titanic/sound/auto_sound_player.cpp new file mode 100644 index 0000000000..8267d65037 --- /dev/null +++ b/engines/titanic/sound/auto_sound_player.cpp @@ -0,0 +1,134 @@ +/* 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/sound/auto_sound_player.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAutoSoundPlayer, CGameObject) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) + ON_MESSAGE(SignalObject) + ON_MESSAGE(SetVolumeMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +CAutoSoundPlayer::CAutoSoundPlayer() : CGameObject(), + _fieldBC(0), _volume(70), _fieldD0(0), _repeated(false), _soundHandle(-1), + _stopSeconds(0), _startSeconds(-1), _active(false), _fieldE8(0) { +} + +void CAutoSoundPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_fieldBC, indent); + file->writeQuotedLine(_filename, indent); + file->writeNumberLine(_volume, indent); + file->writeNumberLine(_fieldD0, indent); + file->writeNumberLine(_repeated, indent); + file->writeNumberLine(_soundHandle, indent); + file->writeNumberLine(_stopSeconds, indent); + file->writeNumberLine(_startSeconds, indent); + file->writeNumberLine(_active, indent); + file->writeNumberLine(_fieldE8, indent); + + CGameObject::save(file, indent); +} + +void CAutoSoundPlayer::load(SimpleFile *file) { + file->readNumber(); + _fieldBC = file->readNumber(); + _filename = file->readString(); + _volume = file->readNumber(); + _fieldD0 = file->readNumber(); + _repeated = file->readNumber(); + _soundHandle = file->readNumber(); + _stopSeconds = file->readNumber(); + _startSeconds = file->readNumber(); + _active = file->readNumber(); + _fieldE8 = file->readNumber(); + + CGameObject::load(file); +} + +bool CAutoSoundPlayer::TurnOn(CTurnOn *msg) { + if (_soundHandle == -1) { + CProximity prox; + prox._fieldC = _fieldD0; + prox._repeated = _repeated; + if (_fieldE8) + prox._positioningMode = POSMODE_VECTOR; + prox._channelVolume = (_startSeconds == -1) ? _volume : 0; + + _soundHandle = playSound(_filename, prox); + if (_startSeconds != -1) + setSoundVolume(_soundHandle, _volume, _startSeconds); + + _active = true; + } + + return true; +} + +bool CAutoSoundPlayer::TurnOff(CTurnOff *msg) { + if (_soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, _stopSeconds); + + _soundHandle = -1; + _active = false; + } + + return true; +} + +bool CAutoSoundPlayer::SignalObject(CSignalObject *msg) { + if (_soundHandle != -1) { + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle, msg->_numValue); + + _soundHandle = -1; + _active = false; + } + + return true; +} + +bool CAutoSoundPlayer::SetVolumeMsg(CSetVolumeMsg *msg) { + if (_soundHandle != -1 && isSoundActive(_soundHandle)) + setSoundVolume(_soundHandle, msg->_volume, msg->_secondsTransition); + + return true; +} + +bool CAutoSoundPlayer::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_active) { + _soundHandle = -1; + _active = false; + + CTurnOn onMsg; + onMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/auto_sound_player.h b/engines/titanic/sound/auto_sound_player.h new file mode 100644 index 0000000000..c8f1d3480e --- /dev/null +++ b/engines/titanic/sound/auto_sound_player.h @@ -0,0 +1,65 @@ +/* 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_AUTO_SOUND_PLAYER_H +#define TITANIC_AUTO_SOUND_PLAYER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CAutoSoundPlayer : public CGameObject { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); + bool SignalObject(CSignalObject *msg); + bool SetVolumeMsg(CSetVolumeMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +public: + int _fieldBC; + CString _filename; + int _volume; + int _fieldD0; + bool _repeated; + int _soundHandle; + int _stopSeconds; + int _startSeconds; + bool _active; + int _fieldE8; +public: + CLASSDEF; + CAutoSoundPlayer(); + + /** + * 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_AUTO_SOUND_PLAYER_H */ diff --git a/engines/titanic/sound/auto_sound_player_adsr.cpp b/engines/titanic/sound/auto_sound_player_adsr.cpp new file mode 100644 index 0000000000..f9f045759b --- /dev/null +++ b/engines/titanic/sound/auto_sound_player_adsr.cpp @@ -0,0 +1,79 @@ +/* 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/sound/auto_sound_player_adsr.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CAutoSoundPlayerADSR, CAutoSoundPlayer) + ON_MESSAGE(TurnOn) + ON_MESSAGE(TurnOff) +END_MESSAGE_MAP() + +void CAutoSoundPlayerADSR::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_soundName1, indent); + file->writeQuotedLine(_soundName2, indent); + file->writeQuotedLine(_soundName3, indent); + CAutoSoundPlayer::save(file, indent); +} + +void CAutoSoundPlayerADSR::load(SimpleFile *file) { + file->readNumber(); + _soundName1 = file->readString(); + _soundName2 = file->readString(); + _soundName3 = file->readString(); + CAutoSoundPlayer::load(file); +} + +bool CAutoSoundPlayerADSR::TurnOn(CTurnOn *msg) { + if (_soundHandle == -1) { + if (!_soundName1.empty()) { + _soundHandle = playSound(_soundName1, _volume, _fieldD0); + + if (!_soundName2.empty()) + _soundHandle = queueSound(_soundName2, _soundHandle, _volume, _fieldD0); + + _soundHandle = queueSound(_filename, _soundHandle, _volume, _fieldD0); + _active = true; + } + } + + return true; +} + +bool CAutoSoundPlayerADSR::TurnOff(CTurnOff *msg) { + if (_soundHandle != -1) { + if (!_soundName3.empty()) + queueSound(_soundName3, _soundHandle, _volume, _fieldD0); + + if (isSoundActive(_soundHandle)) + stopSound(_soundHandle); + + _soundHandle = -1; + _active = false; + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/auto_sound_player_adsr.h b/engines/titanic/sound/auto_sound_player_adsr.h new file mode 100644 index 0000000000..9f09636610 --- /dev/null +++ b/engines/titanic/sound/auto_sound_player_adsr.h @@ -0,0 +1,54 @@ +/* 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_AUTO_SOUND_PLAYER_ADSR_H +#define TITANIC_AUTO_SOUND_PLAYER_ADSR_H + +#include "titanic/sound/auto_sound_player.h" + +namespace Titanic { + +class CAutoSoundPlayerADSR : public CAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool TurnOff(CTurnOff *msg); +private: + CString _soundName1; + CString _soundName2; + CString _soundName3; +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_AUTO_SOUND_PLAYER_ADSR_H */ diff --git a/engines/titanic/sound/background_sound_maker.cpp b/engines/titanic/sound/background_sound_maker.cpp new file mode 100644 index 0000000000..58dde02518 --- /dev/null +++ b/engines/titanic/sound/background_sound_maker.cpp @@ -0,0 +1,47 @@ +/* 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/sound/background_sound_maker.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBackgroundSoundMaker, CGameObject) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +void CBackgroundSoundMaker::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + CGameObject::save(file, indent); +} + +void CBackgroundSoundMaker::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + CGameObject::load(file); +} + +bool CBackgroundSoundMaker::FrameMsg(CFrameMsg *msg) { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/background_sound_maker.h b/engines/titanic/sound/background_sound_maker.h new file mode 100644 index 0000000000..94f3b792dc --- /dev/null +++ b/engines/titanic/sound/background_sound_maker.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_BACKGROUND_SOUND_MAKER_H +#define TITANIC_BACKGROUND_SOUND_MAKER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CBackgroundSoundMaker : public CGameObject { + DECLARE_MESSAGE_MAP; + bool FrameMsg(CFrameMsg *msg); +public: + int _value; +public: + CLASSDEF; + CBackgroundSoundMaker() : CGameObject(), _value(0) {} + + /** + * 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_BACKGROUND_SOUND_MAKER_H */ diff --git a/engines/titanic/sound/bird_song.cpp b/engines/titanic/sound/bird_song.cpp new file mode 100644 index 0000000000..53a25e2dbe --- /dev/null +++ b/engines/titanic/sound/bird_song.cpp @@ -0,0 +1,56 @@ +/* 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/sound/bird_song.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CBirdSong, CAutoSoundPlayer) + ON_MESSAGE(TurnOn) + ON_MESSAGE(SignalObject) +END_MESSAGE_MAP() + +void CBirdSong::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_flag, indent); + CRoomAutoSoundPlayer::save(file, indent); +} + +void CBirdSong::load(SimpleFile *file) { + file->readNumber(); + _flag = file->readNumber(); + CRoomAutoSoundPlayer::load(file); +} + +bool CBirdSong::TurnOn(CTurnOn *msg) { + if (!_flag) + CAutoSoundPlayer::TurnOn(msg); + return true; +} + +bool CBirdSong::SignalObject(CSignalObject *msg) { + _flag = true; + CAutoSoundPlayer::SignalObject(msg); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/bird_song.h b/engines/titanic/sound/bird_song.h new file mode 100644 index 0000000000..52af94b180 --- /dev/null +++ b/engines/titanic/sound/bird_song.h @@ -0,0 +1,53 @@ +/* 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_BIRD_SONG_H +#define TITANIC_BIRD_SONG_H + +#include "titanic/sound/room_auto_sound_player.h" + +namespace Titanic { + +class CBirdSong : public CRoomAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool SignalObject(CSignalObject *msg); +public: + bool _flag; +public: + CLASSDEF; + CBirdSong() : CRoomAutoSoundPlayer(), _flag(false) {} + + /** + * 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_BIRD_SONG_H */ diff --git a/engines/titanic/sound/dome_from_top_of_well.cpp b/engines/titanic/sound/dome_from_top_of_well.cpp new file mode 100644 index 0000000000..789d7fa4cb --- /dev/null +++ b/engines/titanic/sound/dome_from_top_of_well.cpp @@ -0,0 +1,47 @@ +/* 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/sound/dome_from_top_of_well.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CDomeFromTopOfWell, CViewAutoSoundPlayer); + +CDomeFromTopOfWell::CDomeFromTopOfWell() : CViewAutoSoundPlayer() { + _filename = "z#227.wav"; + _volume = 25; + _repeated = true; + _stopSeconds = 1; + _startSeconds = 1; +} + +void CDomeFromTopOfWell::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CViewAutoSoundPlayer::save(file, indent); +} + +void CDomeFromTopOfWell::load(SimpleFile *file) { + file->readNumber(); + CViewAutoSoundPlayer::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/dome_from_top_of_well.h b/engines/titanic/sound/dome_from_top_of_well.h new file mode 100644 index 0000000000..001f66a1a8 --- /dev/null +++ b/engines/titanic/sound/dome_from_top_of_well.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_DOME_FROM_TOP_OF_WELL_H +#define TITANIC_DOME_FROM_TOP_OF_WELL_H + +#include "titanic/sound/view_auto_sound_player.h" + +namespace Titanic { + +class CDomeFromTopOfWell : public CViewAutoSoundPlayer { + DECLARE_MESSAGE_MAP; +public: + CLASSDEF; + CDomeFromTopOfWell(); + + /** + * 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_DOME_FROM_TOP_OF_WELL_H */ diff --git a/engines/titanic/sound/enter_view_toggles_other_music.cpp b/engines/titanic/sound/enter_view_toggles_other_music.cpp new file mode 100644 index 0000000000..2f0091a0a3 --- /dev/null +++ b/engines/titanic/sound/enter_view_toggles_other_music.cpp @@ -0,0 +1,60 @@ +/* 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/sound/enter_view_toggles_other_music.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CEnterViewTogglesOtherMusic, CTriggerAutoMusicPlayer) + ON_MESSAGE(EnterViewMsg) +END_MESSAGE_MAP() + +CEnterViewTogglesOtherMusic::CEnterViewTogglesOtherMusic() : + CTriggerAutoMusicPlayer(), _value(2) { +} + +void CEnterViewTogglesOtherMusic::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + + CTriggerAutoMusicPlayer::save(file, indent); +} + +void CEnterViewTogglesOtherMusic::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + + CTriggerAutoMusicPlayer::load(file); +} + +bool CEnterViewTogglesOtherMusic::EnterViewMsg(CEnterViewMsg *msg) { + CViewItem *view = findView(); + if (view == msg->_newView) { + CTriggerAutoMusicPlayerMsg triggerMsg; + triggerMsg._value = _value; + triggerMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/enter_view_toggles_other_music.h b/engines/titanic/sound/enter_view_toggles_other_music.h new file mode 100644 index 0000000000..a91b1e1933 --- /dev/null +++ b/engines/titanic/sound/enter_view_toggles_other_music.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_ENTER_VIEW_TOGGLES_OTHER_MUSIC_H +#define TITANIC_ENTER_VIEW_TOGGLES_OTHER_MUSIC_H + +#include "titanic/sound/trigger_auto_music_player.h" + +namespace Titanic { + +class CEnterViewTogglesOtherMusic : public CTriggerAutoMusicPlayer { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); +protected: + int _value; +public: + CLASSDEF; + CEnterViewTogglesOtherMusic(); + + /** + * 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_ENTER_VIEW_TOGGLES_OTHER_MUSIC_H */ diff --git a/engines/titanic/sound/gondolier_song.cpp b/engines/titanic/sound/gondolier_song.cpp new file mode 100644 index 0000000000..5c96718723 --- /dev/null +++ b/engines/titanic/sound/gondolier_song.cpp @@ -0,0 +1,94 @@ +/* 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/sound/gondolier_song.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CGondolierSong, CRoomAutoSoundPlayer) + ON_MESSAGE(TurnOn) + ON_MESSAGE(SignalObject) + ON_MESSAGE(SetVolumeMsg) + ON_MESSAGE(StatusChangeMsg) +END_MESSAGE_MAP() + +void CGondolierSong::save(SimpleFile *file, int indent) { + file->writeNumberLine(_enabled, indent); + file->writeNumberLine(_value, indent); + CRoomAutoSoundPlayer::save(file, indent); +} + +void CGondolierSong::load(SimpleFile *file) { + _enabled = file->readNumber(); + _value = file->readNumber(); + CRoomAutoSoundPlayer::load(file); +} + +bool CGondolierSong::TurnOn(CTurnOn *msg) { + if (_enabled) { + if (_soundHandle != -1) { + int volume = _value * _volume / 100; + + if (_startSeconds == -1) { + _soundHandle = playSound(_filename, volume, _fieldD0, _repeated); + } else { + _soundHandle = playSound(_filename, 0, _fieldD0, _repeated); + setSoundVolume(_soundHandle, _volume, _startSeconds); + } + + _active = true; + } + } + + return true; +} + +bool CGondolierSong::SignalObject(CSignalObject *msg) { + _enabled = false; + CAutoSoundPlayer::SignalObject(msg); + return true; +} + +bool CGondolierSong::SetVolumeMsg(CSetVolumeMsg *msg) { + if (_enabled) { + _volume = msg->_volume; + + if (_soundHandle != -1 && isSoundActive(_soundHandle)) { + int newVolume = _value * _volume / 100; + setSoundVolume(_soundHandle, newVolume, msg->_secondsTransition); + } + } + + return true; +} + +bool CGondolierSong::StatusChangeMsg(CStatusChangeMsg *msg) { + if (_enabled) { + _value = CLIP(msg->_newStatus, 0, 100); + CSetVolumeMsg volumeMsg(_volume, _stopSeconds); + volumeMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/gondolier_song.h b/engines/titanic/sound/gondolier_song.h new file mode 100644 index 0000000000..d586711de9 --- /dev/null +++ b/engines/titanic/sound/gondolier_song.h @@ -0,0 +1,56 @@ +/* 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_GONDOLIER_SONG_H +#define TITANIC_GONDOLIER_SONG_H + +#include "titanic/sound/room_auto_sound_player.h" + +namespace Titanic { + +class CGondolierSong : public CRoomAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool TurnOn(CTurnOn *msg); + bool SignalObject(CSignalObject *msg); + bool SetVolumeMsg(CSetVolumeMsg *msg); + bool StatusChangeMsg(CStatusChangeMsg *msg); +public: + bool _enabled; + int _value; +public: + CLASSDEF; + CGondolierSong() : CRoomAutoSoundPlayer(), _enabled(true), _value(0) {} + + /** + * 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_GONDOLIER_SONG_H */ diff --git a/engines/titanic/sound/music_handler.cpp b/engines/titanic/sound/music_handler.cpp new file mode 100644 index 0000000000..07c3994334 --- /dev/null +++ b/engines/titanic/sound/music_handler.cpp @@ -0,0 +1,85 @@ +/* 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/sound/music_handler.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +CMusicHandler::CMusicHandler(CProjectItem *project, CSoundManager *soundManager) : + _project(project), _soundManager(soundManager), _stopWaves(false), + _soundHandle(-1), _waveFile(nullptr) { + Common::fill(&_musicWaves[0], &_musicWaves[4], (CMusicWave *)nullptr); +} + +CMusicHandler::~CMusicHandler() { + stop(); +} + +CMusicWave *CMusicHandler::createMusicWave(int waveIndex, int count) { + switch (waveIndex) { + case 0: + _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 2); + break; + case 1: + _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 3); + break; + case 2: + _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 0); + break; + case 3: + _musicWaves[waveIndex] = new CMusicWave(_project, _soundManager, 1); + break; + default: + return nullptr; + } + + _musicWaves[waveIndex]->setSize(count); + return _musicWaves[waveIndex]; +} + +bool CMusicHandler::isBusy() { + // TODO + return false; +} + +void CMusicHandler::stop() { + if (_waveFile) { + _soundManager->stopSound(_soundHandle); + delete _waveFile; + _waveFile = nullptr; + _soundHandle = -1; + } + + for (int idx = 0; idx < 4; ++idx) { + if (_stopWaves && _musicWaves[idx]) + _musicWaves[idx]->stop(); + } +} + +bool CMusicHandler::checkSound(int index) const { + // TODO + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/music_handler.h b/engines/titanic/sound/music_handler.h new file mode 100644 index 0000000000..6792844cb5 --- /dev/null +++ b/engines/titanic/sound/music_handler.h @@ -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. + * + */ + +#ifndef TITANIC_MUSIC_HANDLER_H +#define TITANIC_MUSIC_HANDLER_H + +#include "titanic/sound/music_wave.h" +#include "titanic/sound/wave_file.h" + +namespace Titanic { + +class CProjectItem; +class CSoundManager; + +class CMusicHandler { +private: + CProjectItem *_project; + CSoundManager *_soundManager; + CMusicWave *_musicWaves[4]; + bool _stopWaves; + CWaveFile *_waveFile; + int _soundHandle; +public: + CMusicHandler(CProjectItem *project, CSoundManager *soundManager); + ~CMusicHandler(); + + /** + * Creates a new music wave class instance, and assigns it to a slot + * in the music handler + * @param waveIndex Slot to save new instance in + * @param count Number of files the new instance will contain + */ + CMusicWave *createMusicWave(int waveIndex, int count); + + bool isBusy(); + + /** + * Flags whether the loaded music waves will be stopped when the + * music handler is stopped + */ + void setStopWaves(bool flag) { _stopWaves = flag; } + + /** + * Stop playing the music + */ + void stop(); + + bool checkSound(int index) const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MUSIC_HANDLER_H */ diff --git a/engines/titanic/sound/music_player.cpp b/engines/titanic/sound/music_player.cpp new file mode 100644 index 0000000000..cd764c7f93 --- /dev/null +++ b/engines/titanic/sound/music_player.cpp @@ -0,0 +1,182 @@ +/* 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/sound/music_player.h" +#include "titanic/sound/music_room.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CMusicPlayer, CGameObject) + ON_MESSAGE(StartMusicMsg) + ON_MESSAGE(StopMusicMsg) + ON_MESSAGE(FrameMsg) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(CreateMusicPlayerMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +void CMusicPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_isActive, indent); + file->writeQuotedLine(_stopTarget, indent); + file->writeNumberLine(_stopWaves, indent); + file->writeNumberLine(_musicId, indent); + + CGameObject::save(file, indent); +} + +void CMusicPlayer::load(SimpleFile *file) { + file->readNumber(); + _isActive = file->readNumber(); + _stopTarget = file->readString(); + _stopWaves = file->readNumber(); + _musicId = file->readNumber(); + + CGameObject::load(file); +} + +bool CMusicPlayer::StartMusicMsg(CStartMusicMsg *msg) { + if (msg->_musicPlayer == this) { + if (_isActive) { + CStopMusicMsg stopMusicMsg; + stopMusicMsg.execute(this); + } + + return false; + } + + if (!_isActive) { + lockMouse(); + + CCreateMusicPlayerMsg createMsg; + createMsg.execute(this); + CSetMusicControlsMsg controlsMsg; + controlsMsg.execute(this, nullptr, MSGFLAG_SCAN); + + getMusicRoom()->startMusic(_musicId); + _isActive = true; + } + + return true; +} + +bool CMusicPlayer::StopMusicMsg(CStopMusicMsg *msg) { + if (!_isActive) + // Player isn't playing, so ignore message + return false; + + // Stop the music + CMusicRoom *musicRoom = getMusicRoom(); + if (musicRoom) + musicRoom->stopMusic(); + _isActive = false; + + CMusicHasStoppedMsg stoppedMsg; + stoppedMsg.execute(_stopTarget, nullptr, MSGFLAG_SCAN); + return true; +} + +bool CMusicPlayer::FrameMsg(CFrameMsg *msg) { + if (_isActive && !CMusicRoom::_musicHandler->isBusy()) { + getMusicRoom()->stopMusic(); + _isActive = false; + + CMusicHasStoppedMsg stoppedMsg; + stoppedMsg.execute(_stopTarget); + } + + return true; +} + +bool CMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) { + addTimer(100); + return true; +} + +bool CMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) { + getMusicRoom()->destroyMusicHandler(); + return true; +} + +bool CMusicPlayer::CreateMusicPlayerMsg(CCreateMusicPlayerMsg *msg) { + if (CMusicRoom::_musicHandler) { + CMusicRoom::_musicHandler->setStopWaves(_stopWaves); + return true; + } + + CMusicHandler *musicHandler = getMusicRoom()->createMusicHandler(); + CMusicWave *wave; + + if (musicHandler) { + wave = musicHandler->createMusicWave(0, 3); + wave->load(0, "z#490.wav", 60); + wave->load(1, "z#488.wav", 62); + wave->load(2, "z#489.wav", 63); + + wave = musicHandler->createMusicWave(1, 5); + wave->load(0, "z#493.wav", 22); + wave->load(1, "z#495.wav", 29); + wave->load(2, "z#492.wav", 34); + wave->load(3, "z#494.wav", 41); + wave->load(4, "z#491.wav", 46); + + wave = musicHandler->createMusicWave(2, 5); + wave->load(0, "z#499.wav", 26); + wave->load(1, "z#497.wav", 34); + wave->load(2, "z#498.wav", 38); + wave->load(3, "z#496.wav", 46); + wave->load(4, "z#500.wav", 60); + + wave = musicHandler->createMusicWave(3, 7); + wave->load(0, "z#504.wav", 22); + wave->load(1, "z#507.wav", 29); + wave->load(2, "z#503.wav", 34); + wave->load(3, "z#506.wav", 41); + wave->load(4, "z#502.wav", 46); + wave->load(5, "z#505.wav", 53); + wave->load(6, "z#501.wav", 58); + + CMusicRoom::_musicHandler->setStopWaves(_stopWaves); + } + + return true; +} + +bool CMusicPlayer::TimerMsg(CTimerMsg *msg) { + CCreateMusicPlayerMsg playerMsg; + playerMsg.execute(this); + return true; +} + +bool CMusicPlayer::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_isActive) { + CStopMusicMsg stopMsg; + stopMsg.execute(this); + CStartMusicMsg startMsg; + startMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/music_player.h b/engines/titanic/sound/music_player.h new file mode 100644 index 0000000000..7b82d4da00 --- /dev/null +++ b/engines/titanic/sound/music_player.h @@ -0,0 +1,64 @@ +/* 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_MUSIC_PLAYER_H +#define TITANIC_MUSIC_PLAYER_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CMusicPlayer : public CGameObject { + DECLARE_MESSAGE_MAP; + bool StartMusicMsg(CStartMusicMsg *msg); + bool StopMusicMsg(CStopMusicMsg *msg); + bool FrameMsg(CFrameMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool CreateMusicPlayerMsg(CCreateMusicPlayerMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +protected: + bool _isActive; + CString _stopTarget; + bool _stopWaves; + int _musicId; +public: + CLASSDEF; + CMusicPlayer() : CGameObject(), + _isActive(false), _stopWaves(false), _musicId(100) {} + + /** + * 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_MUSIC_PLAYER_H */ diff --git a/engines/titanic/sound/music_room.cpp b/engines/titanic/sound/music_room.cpp new file mode 100644 index 0000000000..2e4ad904fa --- /dev/null +++ b/engines/titanic/sound/music_room.cpp @@ -0,0 +1,64 @@ +/* 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/sound/music_room.h" +#include "titanic/sound/sound.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +CMusicHandler *CMusicRoom::_musicHandler; + +CMusicRoom::CMusicRoom(CGameManager *gameManager) : + _gameManager(gameManager) { + _sound = &_gameManager->_sound; + _items.resize(4); +} + +CMusicRoom::~CMusicRoom() { + destroyMusicHandler(); +} + +CMusicHandler *CMusicRoom::createMusicHandler() { + if (_musicHandler) + destroyMusicHandler(); + + _musicHandler = new CMusicHandler(_gameManager->_project, &_sound->_soundManager); + return _musicHandler; +} + +void CMusicRoom::destroyMusicHandler() { + delete _musicHandler; + _musicHandler = nullptr; +} + +void CMusicRoom::startMusic(int musicId) { + // TODO +} + +void CMusicRoom::stopMusic() { + if (_musicHandler) + _musicHandler->stop(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/music_room.h b/engines/titanic/sound/music_room.h new file mode 100644 index 0000000000..5f0b271ab3 --- /dev/null +++ b/engines/titanic/sound/music_room.h @@ -0,0 +1,86 @@ +/* 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_MUSIC_ROOM_H +#define TITANIC_MUSIC_ROOM_H + +#include "common/array.h" +#include "titanic/sound/music_handler.h" + +namespace Titanic { + +class CGameManager; +class CSound; + +enum MusicControlArea { BELLS = 0, SNAKE = 1, PIANO = 2, BASS = 3 }; + +class CMusicRoom { + struct Entry { + uint _val1; + uint _val2; + uint _val3; + uint _val4; + uint _val5; + + Entry() : _val1(0), _val2(0), _val3(0), _val4(0), _val5(0) {} + }; +private: + Common::Array<Entry> _items; +public: + static CMusicHandler *_musicHandler; +public: + CGameManager *_gameManager; + CSound *_sound; +public: + CMusicRoom(CGameManager *owner); + ~CMusicRoom(); + + /** + * Creates a music handler + */ + CMusicHandler *createMusicHandler(); + + /** + * Destroys and currently active music handler + */ + void destroyMusicHandler(); + + void setItem1(MusicControlArea index, int val) { _items[index]._val1 = val; } + void setItem2(MusicControlArea index, int val) { _items[index]._val2 = val; } + void setItem3(MusicControlArea index, int val) { _items[index]._val3 = val; } + void setItem4(MusicControlArea index, int val) { _items[index]._val4 = val; } + void setItem5(MusicControlArea index, int val) { _items[index]._val5 = val; } + + /** + * Start playing a given music number + */ + void startMusic(int musicId); + + /** + * Stop playing music + */ + void stopMusic(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MUSIC_ROOM_H */ diff --git a/engines/titanic/sound/music_wave.cpp b/engines/titanic/sound/music_wave.cpp new file mode 100644 index 0000000000..6b5b187805 --- /dev/null +++ b/engines/titanic/sound/music_wave.cpp @@ -0,0 +1,54 @@ +/* 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/sound/music_wave.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/core/project_item.h" + +namespace Titanic { + +CMusicWave::CMusicWave(CProjectItem *project, CSoundManager *soundManager, int index) : + _project(project), _soundManager(soundManager) { +} + +void CMusicWave::setSize(uint count) { + assert(_items.empty()); + _items.resize(count); +} + +void CMusicWave::load(int index, const CString &filename, int v3) { + assert(!_items[index]._waveFile); + _items[index]._waveFile = createWaveFile(filename); + _items[index]._value = v3; +} + +CWaveFile *CMusicWave::createWaveFile(const CString &name) { + if (name.empty()) + return nullptr; + return _soundManager->loadSound(name); +} + +void CMusicWave::stop() { + +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/music_wave.h b/engines/titanic/sound/music_wave.h new file mode 100644 index 0000000000..b240f4a856 --- /dev/null +++ b/engines/titanic/sound/music_wave.h @@ -0,0 +1,71 @@ +/* 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_MUSIC_WAVE_H +#define TITANIC_MUSIC_WAVE_H + +#include "common/array.h" +#include "titanic/support/string.h" + +namespace Titanic { + +class CProjectItem; +class CSoundManager; +class CWaveFile; + +class CMusicWave { + struct CMusicWaveFile { + CWaveFile *_waveFile; + int _value; + CMusicWaveFile() : _waveFile(nullptr), _value(0) {} + }; +private: + CProjectItem *_project; + CSoundManager *_soundManager; + Common::Array<CMusicWaveFile> _items; +private: + /** + * Loads the specified wave file, and returns a CWaveFile instance for it + */ + CWaveFile *createWaveFile(const CString &name); +public: + CMusicWave(CProjectItem *project, CSoundManager *soundManager, int index); + + /** + * Sets the maximum number of allowed files that be defined + */ + void setSize(uint count); + + /** + * Loads a new file into the list of available entries + */ + void load(int index, const CString &filename, int v3); + + /** + * Stops the music + */ + void stop(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MUSIC_WAVE_H */ diff --git a/engines/titanic/sound/node_auto_sound_player.cpp b/engines/titanic/sound/node_auto_sound_player.cpp new file mode 100644 index 0000000000..40b3d2ea39 --- /dev/null +++ b/engines/titanic/sound/node_auto_sound_player.cpp @@ -0,0 +1,84 @@ +/* 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/sound/node_auto_sound_player.h" +#include "titanic/sound/auto_music_player.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CNodeAutoSoundPlayer, CAutoSoundPlayer) + ON_MESSAGE(EnterNodeMsg) + ON_MESSAGE(LeaveNodeMsg) +END_MESSAGE_MAP() + +void CNodeAutoSoundPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_enabled, indent); + CAutoSoundPlayer::save(file, indent); +} + +void CNodeAutoSoundPlayer::load(SimpleFile *file) { + file->readNumber(); + _enabled = file->readNumber(); + CAutoSoundPlayer::load(file); +} + +bool CNodeAutoSoundPlayer::EnterNodeMsg(CEnterNodeMsg *msg) { + CNodeItem *node = findNode(); + CRoomItem *room = findRoom(); + + if (node == msg->_newNode) { + CTurnOn onMsg; + onMsg.execute(this); + + if (_enabled) { + CChangeMusicMsg changeMsg; + changeMsg._flags = 1; + changeMsg.execute(room, CAutoMusicPlayer::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + } + } + + return true; +} + +bool CNodeAutoSoundPlayer::LeaveNodeMsg(CLeaveNodeMsg *msg) { + CNodeItem *node = findNode(); + CRoomItem *room = findRoom(); + + if (node == msg->_oldNode) { + CTurnOff offMsg; + offMsg.execute(this); + + if (_enabled) { + CChangeMusicMsg changeMsg; + changeMsg._flags = 2; + changeMsg.execute(room, CAutoMusicPlayer::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/node_auto_sound_player.h b/engines/titanic/sound/node_auto_sound_player.h new file mode 100644 index 0000000000..f5bdc42c3c --- /dev/null +++ b/engines/titanic/sound/node_auto_sound_player.h @@ -0,0 +1,54 @@ +/* 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_NODE_AUTO_SOUND_PLAYER_H +#define TITANIC_NODE_AUTO_SOUND_PLAYER_H + +#include "titanic/sound/auto_sound_player.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CNodeAutoSoundPlayer : public CAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool EnterNodeMsg(CEnterNodeMsg *msg); + bool LeaveNodeMsg(CLeaveNodeMsg *msg); +private: + bool _enabled; +public: + CLASSDEF; + CNodeAutoSoundPlayer() : CAutoSoundPlayer(), _enabled(true) {} + + /** + * 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_NODE_AUTO_SOUND_PLAYER_H */ diff --git a/engines/titanic/sound/proximity.cpp b/engines/titanic/sound/proximity.cpp new file mode 100644 index 0000000000..7f4e6784f2 --- /dev/null +++ b/engines/titanic/sound/proximity.cpp @@ -0,0 +1,37 @@ +/* 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/sound/proximity.h" +#include "titanic/true_talk/tt_talker.h" + +namespace Titanic { + +CProximity::CProximity() : _field4(0), _channelVolume(100), _fieldC(0), + _priorSoundHandle(-1), _field14(0), _frequencyMultiplier(0.0), _field1C(1.875), + _repeated(false), _channel(10), _positioningMode(POSMODE_NONE), _azimuth(0.0), + _range(0.5), _elevation(0), _posX(0.0), _posY(0.0), _posZ(0.0), + _hasVelocity(false), _velocityX(0), _velocityY(0), _velocityZ(0), + _field54(0), _field58(0), _field5C(0), _freeSoundFlag(false), _endTalkerFn(nullptr), + _talker(nullptr), _field6C(0) { +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/proximity.h b/engines/titanic/sound/proximity.h new file mode 100644 index 0000000000..b728f22c26 --- /dev/null +++ b/engines/titanic/sound/proximity.h @@ -0,0 +1,71 @@ +/* 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_PROXIMITY_H +#define TITANIC_PROXIMITY_H + +#include "common/scummsys.h" + +namespace Titanic { + +enum PositioningMode { POSMODE_NONE = 0, POSMODE_POLAR = 1, POSMODE_VECTOR = 2 }; + +class TTtalker; + +typedef void (*CEndTalkerFn)(TTtalker *talker); + +class CProximity { +public: + int _field4; + int _channelVolume; + int _fieldC; + int _priorSoundHandle; + int _field14; + double _frequencyMultiplier; + double _field1C; + bool _repeated; + int _channel; + PositioningMode _positioningMode; + double _azimuth; + double _range; + double _elevation; + double _posX; + double _posY; + double _posZ; + bool _hasVelocity; + double _velocityX; + double _velocityY; + double _velocityZ; + int _field54; + int _field58; + int _field5C; + bool _freeSoundFlag; + CEndTalkerFn _endTalkerFn; + TTtalker *_talker; + int _field6C; +public: + CProximity(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PROXIMITY_H */ diff --git a/engines/titanic/sound/qmixer.cpp b/engines/titanic/sound/qmixer.cpp new file mode 100644 index 0000000000..145d142b2d --- /dev/null +++ b/engines/titanic/sound/qmixer.cpp @@ -0,0 +1,173 @@ +/* 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/sound/qmixer.h" + +namespace Titanic { + +QMixer::QMixer(Audio::Mixer *mixer) : _mixer(mixer) { +} + +bool QMixer::qsWaveMixInitEx(const QMIXCONFIG &config) { + assert(_channels.empty()); + assert(config.iChannels > 0 && config.iChannels < 256); + + _channels.resize(config.iChannels); + return true; +} + +void QMixer::qsWaveMixActivate(bool fActivate) { + // Not currently implemented in ScummVM +} + +int QMixer::qsWaveMixOpenChannel(int iChannel, QMixFlag mode) { + // Not currently implemented in ScummVM + return 0; +} + +int QMixer::qsWaveMixEnableChannel(int iChannel, uint flags, bool enabled) { + // Not currently implemented in ScummVM + return 0; +} + +void QMixer::qsWaveMixCloseSession() { + _mixer->stopAll(); + _channels.clear(); +} + +void QMixer::qsWaveMixFreeWave(Audio::SoundHandle &handle) { + _mixer->stopHandle(handle); +} + +void QMixer::qsWaveMixFlushChannel(int iChannel, uint flags) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetPanRate(int iChannel, uint flags, uint rate) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetVolume(int iChannel, uint flags, uint volume) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetListenerPosition(const QSVECTOR &position, uint flags) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetListenerOrientation(const QSVECTOR &direction, const QSVECTOR &up, uint flags) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetDistanceMapping(int iChannel, uint flags, const QMIX_DISTANCES &distances) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetFrequency(int iChannel, uint flags, uint frequency) { + // Not currently implemented in ScummVM +} + +void QMixer::qsWaveMixSetSourceVelocity(int iChannel, uint flags, const QSVECTOR &velocity) { + // Not currently implemented in ScummVM +} + +int QMixer::qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *waveFile, int loops, const QMIXPLAYPARAMS ¶ms) { + if (iChannel == -1) { + // Find a free channel + for (iChannel = 0; iChannel < (int)_channels.size(); ++iChannel) { + if (_channels[iChannel]._sounds.empty()) + break; + } + assert(iChannel != (int)_channels.size()); + } + + // If the new sound replaces current ones, then clear the channel + ChannelEntry &channel = _channels[iChannel]; + if (flags & QMIX_CLEARQUEUE) { + if (!channel._sounds.empty() && channel._sounds.front()._started) + _mixer->stopHandle(channel._sounds.front()._soundHandle); + + channel._sounds.clear(); + } + + // Add the sound to the channel + channel._sounds.push_back(SoundEntry(waveFile, params.callback, loops, params.dwUser)); + qsWaveMixPump(); + + return 0; +} + +bool QMixer::qsWaveMixIsChannelDone(int iChannel) const { + return _channels[iChannel]._sounds.empty(); +} + +void QMixer::qsWaveMixPump() { + // Iterate through each of the channels + for (uint iChannel = 0; iChannel < _channels.size(); ++iChannel) { + ChannelEntry &channel = _channels[iChannel]; + + // If the playing sound on the channel is finished, then call + // the callback registered for it, and remove it from the list + if (!channel._sounds.empty()) { + SoundEntry &sound = channel._sounds.front(); + if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) { + if (sound._loops == -1 || sound._loops-- > 0) { + // Need to loop the sound again + sound._waveFile->_stream->rewind(); + _mixer->playStream(sound._waveFile->_soundType, + &sound._soundHandle, sound._waveFile->_stream, + -1, 0xff, 0, DisposeAfterUse::NO); + } else { + // Sound is finished + if (sound._callback) + // Call the callback to signal end + sound._callback(iChannel, sound._waveFile, sound._userData); + + // Remove sound record from channel + channel._sounds.erase(channel._sounds.begin()); + } + } + } + + // If there's an unstarted sound at the front of a channel's + // sound list, then start it playing + if (!channel._sounds.empty()) { + SoundEntry &sound = channel._sounds.front(); + if (!sound._started) { + _mixer->playStream(sound._waveFile->_soundType, + &sound._soundHandle, sound._waveFile->_stream, + -1, 0xff, 0, DisposeAfterUse::NO); + sound._started = true; + } + } + } +} + +} // End of namespace Titanic z diff --git a/engines/titanic/sound/qmixer.h b/engines/titanic/sound/qmixer.h new file mode 100644 index 0000000000..4ba76a8969 --- /dev/null +++ b/engines/titanic/sound/qmixer.h @@ -0,0 +1,312 @@ +/* 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 + * aint with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef TITANIC_QMIXER_H +#define TITANIC_QMIXER_H + +#include "audio/mixer.h" +#include "titanic/sound/wave_file.h" + +namespace Titanic { + +enum QMixFlag { + QMIX_OPENSINGLE = 0, // Open the single channel specified by iChannel + QMIX_OPENALL = 1, // Opens all the channels, iChannel ignored + QMIX_OPENCOUNT = 2, // Open iChannel Channels (eg. if iChannel = 4 will create channels 0-3) + QMIX_OPENAVAILABLE = 3, // Open the first unopened channel, and return channel number + + // Channel function flags + QMIX_ALL = 0x01, // apply to all channels + QMIX_NOREMIX = 0x02, // don't remix + QMIX_CONTROL_NOREMIX = 0x04, // don't remix + QMIX_USEONCE = 0x10 // settings are temporary +}; + +// qsWaveMixEnableChannel flags: if mode==0, use conventional, high-performance +// stereo mixer. Non-zero modes imply some form of additional processing. +enum QMixChannelFlag { + QMIX_CHANNEL_STEREO = 0x0000, // Perform stereo mixing + QMIX_CHANNEL_QSOUND = 0x0001, // Perform QSound localization (default) + QMIX_CHANNEL_DOPPLER = 0x0002, // Calculate velocity using position updates + QMIX_CHANNEL_RANGE = 0x0004, // Do range effects + QMIX_CHANNEL_ELEVATION = 0x0008, // Do elevation effects + QMIX_CHANNEL_NODOPPLERPITCH = 0x0010, // Disable Doppler pitch shift for this channel + QMIX_CHANNEL_PITCH_COPY = 0x0000, // Pitch shifting using copying (fastest) + QMIX_CHANNEL_PITCH_LINEAR = 0x0100, // Pitch shifting using linear interpolation (better but slower) + QMIX_CHANNEL_PITCH_SPLINE = 0x0200, // Pitch shifting using spline interpolation (better yet, but much slower) + QMIX_CHANNEL_PITCH_FILTER = 0x0300, // Pitch shifting using FIR filter (best, but slowest) + QMIX_CHANNEL_PITCH_MASK = 0x0700 // Bits reserved for pitch types +}; + +/** + * Options for dwFlags parameter in QSWaveMixPlayEx. + * + * Notes: The QMIX_USELRUCHANNEL flag has two roles. When QMIX_CLEARQUEUE is also set, + * the channel that has been playing the longest (least-recently-used) is cleared and + * the buffer played. When QMIX_QUEUEWAVE is set, the channel that will first finish + * playing will be selected and the buffer queued to play. Of course, if an unused + * channel is found, it will be selected instead. + * If QMIX_WAIT hasn't been specified, then the channel number will be returned + * in the iChannel field. + */ +enum QMixPlayFlag { + QMIX_QUEUEWAVE = 0x0000, // Queue on channel + QMIX_CLEARQUEUE = 0x0001, // Clear queue on channel + QMIX_USELRUCHANNEL = 0x0002, // See notes above + QMIX_HIGHPRIORITY = 0x0004, + QMIX_WAIT = 0x0008, // Queue to be played with other sounds + QMIX_IMMEDIATE = 0x0020, // Apply volume/pan changes without interpolation + + QMIX_PLAY_SETEVENT = 0x0100, // Calls SetEvent in the original library when done + QMIX_PLAY_PULSEEVENT = 0x0200, // Calls PulseEvent in the original library when done + QMIX_PLAY_NOTIFYSTOP = 0x0400 // Do callback even when stopping or flushing sound +}; + +/** + * Mixer configuration structure for qsWaveMixInitEx + */ +struct QMIXCONFIG { + uint32 dwSize; + uint32 dwFlags; + uint32 dwSamplingRate; // Sampling rate in Hz + void *lpIDirectSound; + const void *lpGuid; + int iChannels; // Number of channels + int iOutput; // if 0, uses best output device + int iLatency; // (in ms) if 0, uses default for output device + int iMath; // style of math + uint hwnd; + + QMIXCONFIG() : dwSize(40), dwFlags(0), dwSamplingRate(0), lpIDirectSound(nullptr), + lpGuid(nullptr), iChannels(0), iOutput(0), iLatency(0), iMath(0), hwnd(0) {} + QMIXCONFIG(uint32 rate, int channels, int latency) : dwSize(40), dwFlags(0), + dwSamplingRate(rate), iChannels(channels), iLatency(latency), + lpIDirectSound(nullptr), lpGuid(nullptr), iOutput(0), iMath(0), hwnd(0) {} +}; + +/** + * Vector positioning in metres + */ +struct QSVECTOR { + double x; + double y; + double z; + + QSVECTOR() : x(0.0), y(0.0), z(0.0) {} + QSVECTOR(double xp, double yp, double zp) : x(xp), y(yp), z(zp) {} +}; + +/** + * Polar positioning + */ +struct QSPOLAR { + double azimuth; // degrees + double range; // meters + double elevation; // degrees + + QSPOLAR() : azimuth(0.0), range(0.0), elevation(0.0) {} + QSPOLAR(double azimuth_, double range_, double elevation_) : + azimuth(azimuth_), range(range_), elevation(elevation_) {} +}; + +struct QMIX_DISTANCES { + int cbSize; // Structure size + double minDistance; // sounds are at full volume if closer than this + double maxDistance; // sounds are muted if further away than this + double scale; // relative amount to adjust rolloff by + + QMIX_DISTANCES() : cbSize(16), minDistance(0.0), maxDistance(0.0), scale(0.0) {} + QMIX_DISTANCES(double minDistance_, double maxDistance_, double scale_) : + cbSize(16), minDistance(minDistance_), maxDistance(maxDistance_), scale(scale_) {} +}; + +typedef void (*LPQMIXDONECALLBACK)(int iChannel, CWaveFile *lpWave, void *dwUser); + +struct QMIXPLAYPARAMS { + uint dwSize; // Size of the play structure + void *lpImage; // Additional preprocessed audio for high performance + uint hwndNotify; // if set, WOM_OPEN and WOM_DONE messages sent to that window + LPQMIXDONECALLBACK callback; // Callback function + void *dwUser; // User data accompanying callback + int lStart; + int lStartLoop; + int lEndLoop; + int lEnd; + const void *lpChannelParams; // initialize with these parameters + // Properties introduced by ScummVM + Audio::Mixer::SoundType _soundType; + + QMIXPLAYPARAMS() : dwSize(36), lpImage(nullptr), hwndNotify(0), callback(nullptr), + dwUser(nullptr), lStart(0), lStartLoop(0), lEndLoop(0), lEnd(0), + lpChannelParams(nullptr), _soundType(Audio::Mixer::kPlainSoundType) {} +}; + +/** + * This class represents an interface to the QMixer library developed by + * QSound Labs, Inc. Which itself is apparently based on Microsoft's + * WaveMix API. + * + * It does not currently have any actual code from the library, + * and instead remaps calls to ScummVM's existing mixer where possible. + * This means that advanced features of the QMixer library, like being + * able to set up both the player and sounds at different positions are + * currently ignored, and all sounds play at full volume. + */ +class QMixer { + struct SoundEntry { + bool _started; + CWaveFile *_waveFile; + Audio::SoundHandle _soundHandle; + LPQMIXDONECALLBACK _callback; + int _loops; + void *_userData; + SoundEntry() : _started(false), _waveFile(nullptr), _callback(nullptr), + _loops(0), _userData(nullptr) {} + + SoundEntry(CWaveFile *waveFile, LPQMIXDONECALLBACK callback, int loops, void *userData) : + _started(false), _waveFile(waveFile), _callback(callback), _loops(loops), _userData(userData) {} + }; + struct ChannelEntry { + Common::List<SoundEntry> _sounds; + }; +private: + Audio::Mixer *_mixer; + Common::Array<ChannelEntry> _channels; +public: + QMixer(Audio::Mixer *mixer); + virtual ~QMixer() {} + + /** + * Initializes the mixer + */ + bool qsWaveMixInitEx(const QMIXCONFIG &config); + + /** + * Activates the mixer + */ + void qsWaveMixActivate(bool fActivate); + + /** + * Opens channels in the mixer for access + */ + int qsWaveMixOpenChannel(int iChannel, QMixFlag mode); + + /** + * Enables a given channel + */ + int qsWaveMixEnableChannel(int iChannel, uint flags, bool enabled); + + /** + * Closes down the mixer + */ + void qsWaveMixCloseSession(); + + /** + * Stops a sound from playing + */ + void qsWaveMixFreeWave(Audio::SoundHandle &handle); + + /** + * Flushes a channel + */ + void qsWaveMixFlushChannel(int iChannel, uint flags = 0); + + /** + * Sets the amount of time, in milliseconds, to effect a change in + * a channel property (e.g. volume, position). Non-zero values + * smooth out changes + * @param iChannel Channel to change + * @param flags Flags + * @param rate Pan rate in milliseconds + */ + void qsWaveMixSetPanRate(int iChannel, uint flags, uint rate); + + /** + * Sets the volume for a channel + */ + void qsWaveMixSetVolume(int iChannel, uint flags, uint volume); + + /** + * Sets the relative position of a channel + * @param iChannel Channel number + * @param Flags Flags + * @param position Vector position for channel + */ + void qsWaveMixSetSourcePosition(int iChannel, uint flags, const QSVECTOR &position); + + /** + * Sets the relative position of a channel using polar co-ordinates + * @param iChannel Channel number + * @param Flags Flags + * @param position Polar position for channel + */ + void qsWaveMixSetPolarPosition(int iChannel, uint flags, const QSPOLAR &position); + + /** + * Sets the listener position + */ + void qsWaveMixSetListenerPosition(const QSVECTOR &position, uint flags = 0); + + /** + * Sets the listener orientation + */ + void qsWaveMixSetListenerOrientation(const QSVECTOR &direction, const QSVECTOR &up, uint flags = 0); + + /** + * Sets the mapping ditance range + */ + void qsWaveMixSetDistanceMapping(int iChannel, uint flags, const QMIX_DISTANCES &distances); + + /** + * + */ + void qsWaveMixSetFrequency(int iChannel, uint flags, uint frequency); + + /** + * Sets the velocity of the source (listener) + */ + void qsWaveMixSetSourceVelocity(int iChannel, uint flags, const QSVECTOR &velocity); + + /** + * Plays sound + * @param iChannel The channel number to be played on + * @param flags Play flags + * @param mixWave Data for the sound to be played + * @param loops Number of loops to play (-1 for forever) + * @param params Playback parameter data + */ + int qsWaveMixPlayEx(int iChannel, uint flags, CWaveFile *waveFile, int loops, const QMIXPLAYPARAMS ¶ms); + + /** + * Returns true if there are no more buffers playing or queued on the channel + */ + bool qsWaveMixIsChannelDone(int iChannel) const; + + /** + * Handles regularly updating the mixer + */ + void qsWaveMixPump(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_QMIXER_H */ diff --git a/engines/titanic/sound/restricted_auto_music_player.cpp b/engines/titanic/sound/restricted_auto_music_player.cpp new file mode 100644 index 0000000000..2384d4da25 --- /dev/null +++ b/engines/titanic/sound/restricted_auto_music_player.cpp @@ -0,0 +1,79 @@ +/* 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/sound/restricted_auto_music_player.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CRestrictedAutoMusicPlayer, CAutoMusicPlayer) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) +END_MESSAGE_MAP() + +void CRestrictedAutoMusicPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_oldNodeName, indent); + file->writeQuotedLine(_newNodeName, indent); + file->writeQuotedLine(_newRoomName, indent); + file->writeQuotedLine(_oldRoomName, indent); + + CAutoMusicPlayer::save(file, indent); +} + +void CRestrictedAutoMusicPlayer::load(SimpleFile *file) { + file->readNumber(); + _oldNodeName = file->readString(); + _newNodeName = file->readString(); + _newRoomName = file->readString(); + _oldRoomName = file->readString(); + + CAutoMusicPlayer::load(file); +} + +bool CRestrictedAutoMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) { + if (!msg->_oldRoom) + return true; + if (petCheckNode(_oldNodeName)) + return false; + + CString roomName = msg->_oldRoom->getName(); + if (_oldRoomName.compareToIgnoreCase(roomName)) { + _isRepeated = true; + return false; + } else { + return CAutoMusicPlayer::EnterRoomMsg(msg); + } +} + +bool CRestrictedAutoMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) { + CString roomName = msg->_newRoom->getName(); + + if (petCheckNode(_newNodeName) || _newRoomName.compareToIgnoreCase(roomName)) { + _isRepeated = false; + return true; + } else { + return CAutoMusicPlayer::LeaveRoomMsg(msg); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/restricted_auto_music_player.h b/engines/titanic/sound/restricted_auto_music_player.h new file mode 100644 index 0000000000..d36ee5a7ab --- /dev/null +++ b/engines/titanic/sound/restricted_auto_music_player.h @@ -0,0 +1,56 @@ +/* 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_RESTRICTED_AUTO_MUSIC_PLAYER_H +#define TITANIC_RESTRICTED_AUTO_MUSIC_PLAYER_H + +#include "titanic/sound/auto_music_player.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CRestrictedAutoMusicPlayer : public CAutoMusicPlayer { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *msg); +private: + CString _oldNodeName; + CString _newNodeName; + CString _newRoomName; + CString _oldRoomName; +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_RESTRICTED_AUTO_MUSIC_PLAYER_H */ diff --git a/engines/titanic/sound/room_auto_sound_player.cpp b/engines/titanic/sound/room_auto_sound_player.cpp new file mode 100644 index 0000000000..cad7c10771 --- /dev/null +++ b/engines/titanic/sound/room_auto_sound_player.cpp @@ -0,0 +1,62 @@ +/* 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/sound/room_auto_sound_player.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CRoomAutoSoundPlayer, CAutoSoundPlayer) + ON_MESSAGE(EnterRoomMsg) + ON_MESSAGE(LeaveRoomMsg) +END_MESSAGE_MAP() + +void CRoomAutoSoundPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CAutoSoundPlayer::save(file, indent); +} + +void CRoomAutoSoundPlayer::load(SimpleFile *file) { + file->readNumber(); + CAutoSoundPlayer::load(file); +} + +bool CRoomAutoSoundPlayer::EnterRoomMsg(CEnterRoomMsg *msg) { + CRoomItem *room = findRoom(); + if (room == msg->_newRoom) { + CTurnOn onMsg; + onMsg.execute(this); + } + + return true; +} + +bool CRoomAutoSoundPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) { + CRoomItem *room = findRoom(); + if (room == msg->_oldRoom) { + CTurnOff offMsg; + offMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/room_auto_sound_player.h b/engines/titanic/sound/room_auto_sound_player.h new file mode 100644 index 0000000000..56525ccfa3 --- /dev/null +++ b/engines/titanic/sound/room_auto_sound_player.h @@ -0,0 +1,51 @@ +/* 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_ROOM_AUTO_SOUND_PLAYER_H +#define TITANIC_ROOM_AUTO_SOUND_PLAYER_H + +#include "titanic/sound/auto_sound_player.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CRoomAutoSoundPlayer : public CAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool EnterRoomMsg(CEnterRoomMsg *msg); + bool LeaveRoomMsg(CLeaveRoomMsg *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_ROOM_AUTO_SOUND_PLAYER_H */ diff --git a/engines/titanic/sound/room_trigger_auto_music_player.cpp b/engines/titanic/sound/room_trigger_auto_music_player.cpp new file mode 100644 index 0000000000..7782cef0e2 --- /dev/null +++ b/engines/titanic/sound/room_trigger_auto_music_player.cpp @@ -0,0 +1,62 @@ +/* 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/sound/room_trigger_auto_music_player.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CRoomTriggerAutoMusicPlayer, CTriggerAutoMusicPlayer) + ON_MESSAGE(LeaveRoomMsg) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +void CRoomTriggerAutoMusicPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + CTriggerAutoMusicPlayer::save(file, indent); +} + +void CRoomTriggerAutoMusicPlayer::load(SimpleFile *file) { + file->readNumber(); + CTriggerAutoMusicPlayer::load(file); +} + +bool CRoomTriggerAutoMusicPlayer::LeaveRoomMsg(CLeaveRoomMsg *msg) { + if (msg->_oldRoom == findRoom()) { + CTriggerAutoMusicPlayerMsg triggerMsg; + triggerMsg._value = 1; + triggerMsg.execute(this); + } + + return true; +} + +bool CRoomTriggerAutoMusicPlayer::EnterRoomMsg(CEnterRoomMsg *msg) { + if (msg->_newRoom == findRoom()) { + CTriggerAutoMusicPlayerMsg triggerMsg; + triggerMsg._value = 2; + triggerMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/room_trigger_auto_music_player.h b/engines/titanic/sound/room_trigger_auto_music_player.h new file mode 100644 index 0000000000..a57e133eb6 --- /dev/null +++ b/engines/titanic/sound/room_trigger_auto_music_player.h @@ -0,0 +1,51 @@ +/* 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_ROOM_TRIGGER_AUTO_MUSIC_PLAYER_H +#define TITANIC_ROOM_TRIGGER_AUTO_MUSIC_PLAYER_H + +#include "titanic/sound/trigger_auto_music_player.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CRoomTriggerAutoMusicPlayer : public CTriggerAutoMusicPlayer { + DECLARE_MESSAGE_MAP; + bool LeaveRoomMsg(CLeaveRoomMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *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_ROOM_TRIGGER_AUTO_MUSIC_PLAYER_H */ diff --git a/engines/titanic/sound/season_noises.cpp b/engines/titanic/sound/season_noises.cpp new file mode 100644 index 0000000000..ce045488ee --- /dev/null +++ b/engines/titanic/sound/season_noises.cpp @@ -0,0 +1,115 @@ +/* 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/sound/season_noises.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSeasonNoises, CViewAutoSoundPlayer) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(ActMsg) + ON_MESSAGE(LoadSuccessMsg) +END_MESSAGE_MAP() + +CSeasonNoises::CSeasonNoises() : CViewAutoSoundPlayer(), _seasonNumber(0), + _springName("NULL"), _summerName("NULL"), _autumnName("NULL"), _winterName("NULL") { +} + +void CSeasonNoises::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_seasonNumber, indent); + file->writeQuotedLine(_springName, indent); + file->writeQuotedLine(_summerName, indent); + file->writeQuotedLine(_autumnName, indent); + file->writeQuotedLine(_winterName, indent); + + CViewAutoSoundPlayer::save(file, indent); +} + +void CSeasonNoises::load(SimpleFile *file) { + file->readNumber(); + _seasonNumber = file->readNumber(); + _springName = file->readString(); + _summerName = file->readString(); + _autumnName = file->readString(); + _winterName = file->readString(); + + CViewAutoSoundPlayer::load(file); +} + +bool CSeasonNoises::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + _seasonNumber = (_seasonNumber + 1) % 4; + CActMsg actMsg("Update"); + actMsg.execute(this); + + return true; +} + +bool CSeasonNoises::EnterViewMsg(CEnterViewMsg *msg) { + CActMsg actMsg("Update"); + return true; +} + +bool CSeasonNoises::ActMsg(CActMsg *msg) { + msg->_action = "Update"; + + switch (_seasonNumber) { + case 0: + _filename = _springName; + break; + case 1: + _filename = _summerName; + break; + case 2: + _filename = _autumnName; + break; + case 3: + _filename = _winterName; + break; + default: + break; + } + + CSignalObject signalMsg; + signalMsg._numValue = 2; + signalMsg.execute(this); + + CTurnOn onMsg; + onMsg.execute(this); + + return true; +} + +bool CSeasonNoises::LoadSuccessMsg(CLoadSuccessMsg *msg) { + if (_active) { + _active = false; + _soundHandle = -1; + + CActMsg actMsg("Update"); + actMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/season_noises.h b/engines/titanic/sound/season_noises.h new file mode 100644 index 0000000000..796628d10d --- /dev/null +++ b/engines/titanic/sound/season_noises.h @@ -0,0 +1,59 @@ +/* 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_SEASON_NOISES_H +#define TITANIC_SEASON_NOISES_H + +#include "titanic/sound/view_auto_sound_player.h" + +namespace Titanic { + +class CSeasonNoises : public CViewAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool EnterViewMsg(CEnterViewMsg *msg); + bool ActMsg(CActMsg *msg); + bool LoadSuccessMsg(CLoadSuccessMsg *msg); +private: + int _seasonNumber; + CString _springName; + CString _summerName; + CString _autumnName; + CString _winterName; +public: + CLASSDEF; + CSeasonNoises(); + + /** + * 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_SEASON_NOISES_H */ diff --git a/engines/titanic/sound/seasonal_music_player.cpp b/engines/titanic/sound/seasonal_music_player.cpp new file mode 100644 index 0000000000..3532311bdf --- /dev/null +++ b/engines/titanic/sound/seasonal_music_player.cpp @@ -0,0 +1,135 @@ +/* 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/sound/seasonal_music_player.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CSeasonalMusicPlayer, CAutoMusicPlayerBase) + ON_MESSAGE(ChangeSeasonMsg) + ON_MESSAGE(ArboretumGateMsg) + ON_MESSAGE(ChangeMusicMsg) +END_MESSAGE_MAP() + +CSeasonalMusicPlayer::CSeasonalMusicPlayer() : CAutoMusicPlayerBase() { + _isSpring = false; + _isSummer = true; + _isAutumn = false; + _isWinter = false; + _springMode = -4; + _summerMode = -2; + _autumnMode = -4; + _winterMode = -4; +} + +void CSeasonalMusicPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_isSpring, indent); + file->writeNumberLine(_isSummer, indent); + file->writeNumberLine(_isAutumn, indent); + file->writeNumberLine(_isWinter, indent); + file->writeNumberLine(_springMode, indent); + file->writeNumberLine(_summerMode, indent); + file->writeNumberLine(_autumnMode, indent); + file->writeNumberLine(_winterMode, indent); + + CAutoMusicPlayerBase::save(file, indent); +} + +void CSeasonalMusicPlayer::load(SimpleFile *file) { + file->readNumber(); + _isSpring = file->readNumber(); + _isSummer = file->readNumber(); + _isAutumn = file->readNumber(); + _isWinter = file->readNumber(); + _springMode = file->readNumber(); + _summerMode = file->readNumber(); + _autumnMode = file->readNumber(); + _winterMode = file->readNumber(); + + CAutoMusicPlayerBase::load(file); +} + +bool CSeasonalMusicPlayer::ChangeSeasonMsg(CChangeSeasonMsg *msg) { + _isSpring = msg->_season == "spring"; + _isSummer = msg->_season == "summer"; + _isAutumn = msg->_season == "autumn"; + _isWinter = msg->_season == "winter"; + + _springMode = _isSpring ? -2 : -4; + _summerMode = _isSummer ? -2 : -4; + _autumnMode = _isAutumn ? -2 : -4; + _winterMode = _isWinter ? -2 : -4; + + CChangeMusicMsg changeMsg; + changeMsg._filename = msg->_season; + changeMsg.execute(this); + + return true; +} + +bool CSeasonalMusicPlayer::ArboretumGateMsg(CArboretumGateMsg *msg) { + CChangeMusicMsg changeMsg; + changeMsg._flags = msg->_value ? 2 : 1; + changeMsg.execute(this); + + return true; +} + +bool CSeasonalMusicPlayer::ChangeMusicMsg(CChangeMusicMsg *msg) { + if (_isRepeated && msg->_flags == 1) { + _isRepeated = false; + stopGlobalSound(_transition, -1); + } + + if (!msg->_filename.empty()) { + if (_isSummer) { + setGlobalSoundVolume(-4, 2, 0); + setGlobalSoundVolume(-2, 2, 1); + } else if (_isAutumn) { + setGlobalSoundVolume(-4, 2, 1); + setGlobalSoundVolume(-2, 2, 2); + } else if (_isWinter) { + setGlobalSoundVolume(-4, 2, 2); + setGlobalSoundVolume(-2, 2, 3); + } else if (_isSpring) { + setGlobalSoundVolume(-4, 2, 3); + setGlobalSoundVolume(-2, 2, 0); + } + } + + if (!_isRepeated && msg->_flags == 2) { + _isRepeated = true; + loadSound("c#64.wav"); + loadSound("c#63.wav"); + loadSound("c#65.wav"); + loadSound("c#62.wav"); + playGlobalSound("c#64.wav", _springMode, _isSpring, true, 0); + playGlobalSound("c#63.wav", _summerMode, _isSummer, true, 1); + playGlobalSound("c#65.wav", _autumnMode, _isAutumn, true, 2); + playGlobalSound("c#62.wav", _winterMode, _isWinter, true, 3); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/seasonal_music_player.h b/engines/titanic/sound/seasonal_music_player.h new file mode 100644 index 0000000000..d6a79d73da --- /dev/null +++ b/engines/titanic/sound/seasonal_music_player.h @@ -0,0 +1,61 @@ +/* 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_SEASONAL_MUSIC_PLAYER_H +#define TITANIC_SEASONAL_MUSIC_PLAYER_H + +#include "titanic/sound/auto_music_player_base.h" + +namespace Titanic { + +class CSeasonalMusicPlayer : public CAutoMusicPlayerBase { + DECLARE_MESSAGE_MAP; + bool ChangeSeasonMsg(CChangeSeasonMsg *msg); + bool ArboretumGateMsg(CArboretumGateMsg *msg); + bool ChangeMusicMsg(CChangeMusicMsg *msg); +private: + bool _isSpring; + bool _isSummer; + bool _isAutumn; + bool _isWinter; + int _springMode; + int _summerMode; + int _autumnMode; + int _winterMode; +public: + CLASSDEF; + CSeasonalMusicPlayer(); + + /** + * 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_SEASONAL_MUSIC_PLAYER_H */ diff --git a/engines/titanic/sound/sound.cpp b/engines/titanic/sound/sound.cpp new file mode 100644 index 0000000000..7e791c2ba5 --- /dev/null +++ b/engines/titanic/sound/sound.cpp @@ -0,0 +1,223 @@ +/* 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/sound/sound.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CSound::CSound(CGameManager *owner, Audio::Mixer *mixer) : + _gameManager(owner), _soundManager(mixer) { + g_vm->_movieManager.setSoundManager(&_soundManager); +} + +void CSound::save(SimpleFile *file) const { + _soundManager.save(file); +} + +void CSound::load(SimpleFile *file) { + _soundManager.load(file); +} + +void CSound::preLoad() { + _soundManager.preLoad(); + + if (_gameManager) + _gameManager->_musicRoom.destroyMusicHandler(); +} + +void CSound::preEnterView(CViewItem *newView, bool isNewRoom) { + CNodeItem *node = newView->findNode(); + double xp, yp, zp; + node->getPosition(xp, yp, zp); + + double cosVal = cos(newView->_angle); + double sinVal = -sin(newView->_angle); + + _soundManager.setListenerPosition(xp, yp, zp, cosVal, sinVal, 0, isNewRoom); +} + +bool CSound::isActive(int handle) const { + if (handle != 0 && handle != -1) + return _soundManager.isActive(handle); + + return false; +} + +void CSound::setVolume(uint handle, uint volume, uint seconds) { + _soundManager.setVolume(handle, volume, seconds); +} + +void CSound::activateSound(CWaveFile *waveFile, bool freeFlag) { + for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) { + CSoundItem *sound = *i; + if (sound->_waveFile == waveFile) { + sound->_active = true; + sound->_freeFlag = freeFlag; + + if (!freeFlag && waveFile->size() > 51200) + sound->_freeFlag = true; + break; + } + } +} + +void CSound::stopChannel(int channel) { + _soundManager.stopChannel(channel); +} + +void CSound::checkSounds() { + for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) { + CSoundItem *soundItem = *i; + if (soundItem->_active && soundItem->_freeFlag) { + if (_soundManager.isActive(soundItem->_waveFile)) { + _sounds.remove(soundItem); + delete soundItem; + } + } + } +} + +void CSound::removeOldest() { + for (CSoundItemList::iterator i = _sounds.reverse_begin(); + i != _sounds.end(); --i) { + CSoundItem *soundItem = *i; + if (soundItem->_active && !_soundManager.isActive(soundItem->_waveFile)) { + _sounds.remove(soundItem); + delete soundItem; + break; + } + } +} + +CWaveFile *CSound::getTrueTalkSound(CDialogueFile *dialogueFile, int index) { + return loadSpeech(dialogueFile, index); +} + +CWaveFile *CSound::loadSound(const CString &name) { + checkSounds(); + + // Check whether an entry for the given name is already active + for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) { + CSoundItem *soundItem = *i; + if (soundItem->_name == name) { + // Found it, so move it to the front of the list and return + _sounds.remove(soundItem); + _sounds.push_front(soundItem); + return soundItem->_waveFile; + } + } + + // Create new sound item + CSoundItem *soundItem = new CSoundItem(name); + soundItem->_waveFile = _soundManager.loadSound(name); + + if (!soundItem->_waveFile) { + // Couldn't load sound, so destroy new item and return + delete soundItem; + return 0; + } + + // Add the item to the list of sounds + _sounds.push_front(soundItem); + + // If there are more than 10 sounds loaded, remove the last one, + // which is the least recently used of all of them + if (_sounds.size() > 10) + removeOldest(); + + return soundItem->_waveFile; +} + +int CSound::playSound(const CString &name, CProximity &prox) { + CWaveFile *waveFile = loadSound(name); + if (!waveFile) + return -1; + + prox._field6C = waveFile->fn1(); + activateSound(waveFile, prox._freeSoundFlag); + + return _soundManager.playSound(*waveFile, prox); +} + +CWaveFile *CSound::loadSpeech(CDialogueFile *dialogueFile, int speechId) { + checkSounds(); + + // Check whether an entry for the given name is already active + for (CSoundItemList::iterator i = _sounds.begin(); i != _sounds.end(); ++i) { + CSoundItem *soundItem = *i; + if (soundItem->_dialogueFileHandle == dialogueFile->getFile() + && soundItem->_speechId == speechId) { + // Found it, so move it to the front of the list and return + _sounds.remove(soundItem); + _sounds.push_front(soundItem); + return soundItem->_waveFile; + } + } + + // Create new sound item + CSoundItem *soundItem = new CSoundItem(dialogueFile->getFile(), speechId); + soundItem->_waveFile = _soundManager.loadSpeech(dialogueFile, speechId); + + if (!soundItem->_waveFile) { + // Couldn't load speech, so destroy new item and return + delete soundItem; + return 0; + } + + // Add the item to the list of sounds + _sounds.push_front(soundItem); + + // If there are more than 10 sounds loaded, remove the last one, + // which is the least recently used of all of them + if (_sounds.size() > 10) + removeOldest(); + + return soundItem->_waveFile; +} + +int CSound::playSpeech(CDialogueFile *dialogueFile, int speechId, CProximity &prox) { + CWaveFile *waveFile = loadSpeech(dialogueFile, speechId); + if (!waveFile) + return -1; + + prox._field6C = waveFile->fn1(); + activateSound(waveFile, prox._freeSoundFlag); + + return _soundManager.playSound(*waveFile, prox); +} + +void CSound::stopSound(uint handle) { + _soundManager.stopSound(handle); +} + +void CSound::setCanFree(int handle) { + if (handle != 0 && handle != -1) + _soundManager.setCanFree(handle); +} + +void CSound::updateMixer() { + _soundManager.waveMixPump(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/sound.h b/engines/titanic/sound/sound.h new file mode 100644 index 0000000000..de95f9edf1 --- /dev/null +++ b/engines/titanic/sound/sound.h @@ -0,0 +1,190 @@ +/* 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_SOUND_H +#define TITANIC_SOUND_H + +#include "titanic/support/simple_file.h" +#include "titanic/sound/proximity.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/sound/wave_file.h" +#include "titanic/core/list.h" +#include "titanic/core/view_item.h" +#include "titanic/true_talk/dialogue_file.h" + +namespace Titanic { + +class CGameManager; + +class CSoundItem : public ListItem { +public: + CString _name; + CWaveFile *_waveFile; + File *_dialogueFileHandle; + int _speechId; + bool _freeFlag; + bool _active; +public: + CSoundItem() : ListItem(), _waveFile(nullptr), _dialogueFileHandle(nullptr), + _speechId(0), _freeFlag(false), _active(false) {} + CSoundItem(const CString &name) : ListItem(), _name(name), _waveFile(nullptr), + _dialogueFileHandle(nullptr), _speechId(0), _freeFlag(false), _active(false) {} + CSoundItem(File *dialogueFile, int speechId) : ListItem(), _waveFile(nullptr), + _dialogueFileHandle(dialogueFile), _speechId(speechId), _freeFlag(false), _active(false) {} +}; + +class CSoundItemList : public List<CSoundItem> { +}; + +class CSound { +private: + CGameManager *_gameManager; + CSoundItemList _sounds; +private: + /** + * Check whether any sounds are done and can be be removed + */ + void checkSounds(); + + /** + * Removes the oldest sound from the sounds list that isn't + * currently playing + */ + void removeOldest(); +public: + QSoundManager _soundManager; +public: + CSound(CGameManager *owner, Audio::Mixer *mixer); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file) const; + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file); + + /** + * Called when a game is about to be loaded + */ + void preLoad(); + + /** + * Called when loading a game is complete + */ + void postLoad() { _soundManager.postLoad(); } + + /** + * Called when a game is about to be saved + */ + void preSave() { _soundManager.preSave(); } + + /** + * Called when a game has finished being saved + */ + void postSave() { _soundManager.postSave(); } + + /** + * Called when the view has been changed + */ + void preEnterView(CViewItem *newView, bool isNewRoom); + + /** + * Returns true if a sound with the specified handle is active + */ + bool isActive(int handle) const; + + /** + * Sets the volume for a sound + * @param handle Sound handle + * @param volume Volume percentage (0 to 100) + * @param seconds Number of seconds to transition to the new volume + */ + void setVolume(uint handle, uint volume, uint seconds); + + /** + * Flags a sound about to be played as activated + */ + void activateSound(CWaveFile *waveFile, bool freeFlag); + + /** + * Stops any sounds attached to a given channel + */ + void stopChannel(int channel); + + /** + * Loads a TrueTalk dialogue + * @param dialogueFile Dialogue file reference + * @param speechId Speech Id within dialogue + * @returns Wave file instance + */ + CWaveFile *getTrueTalkSound(CDialogueFile *dialogueFile, int index); + + /** + * Load a speech resource + * @param dialogueFile Dialogue file reference + * @param speechId Speech Id within dialogue + * @returns Wave file instance + */ + CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId); + + /** + * Play a speech + * @param dialogueFile Dialogue file reference + * @param speechId Speech Id within dialogue + * @param prox Proximity instance + */ + int playSpeech(CDialogueFile *dialogueFile, int speechId, CProximity &prox); + + /** + * Load a sound + * @param name Name of sound resource + * @returns Sound item record + */ + CWaveFile *loadSound(const CString &name); + + /** + * Play a sound + */ + int playSound(const CString &name, CProximity &prox); + + /** + * Stop a sound + */ + void stopSound(uint handle); + + /** + * Flags that a sound can be freed if a timeout is set + */ + void setCanFree(int handle); + + /** + * Handles regularly updating the mixer + */ + void updateMixer(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SOUND_H */ diff --git a/engines/titanic/sound/sound_manager.cpp b/engines/titanic/sound/sound_manager.cpp new file mode 100644 index 0000000000..ae806feb52 --- /dev/null +++ b/engines/titanic/sound/sound_manager.cpp @@ -0,0 +1,481 @@ +/* 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/sound/sound_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +const uint SAMPLING_RATE = 22050; +const uint LATENCY = 100; +const uint CHANNELS_COUNT = 16; + +CSoundManager::CSoundManager() : _musicPercent(75.0), _speechPercent(75.0), + _masterPercent(75.0), _parrotPercent(75.0), _handleCtr(1) { +} + +uint CSoundManager::getModeVolume(int mode) { + switch (mode) { + case -1: + return (uint)_masterPercent; + case -2: + return (uint)(_masterPercent * 30 / 100); + case -3: + return (uint)(_masterPercent * 15 / 100); + default: + return 0; + } +} + +/*------------------------------------------------------------------------*/ + +void QSoundManagerSounds::add(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker) { + push_back(new QSoundManagerSound(waveFile, iChannel, endFn, talker)); +} + +void QSoundManagerSounds::flushChannel(int iChannel) { + for (iterator i = begin(); i != end(); ++i) { + QSoundManagerSound *item = *i; + if (item->_iChannel == iChannel) { + if (item->_endFn) + item->_endFn(item->_talker); + + remove(item); + delete item; + break; + } + } +} + +void QSoundManagerSounds::flushChannel(CWaveFile *waveFile, int iChannel) { + for (iterator i = begin(); i != end(); ++i) { + QSoundManagerSound *item = *i; + if (item->_waveFile->isLoaded() && item->_iChannel == iChannel) { + if (item->_endFn) + item->_endFn(item->_talker); + + remove(item); + delete item; + break; + } + } +} + +bool QSoundManagerSounds::contains(const CWaveFile *waveFile) const { + for (const_iterator i = begin(); i != end(); ++i) { + const QSoundManagerSound *item = *i; + if (item->_waveFile == waveFile) + return true; + } + + return false; +} + +/*------------------------------------------------------------------------*/ + +void QSoundManager::Slot::clear() { + _waveFile = nullptr; + _isTimed = false; + _ticks = 0; + _channel = -1; + _handle = 0; + _positioningMode = POSMODE_NONE; +} + +/*------------------------------------------------------------------------*/ + +QSoundManager::QSoundManager(Audio::Mixer *mixer) : CSoundManager(), QMixer(mixer), + _field18(0), _field1C(0) { + _slots.resize(48); + Common::fill(&_channelsVolume[0], &_channelsVolume[16], 0); + Common::fill(&_channelsMode[0], &_channelsMode[16], 0); + + qsWaveMixInitEx(QMIXCONFIG(SAMPLING_RATE, CHANNELS_COUNT, LATENCY)); + qsWaveMixActivate(true); + qsWaveMixOpenChannel(0, QMIX_OPENALL); +} + +QSoundManager::~QSoundManager() { + // Close down the mixer + qsWaveMixCloseSession(); +} + +CWaveFile *QSoundManager::loadSound(const CString &name) { + CWaveFile *waveFile = new CWaveFile(); + + // Try to load the specified sound + if (!waveFile->loadSound(name)) { + delete waveFile; + return nullptr; + } + + return waveFile; +} + +CWaveFile *QSoundManager::loadSpeech(CDialogueFile *dialogueFile, int speechId) { + CWaveFile *waveFile = new CWaveFile(); + + // Try to load the specified sound + if (!waveFile->loadSpeech(dialogueFile, speechId)) { + delete waveFile; + return nullptr; + } + + return waveFile; +} + +CWaveFile *QSoundManager::loadMusic(const CString &name) { + CWaveFile *waveFile = new CWaveFile(); + + // Try to load the specified sound + if (!waveFile->loadMusic(name)) { + delete waveFile; + return nullptr; + } + + return waveFile; +} + +int QSoundManager::playSound(CWaveFile &waveFile, CProximity &prox) { + int channel = -1; + uint flags = QMIX_CLEARQUEUE; + + if (prox._priorSoundHandle >= 1) { + // This sound should only be started after a prior one finishes, + // so scan the slots for the specified sound + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (_slots[idx]._handle == prox._priorSoundHandle) { + channel = _slots[idx]._channel; + flags = QMIX_QUEUEWAVE; + break; + } + } + } + + if (channel >= 0 || (channel = resetChannel(prox._channel)) != -1) { + return playWave(&waveFile, channel, flags, prox); + } + + return 0; +} + +void QSoundManager::stopSound(int handle) { + resetChannel(10); + + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + qsWaveMixFlushChannel(slot._channel); + _sounds.flushChannel(slot._channel); + resetChannel(10); + } + } +} + +void QSoundManager::stopChannel(int channel) { + int endChannel; + switch (channel) { + case 0: + case 3: + endChannel = channel + 3; + break; + case 6: + endChannel = 10; + break; + case 10: + endChannel = 48; + break; + default: + return; + } + + for (; channel < endChannel; ++channel) { + qsWaveMixFlushChannel(channel); + _sounds.flushChannel(channel); + } +} + +void QSoundManager::setCanFree(int handle) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (_slots[idx]._handle == handle) + _slots[idx]._isTimed = true; + } +} + +void QSoundManager::stopAllChannels() { + qsWaveMixFlushChannel(0, QMIX_OPENALL); + + for (int idx = 0; idx < 16; ++idx) + _sounds.flushChannel(idx); + resetChannel(10); +} + +int QSoundManager::resetChannel(int iChannel) { + int newChannel = -1; + int channelStart = 10; + int channelEnd = 16; + + if (iChannel != 10) { + qsWaveMixFlushChannel(iChannel); + _sounds.flushChannel(iChannel); + channelStart = iChannel; + channelEnd = iChannel + 1; + } else { + uint ticks = g_vm->_events->getTicksCount(); + + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._isTimed && slot._ticks && ticks > slot._ticks) { + qsWaveMixFlushChannel(slot._channel); + _sounds.flushChannel(slot._channel); + } + } + } + + for (iChannel = channelStart; iChannel < channelEnd; ++iChannel) { + if (qsWaveMixIsChannelDone(iChannel)) { + // Scan through the slots, and reset any slot using the channel + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._channel == iChannel) + slot.clear(); + } + + // Use the empty channel + newChannel = iChannel; + } + } + + return newChannel; +} + +void QSoundManager::setVolume(int handle, uint volume, uint seconds) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + _channelsVolume[slot._channel] = volume; + updateVolume(slot._channel, seconds * 1000); + + if (volume) { + uint ticks = g_vm->_events->getTicksCount() + seconds * 1000; + if (!slot._ticks || ticks >= slot._ticks) + slot._ticks = ticks; + } else { + slot._ticks = 0; + } + break; + } + } +} + +void QSoundManager::setVectorPosition(int handle, double x, double y, double z, uint panRate) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + qsWaveMixSetPanRate(slot._channel, QMIX_USEONCE, panRate); + qsWaveMixSetSourcePosition(slot._channel, QMIX_USEONCE, QSVECTOR(x, y, z)); + break; + } + } +} + +void QSoundManager::setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) { + for (uint idx = 0; idx < _slots.size(); ++idx) { + Slot &slot = _slots[idx]; + if (slot._handle == handle) { + qsWaveMixSetPanRate(slot._channel, QMIX_USEONCE, panRate); + qsWaveMixSetPolarPosition(slot._channel, QMIX_USEONCE, + QSPOLAR(azimuth, range, elevation)); + break; + } + } +} + +bool QSoundManager::isActive(int handle) const { + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (_slots[idx]._handle == handle) + return true; + } + + return false; +} + +bool QSoundManager::isActive(const CWaveFile *waveFile) const { + return _sounds.contains(waveFile); +} + +void QSoundManager::waveMixPump() { + qsWaveMixPump(); +} + +uint QSoundManager::getLatency() const { + return LATENCY; +} + +void QSoundManager::setMusicPercent(double percent) { + _musicPercent = percent; + updateVolumes(); +} + +void QSoundManager::setSpeechPercent(double percent) { + _speechPercent = percent; + updateVolumes(); +} + +void QSoundManager::setMasterPercent(double percent) { + _masterPercent = percent; + updateVolumes(); +} + +void QSoundManager::setParrotPercent(double percent) { + _parrotPercent = percent; +} + +void QSoundManager::setListenerPosition(double posX, double posY, double posZ, + double directionX, double directionY, double directionZ, bool stopSounds) { + if (stopSounds) { + // Stop any running sounds + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (_slots[idx]._positioningMode != 0) + stopSound(_slots[idx]._handle); + } + } + + qsWaveMixSetListenerPosition(QSVECTOR(posX, posY, posZ)); + qsWaveMixSetListenerOrientation(QSVECTOR(directionX, directionY, directionZ), + QSVECTOR(0.0, 0.0, -1.0)); +} + +int QSoundManager::playWave(CWaveFile *waveFile, int iChannel, uint flags, CProximity &prox) { + if (!waveFile || !waveFile->isLoaded()) + return 0; + + prox._channelVolume = CLIP(prox._channelVolume, 0, 100); + prox._fieldC = CLIP(prox._fieldC, -100, 100); + + int slotIndex = findFreeSlot(); + if (slotIndex == -1) + return -1; + + switch (prox._positioningMode) { + case POSMODE_POLAR: + qsWaveMixSetPolarPosition(iChannel, 8, QSPOLAR(prox._azimuth, prox._range, prox._elevation)); + qsWaveMixEnableChannel(iChannel, QMIX_CHANNEL_ELEVATION, true); + qsWaveMixSetDistanceMapping(iChannel, 8, QMIX_DISTANCES(5.0, 3.0, 1.0)); + break; + + case POSMODE_VECTOR: + qsWaveMixSetSourcePosition(iChannel, 8, QSVECTOR(prox._posX, prox._posY, prox._posZ)); + qsWaveMixEnableChannel(iChannel, QMIX_CHANNEL_ELEVATION, true); + qsWaveMixSetDistanceMapping(iChannel, 8, QMIX_DISTANCES(5.0, 3.0, 1.0)); + break; + + default: + qsWaveMixEnableChannel(iChannel, QMIX_CHANNEL_ELEVATION, true); + qsWaveMixSetPolarPosition(iChannel, 8, QSPOLAR(0.0, 1.0, 0.0)); + break; + } + + if (prox._frequencyMultiplier || prox._field1C != 1.875) { + uint freq = (uint)(waveFile->getFrequency() * prox._frequencyMultiplier); + qsWaveMixSetFrequency(iChannel, 8, freq); + } + + _sounds.add(waveFile, iChannel, prox._endTalkerFn, prox._talker); + + QMIXPLAYPARAMS playParams; + playParams.callback = soundFinished; + playParams.dwUser = this; + if (!qsWaveMixPlayEx(iChannel, flags, waveFile, prox._repeated ? -1 : 0, playParams)) { + Slot &slot = _slots[slotIndex]; + slot._handle = _handleCtr++; + slot._channel = iChannel; + slot._waveFile = waveFile; + slot._positioningMode = prox._positioningMode; + + return slot._handle; + } else { + _sounds.flushChannel(waveFile, iChannel); + if (prox._freeSoundFlag) + delete waveFile; + return 0; + } +} + +void QSoundManager::soundFreed(Audio::SoundHandle &handle) { + qsWaveMixFreeWave(handle); +} + +void QSoundManager::updateVolume(int channel, uint panRate) { + uint volume = _channelsVolume[channel] * 327; + + switch (_channelsMode[channel]) { + case 0: + case 1: + case 2: + volume = (_speechPercent * volume) / 100; + break; + case 3: + case 4: + case 5: + volume = (24525 * volume) / 100; + break; + case 6: + case 7: + case 8: + case 9: + volume = (_masterPercent * volume) / 100; + break; + default: + break; + } + + volume = (_musicPercent * volume) / 100; + qsWaveMixSetPanRate(channel, 0, panRate); + qsWaveMixSetVolume(channel, 0, volume); +} + +void QSoundManager::updateVolumes() { + for (uint idx = 0; idx < CHANNELS_COUNT; ++idx) + updateVolume(idx, 250); +} + +void QSoundManager::soundFinished(int iChannel, CWaveFile *waveFile, void *soundManager) { + static_cast<QSoundManager *>(soundManager)->_sounds.flushChannel(waveFile, iChannel); +} + +int QSoundManager::findFreeSlot() { + for (uint idx = 0; idx < _slots.size(); ++idx) { + if (!_slots[idx]._waveFile) + return idx; + } + + return -1; +} + +void QSoundManager::setChannelVolume(int iChannel, uint volume, uint mode) { + _channelsVolume[iChannel] = volume; + _channelsMode[iChannel] = mode; + updateVolume(iChannel, 250); +} + +} // End of namespace Titanic z diff --git a/engines/titanic/sound/sound_manager.h b/engines/titanic/sound/sound_manager.h new file mode 100644 index 0000000000..d1afdb4ad4 --- /dev/null +++ b/engines/titanic/sound/sound_manager.h @@ -0,0 +1,454 @@ +/* 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_SOUND_MANAGER_H +#define TITANIC_SOUND_MANAGER_H + +#include "titanic/core/list.h" +#include "titanic/support/simple_file.h" +#include "titanic/sound/proximity.h" +#include "titanic/sound/qmixer.h" +#include "titanic/sound/wave_file.h" +#include "titanic/true_talk/dialogue_file.h" + +namespace Titanic { + +/** + * Abstract interface class for a sound manager + */ +class CSoundManager { +protected: + double _musicPercent; + double _speechPercent; + double _masterPercent; + double _parrotPercent; + uint _handleCtr; +public: + CSoundManager(); + virtual ~CSoundManager() {} + + /** + * Loads a sound + * @param name Name of sound resource + * @returns Loaded wave file + */ + virtual CWaveFile *loadSound(const CString &name) { return nullptr; } + + /** + * Loads a speech resource from a dialogue file + * @param name Name of sound resource + * @returns Loaded wave file + */ + virtual CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId) { return 0; } + + /** + * Loads a music file + * @param name Name of music resource + * @returns Loaded wave file + * @remarks The original created a streaming audio buffer for the wave file, + * and passed this to the method. For ScummVM, this has been discarded + * in favor of simply passing the filename. + */ + virtual CWaveFile *loadMusic(const CString &name) { return nullptr; } + + /** + * Start playing a previously loaded wave file + */ + virtual int playSound(CWaveFile &waveFile, CProximity &prox) = 0; + + /** + * Stop playing the specified sound + */ + virtual void stopSound(int handle) = 0; + + /** + * Stops a designated range of channels + */ + virtual void stopChannel(int channel) = 0; + + virtual void proc9(int handle) {} + + /** + * Stops sounds on all playing channels + */ + virtual void stopAllChannels() = 0; + + /** + * Sets the volume for a sound + * @param handle Handle for sound + * @param volume New volume + * @param seconds Number of seconds to transition to the new volume + */ + virtual void setVolume(int handle, uint volume, uint seconds) = 0; + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param x x position in metres + * @param y y position in metres + * @param z z position in metres + * @param panRate Rate in milliseconds to transition + */ + virtual void setVectorPosition(int handle, double x, double y, double z, uint panRate) {} + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param range Range value in metres + * @param azimuth Azimuth value in degrees + * @param elevation Elevation value in degrees + * @param panRate Rate in milliseconds to transition + */ + virtual void setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate) {} + + /** + * Returns true if the given sound is currently active + */ + virtual bool isActive(int handle) const = 0; + + /** + * Returns true if the given sound is currently active + */ + virtual bool isActive(const CWaveFile *waveFile) const { return false; } + + /** + * Handles regularly updating the mixer + */ + virtual void waveMixPump() = 0; + + /** + * Returns the movie latency + */ + virtual uint getLatency() const { return 0; } + + /** + * Sets the music volume percent + */ + virtual void setMusicPercent(double percent) = 0; + + /** + * Sets the speech volume percent + */ + virtual void setSpeechPercent(double percent) = 0; + + /** + * Sets the master volume percent + */ + virtual void setMasterPercent(double percent) = 0; + + /** + * Sets the Parrot NPC volume percent + */ + virtual void setParrotPercent(double percent) = 0; + + /** + * Called when a game is about to be loaded + */ + virtual void preLoad() { stopAllChannels(); } + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file) {} + + /** + * Called after loading of a game is completed + */ + virtual void postLoad() {} + + /** + * Called when a game is about to be saved + */ + virtual void preSave() {} + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file) const {} + + /** + * Called after saving is complete + */ + virtual void postSave() {} + + /** + * Sets the position and orientation for the listener (player) + */ + virtual void setListenerPosition(double posX, double posY, double posZ, + double directionX, double directionY, double directionZ, bool stopSounds) {} + + /** + * Returns the music volume percent + */ + double getMusicVolume() const { return _musicPercent; } + + /** + * Returns the speech volume percent + */ + double getSpeechVolume() const { return _speechPercent; } + + /** + * Returns the parrot volume percent + */ + double getParrotVolume() const { return _parrotPercent; } + + /** + * Gets the volume for a given mode? value + */ + uint getModeVolume(int mode); +}; + +class QSoundManagerSound : public ListItem { +public: + CWaveFile *_waveFile; + int _iChannel; + CEndTalkerFn _endFn; + TTtalker *_talker; +public: + QSoundManagerSound() : ListItem(), _waveFile(nullptr), + _iChannel(0), _endFn(nullptr), _talker(nullptr) {} + QSoundManagerSound(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker) : + ListItem(), _waveFile(waveFile), _iChannel(iChannel), _endFn(endFn), _talker(talker) {} +}; + +class QSoundManagerSounds : public List<QSoundManagerSound> { +public: + /** + * Adds a new sound entry to the list + */ + void add(CWaveFile *waveFile, int iChannel, CEndTalkerFn endFn, TTtalker *talker); + + /** + * Flushes a wave file attached to the specified channel + */ + void flushChannel(int iChannel); + + /** + * Flushes a wave file attached to the specified channel + */ + void flushChannel(CWaveFile *waveFile, int iChannel); + + /** + * Returns true if the list contains the specified wave file + */ + bool contains(const CWaveFile *waveFile) const; +}; + +/** + * Concrete sound manager class that handles interfacing with + * the QMixer sound mixer class + */ +class QSoundManager : public CSoundManager, public QMixer { + struct Slot { + CWaveFile *_waveFile; + bool _isTimed; + uint _ticks; + int _channel; + int _handle; + PositioningMode _positioningMode; + + Slot() : _waveFile(0), _isTimed(0), _ticks(0), _channel(-1), + _handle(0), _positioningMode(POSMODE_NONE) {} + void clear(); + }; +private: + QSoundManagerSounds _sounds; + Common::Array<Slot> _slots; + uint _channelsVolume[16]; + int _channelsMode[16]; +private: + /** + * Updates the volume for a channel + * @param channel Channel to be update + * @param panRate Time in milliseconds for change to occur + */ + void updateVolume(int channel, uint panRate); + + /** + * Updates all the volumes + */ + void updateVolumes(); + + /** + * Called by the QMixer when a sound finishes playing + */ + static void soundFinished(int iChannel, CWaveFile *waveFile, void *soundManager); + + /** + * Finds the first free slot + */ + int findFreeSlot(); + + /** + * Sets a channel volume + */ + void setChannelVolume(int iChannel, uint volume, uint mode); + + /** + * Resets the specified channel and returns a new free one + */ + int resetChannel(int iChannel); +public: + int _field18; + int _field1C; + +public: + QSoundManager(Audio::Mixer *mixer); + virtual ~QSoundManager(); + + /** + * Loads a sound + * @param name Name of sound resource + * @returns Loaded wave file + */ + virtual CWaveFile *loadSound(const CString &name); + + /** + * Loads a speech resource from a dialogue file + * @param name Name of sound resource + * @returns Loaded wave file + */ + virtual CWaveFile *loadSpeech(CDialogueFile *dialogueFile, int speechId); + + /** + * Loads a music file + * @param name Name of music resource + * @returns Loaded wave file + * @remarks The original created a streaming audio buffer for the wave file, + * and passed this to the method. For ScummVM, this has been discarded + * in favor of simply passing the filename. + */ + virtual CWaveFile *loadMusic(const CString &name); + + /** + * Start playing a previously loaded sound resource + */ + virtual int playSound(CWaveFile &waveFile, CProximity &prox); + + /** + * Stop playing the specified sound + */ + virtual void stopSound(int handle); + + /** + * Stops a designated range of channels + */ + virtual void stopChannel(int channel); + + /** + * Flags that a sound can be freed if a timeout is set + */ + virtual void setCanFree(int handle); + + /** + * Stops sounds on all playing channels + */ + virtual void stopAllChannels(); + + /** + * Sets the volume for a sound + * @param handle Handle for sound + * @param volume New volume + * @param seconds Number of seconds to transition to the new volume + */ + virtual void setVolume(int handle, uint volume, uint seconds); + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param x x position in metres + * @param y y position in metres + * @param z z position in metres + * @param panRate Rate in milliseconds to transition + */ + virtual void setVectorPosition(int handle, double x, double y, double z, uint panRate); + + /** + * Set the position for a sound + * @param handle Handle for sound + * @param range Range value in metres + * @param azimuth Azimuth value in degrees + * @param elevation Elevation value in degrees + * @param panRate Rate in milliseconds to transition + */ + virtual void setPolarPosition(int handle, double range, double azimuth, double elevation, uint panRate); + + /** + * Returns true if the given sound is currently active + */ + virtual bool isActive(int handle) const; + + /** + * Returns true if the given sound is currently active + */ + virtual bool isActive(const CWaveFile *waveFile) const; + + /** + * Handles regularly updating the mixer + */ + virtual void waveMixPump(); + + /** + * Returns the movie latency + */ + virtual uint getLatency() const; + + /** + * Sets the music volume percent + */ + virtual void setMusicPercent(double percent); + + /** + * Sets the speech volume percent + */ + virtual void setSpeechPercent(double percent); + + /** + * Sets the master volume percent + */ + virtual void setMasterPercent(double percent); + + /** + * Sets the Parrot NPC volume percent + */ + virtual void setParrotPercent(double percent); + + /** + * Sets the position and orientation for the listener (player) + */ + virtual void setListenerPosition(double posX, double posY, double posZ, + double directionX, double directionY, double directionZ, bool stopSounds); + + /** + * Starts a wave file playing + */ + virtual int playWave(CWaveFile *waveFile, int iChannel, uint flags, CProximity &prox); + + /** + * Called when a wave file is freed + */ + void soundFreed(Audio::SoundHandle &handle); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_QSOUND_MANAGER_H */ diff --git a/engines/titanic/sound/titania_speech.cpp b/engines/titanic/sound/titania_speech.cpp new file mode 100644 index 0000000000..a07cc79334 --- /dev/null +++ b/engines/titanic/sound/titania_speech.cpp @@ -0,0 +1,157 @@ +/* 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/sound/titania_speech.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CTitaniaSpeech, CGameObject) + ON_MESSAGE(ActMsg) + ON_MESSAGE(MovieEndMsg) + ON_MESSAGE(MovieFrameMsg) + ON_MESSAGE(TimerMsg) + ON_MESSAGE(EnterRoomMsg) +END_MESSAGE_MAP() + +void CTitaniaSpeech::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_paraNum, indent); + file->writeNumberLine(_frameNum, indent); + + CGameObject::save(file, indent); +} + +void CTitaniaSpeech::load(SimpleFile *file) { + file->readNumber(); + _paraNum = file->readNumber(); + _frameNum = file->readNumber(); + + CGameObject::load(file); +} + +bool CTitaniaSpeech::ActMsg(CActMsg *msg) { + CSetFrameMsg frameMsg; + CVisibleMsg visibleMsg; + CActMsg actMsg; + + if (msg->_action == "TitaniaSpeech") { + switch (_paraNum) { + case 0: + movieSetAudioTiming(true); + loadSound("a#12.wav"); + sleep(1000); + playMovie(0, 187, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + movieEvent(0); + break; + + case 1: + loadSound("a#11.wav"); + addTimer(0); + startAnimTimer("Para2", 300); + addTimer(6000); + addTimer(12000); + addTimer(18000); + addTimer(24000); + startAnimTimer("NextPara", 30000); + break; + + case 2: + visibleMsg._visible = false; + visibleMsg.execute("TitaniaStillControl"); + loadSound("a#10.wav"); + playMovie(585, 706, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + playSound("a#10.wav"); + break; + + case 3: + visibleMsg._visible = false; + visibleMsg.execute("TitaniaStillControl"); + loadSound("a#9.wav"); + playMovie(707, 905, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + playSound("a#9.wav"); + break; + + case 4: + visibleMsg._visible = false; + visibleMsg.execute("TitaniaStillControl"); + loadSound("a#8.wav"); + playMovie(906, 938, MOVIE_GAMESTATE || MOVIE_NOTIFY_OBJECT); + playSound("a#8.wav"); + break; + + default: + sleep(3000); + actMsg._action = "SleepTitania"; + actMsg.execute(this); + } + } + + return true; +} + +bool CTitaniaSpeech::MovieEndMsg(CMovieEndMsg *msg) { + if (_paraNum == 5) { + startAnimTimer("NextPara", 0); + } else { + if (_paraNum != 1) + addTimer(0); + startAnimTimer("NextPara", 3000); + } + + return true; +} + +bool CTitaniaSpeech::MovieFrameMsg(CMovieFrameMsg *msg) { + int frame = getMovieFrame(); + if (!frame) + playSound("a#12.wav"); + + return true; +} + +bool CTitaniaSpeech::TimerMsg(CTimerMsg *msg) { + CSetFrameMsg frameMsg; + CVisibleMsg visibleMsg; + CActMsg actMsg("TitaniaSpeech"); + + if (msg->_action == "NextPara") { + visibleMsg.execute("TitaniaStillControl"); + ++_paraNum; + actMsg.execute(this); + } else if (msg->_action == "Para2") { + playSound("a#11.wav"); + } else { + frameMsg._frameNumber = _frameNum; + frameMsg.execute("TitaniaStillControl"); + } + + return true; +} + +bool CTitaniaSpeech::EnterRoomMsg(CEnterRoomMsg *msg) { + CActMsg actMsg("Disable"); + actMsg.execute("ShipAnnouncements"); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/titania_speech.h b/engines/titanic/sound/titania_speech.h new file mode 100644 index 0000000000..2244bb01af --- /dev/null +++ b/engines/titanic/sound/titania_speech.h @@ -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. + * + */ + +#ifndef TITANIC_TITANIA_SPEECH_H +#define TITANIC_TITANIA_SPEECH_H + +#include "titanic/core/game_object.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +class CTitaniaSpeech : public CGameObject { + DECLARE_MESSAGE_MAP; + bool ActMsg(CActMsg *msg); + bool MovieEndMsg(CMovieEndMsg *msg); + bool MovieFrameMsg(CMovieFrameMsg *msg); + bool TimerMsg(CTimerMsg *msg); + bool EnterRoomMsg(CEnterRoomMsg *msg); +private: + int _paraNum, _frameNum; +public: + CLASSDEF; + CTitaniaSpeech() : CGameObject(), _paraNum(1), _frameNum(0) {} + + /** + * 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_TITANIA_SPEECH_H */ diff --git a/engines/titanic/sound/trigger_auto_music_player.cpp b/engines/titanic/sound/trigger_auto_music_player.cpp new file mode 100644 index 0000000000..a332570aba --- /dev/null +++ b/engines/titanic/sound/trigger_auto_music_player.cpp @@ -0,0 +1,61 @@ +/* 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/sound/trigger_auto_music_player.h" +#include "titanic/sound/auto_music_player.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CTriggerAutoMusicPlayer, CGameObject) + ON_MESSAGE(TriggerAutoMusicPlayerMsg) +END_MESSAGE_MAP() + +void CTriggerAutoMusicPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_roomName, indent); + CGameObject::save(file, indent); +} + +void CTriggerAutoMusicPlayer::load(SimpleFile *file) { + file->readNumber(); + _roomName = file->readString(); + CGameObject::load(file); +} + +bool CTriggerAutoMusicPlayer::TriggerAutoMusicPlayerMsg(CTriggerAutoMusicPlayerMsg *msg) { + CRoomItem *room1 = msg->_value == 1 ? locateRoom(_roomName) : findRoom(); + CRoomItem *room2 = msg->_value == 2 ? locateRoom(_roomName) : findRoom(); + + CChangeMusicMsg changeMsg; + changeMsg._flags = 1; + changeMsg.execute(room1, CAutoMusicPlayer::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + + changeMsg._flags = 2; + changeMsg.execute(room2, CAutoMusicPlayer::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/trigger_auto_music_player.h b/engines/titanic/sound/trigger_auto_music_player.h new file mode 100644 index 0000000000..45631e08fc --- /dev/null +++ b/engines/titanic/sound/trigger_auto_music_player.h @@ -0,0 +1,51 @@ +/* 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_TRIGGER_AUTO_MUSIC_PLAYER_H +#define TITANIC_TRIGGER_AUTO_MUSIC_PLAYER_H + +#include "titanic/core/game_object.h" + +namespace Titanic { + +class CTriggerAutoMusicPlayer : public CGameObject { + DECLARE_MESSAGE_MAP; + bool TriggerAutoMusicPlayerMsg(CTriggerAutoMusicPlayerMsg *msg); +protected: + CString _roomName; +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_TRIGGER_AUTO_MUSIC_PLAYER_H */ diff --git a/engines/titanic/sound/view_auto_sound_player.cpp b/engines/titanic/sound/view_auto_sound_player.cpp new file mode 100644 index 0000000000..55501fe340 --- /dev/null +++ b/engines/titanic/sound/view_auto_sound_player.cpp @@ -0,0 +1,84 @@ +/* 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/sound/view_auto_sound_player.h" +#include "titanic/sound/auto_music_player.h" +#include "titanic/core/room_item.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CViewAutoSoundPlayer, CAutoSoundPlayer) + ON_MESSAGE(EnterViewMsg) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +void CViewAutoSoundPlayer::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_enabled, indent); + CAutoSoundPlayer::save(file, indent); +} + +void CViewAutoSoundPlayer::load(SimpleFile *file) { + file->readNumber(); + _enabled = file->readNumber(); + CAutoSoundPlayer::load(file); +} + +bool CViewAutoSoundPlayer::EnterViewMsg(CEnterViewMsg *msg) { + CViewItem *view = findView(); + CRoomItem *room = findRoom(); + + if (view == msg->_newView) { + CTurnOn onMsg; + onMsg.execute(this); + + if (_enabled) { + CChangeMusicMsg changeMsg; + changeMsg._flags = 1; + changeMsg.execute(room, CAutoMusicPlayer::_type, + MSGFLAG_CLASS_DEF |MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + } + } + + return true; +} + +bool CViewAutoSoundPlayer::LeaveViewMsg(CLeaveViewMsg *msg) { + CViewItem *view = findView(); + CRoomItem *room = findRoom(); + + if (view == msg->_oldView) { + CTurnOff offMsg; + offMsg.execute(this); + + if (_enabled) { + CChangeMusicMsg changeMsg; + changeMsg._flags = 2; + changeMsg.execute(room, CAutoMusicPlayer::_type, + MSGFLAG_CLASS_DEF | MSGFLAG_BREAK_IF_HANDLED | MSGFLAG_SCAN); + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/view_auto_sound_player.h b/engines/titanic/sound/view_auto_sound_player.h new file mode 100644 index 0000000000..b62805ea6e --- /dev/null +++ b/engines/titanic/sound/view_auto_sound_player.h @@ -0,0 +1,53 @@ +/* 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_VIEW_AUTO_SOUND_PLAYER_H +#define TITANIC_VIEW_AUTO_SOUND_PLAYER_H + +#include "titanic/sound/auto_sound_player.h" + +namespace Titanic { + +class CViewAutoSoundPlayer : public CAutoSoundPlayer { + DECLARE_MESSAGE_MAP; + bool EnterViewMsg(CEnterViewMsg *msg); + bool LeaveViewMsg(CLeaveViewMsg *msg); +private: + bool _enabled; +public: + CLASSDEF; + CViewAutoSoundPlayer() : CAutoSoundPlayer(), _enabled(false) {} + + /** + * 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_VIEW_AUTO_SOUND_PLAYER_H */ diff --git a/engines/titanic/sound/view_toggles_other_music.cpp b/engines/titanic/sound/view_toggles_other_music.cpp new file mode 100644 index 0000000000..731f59bd53 --- /dev/null +++ b/engines/titanic/sound/view_toggles_other_music.cpp @@ -0,0 +1,58 @@ +/* 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/sound/view_toggles_other_music.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CViewTogglesOtherMusic, CEnterViewTogglesOtherMusic) + ON_MESSAGE(LeaveViewMsg) +END_MESSAGE_MAP() + +CViewTogglesOtherMusic::CViewTogglesOtherMusic() : + CEnterViewTogglesOtherMusic(), _value(1) { +} + +void CViewTogglesOtherMusic::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeNumberLine(_value, indent); + + CEnterViewTogglesOtherMusic::save(file, indent); +} + +void CViewTogglesOtherMusic::load(SimpleFile *file) { + file->readNumber(); + _value = file->readNumber(); + + CEnterViewTogglesOtherMusic::load(file); +} + +bool CViewTogglesOtherMusic::LeaveViewMsg(CLeaveViewMsg *msg) { + if (msg->_oldView == findView()) { + CTriggerAutoMusicPlayerMsg playerMsg(_value); + playerMsg.execute(this); + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/view_toggles_other_music.h b/engines/titanic/sound/view_toggles_other_music.h new file mode 100644 index 0000000000..1b5f110e70 --- /dev/null +++ b/engines/titanic/sound/view_toggles_other_music.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_VIEW_TOGGLES_OTHER_MUSIC_H +#define TITANIC_VIEW_TOGGLES_OTHER_MUSIC_H + +#include "titanic/sound/enter_view_toggles_other_music.h" + +namespace Titanic { + +class CViewTogglesOtherMusic : public CEnterViewTogglesOtherMusic { + DECLARE_MESSAGE_MAP; + bool LeaveViewMsg(CLeaveViewMsg *msg); +private: + int _value; +public: + CLASSDEF; + CViewTogglesOtherMusic(); + + /** + * 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_VIEW_TOGGLES_OTHER_MUSIC_H */ diff --git a/engines/titanic/sound/water_lapping_sounds.cpp b/engines/titanic/sound/water_lapping_sounds.cpp new file mode 100644 index 0000000000..7616c4b43b --- /dev/null +++ b/engines/titanic/sound/water_lapping_sounds.cpp @@ -0,0 +1,56 @@ +/* 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/sound/water_lapping_sounds.h" + +namespace Titanic { + +EMPTY_MESSAGE_MAP(CWaterLappingSounds, CRoomAutoSoundPlayer); + +CWaterLappingSounds::CWaterLappingSounds() : CRoomAutoSoundPlayer(), + _value(0) { + _filename = "z#217.wav"; + _repeated = false; + _startSeconds = 0; +} + +void CWaterLappingSounds::save(SimpleFile *file, int indent) { + file->writeNumberLine(1, indent); + file->writeQuotedLine(_filename, indent); + file->writeNumberLine(_repeated, indent); + file->writeNumberLine(_startSeconds, indent); + file->writeNumberLine(_value, indent); + + CRoomAutoSoundPlayer::save(file, indent); +} + +void CWaterLappingSounds::load(SimpleFile *file) { + file->readNumber(); + _filename = file->readString(); + _repeated = file->readNumber(); + _startSeconds = file->readNumber(); + _value = file->readNumber(); + + CRoomAutoSoundPlayer::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/sound/water_lapping_sounds.h b/engines/titanic/sound/water_lapping_sounds.h new file mode 100644 index 0000000000..2d0594b26b --- /dev/null +++ b/engines/titanic/sound/water_lapping_sounds.h @@ -0,0 +1,51 @@ +/* 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_WATER_LAPPING_SOUNDS_H +#define TITANIC_WATER_LAPPING_SOUNDS_H + +#include "titanic/sound/room_auto_sound_player.h" + +namespace Titanic { + +class CWaterLappingSounds : public CRoomAutoSoundPlayer { + DECLARE_MESSAGE_MAP; +public: + int _value; +public: + CLASSDEF; + CWaterLappingSounds(); + + /** + * 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_WATER_LAPPING_SOUNDS_H */ diff --git a/engines/titanic/sound/wave_file.cpp b/engines/titanic/sound/wave_file.cpp new file mode 100644 index 0000000000..8c00637d73 --- /dev/null +++ b/engines/titanic/sound/wave_file.cpp @@ -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. + * + */ + +#include "audio/decoders/wave.h" +#include "common/memstream.h" +#include "titanic/sound/wave_file.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +CWaveFile::CWaveFile() : _owner(nullptr), _stream(nullptr), + _soundType(Audio::Mixer::kPlainSoundType) { +} + +CWaveFile::CWaveFile(QSoundManager *owner) : _owner(owner), _stream(nullptr), + _soundType(Audio::Mixer::kPlainSoundType) { +} + +CWaveFile::~CWaveFile() { + if (_stream) { + _owner->soundFreed(_soundHandle); + delete _stream; + } +} + +int CWaveFile::fn1() { + // TODO + return 0; +} + +bool CWaveFile::loadSound(const CString &name) { + assert(!_stream); + + StdCWadFile file; + if (!file.open(name)) + return false; + + Common::SeekableReadStream *stream = file.readStream(); + _size = stream->size(); + _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES); + _soundType = Audio::Mixer::kSFXSoundType; + + return true; +} + +bool CWaveFile::loadSpeech(CDialogueFile *dialogueFile, int speechIndex) { + DialogueResource *res = dialogueFile->openWaveEntry(speechIndex); + if (!res) + return false; + + byte *data = (byte *)malloc(res->_size); + dialogueFile->read(res, data, res->_size); + + _size = res->_size; + _stream = Audio::makeWAVStream(new Common::MemoryReadStream(data, _size, DisposeAfterUse::YES), + DisposeAfterUse::YES); + _soundType = Audio::Mixer::kSpeechSoundType; + + return true; +} + +bool CWaveFile::loadMusic(const CString &name) { + assert(!_stream); + + StdCWadFile file; + if (!file.open(name)) + return false; + + Common::SeekableReadStream *stream = file.readStream(); + _size = stream->size(); + _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES); + _soundType = Audio::Mixer::kMusicSoundType; + + return true; +} + +uint CWaveFile::getFrequency() const { + return _stream->getRate(); +} + +} // End of namespace Titanic z diff --git a/engines/titanic/sound/wave_file.h b/engines/titanic/sound/wave_file.h new file mode 100644 index 0000000000..aede0c9328 --- /dev/null +++ b/engines/titanic/sound/wave_file.h @@ -0,0 +1,83 @@ +/* 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_WAVE_FILE_H +#define TITANIC_WAVE_FILE_H + +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "titanic/support/string.h" +#include "titanic/true_talk/dialogue_file.h" + +namespace Titanic { + +class QSoundManager; + +class CWaveFile { +private: + uint _size; +public: + QSoundManager *_owner; + Audio::SeekableAudioStream *_stream; + Audio::SoundHandle _soundHandle; + Audio::Mixer::SoundType _soundType; +public: + CWaveFile(); + CWaveFile(QSoundManager *owner); + ~CWaveFile(); + + int fn1(); + + /** + * Return the size of the wave file + */ + uint size() const { return _size; } + + /** + * Tries to load the specified wave file sound + */ + bool loadSound(const CString &name); + + /** + * Tries to load speech from a specified dialogue file + */ + bool loadSpeech(CDialogueFile *dialogueFile, int speechIndex); + + /** + * Tries to load the specified music wave file + */ + bool loadMusic(const CString &name); + + /** + * Returns true if the wave file has data loaded + */ + bool isLoaded() const { return _stream != nullptr; } + + /** + * Return the frequency of the loaded wave file + */ + uint getFrequency() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_WAVE_FILE_H */ diff --git a/engines/titanic/star_control/base_star.cpp b/engines/titanic/star_control/base_star.cpp new file mode 100644 index 0000000000..f09df38620 --- /dev/null +++ b/engines/titanic/star_control/base_star.cpp @@ -0,0 +1,118 @@ +/* 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/star_control/base_star.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CBaseStarEntry::CBaseStarEntry() : _field0(0), _value(0.0) { + Common::fill(&_data[0], &_data[5], 0); +} + +void CBaseStarEntry::load(Common::SeekableReadStream &s) { + _field0 = s.readByte(); + _field1 = s.readByte(); + _field2 = s.readByte(); + _field3 = s.readByte(); + *((uint32 *)&_value) = s.readUint32LE(); // FIXME + _val._v1 = s.readUint32LE(); + _val._v2 = s.readUint32LE(); + _val._v3 = s.readUint32LE(); + + for (int idx = 0; idx < 5; ++idx) + _data[idx] = s.readUint32LE(); +} + +/*------------------------------------------------------------------------*/ + +CBaseStar::CBaseStar() : _minVal(0.0), _maxVal(1.0), _range(0.0) { +} + +void CBaseStar::draw(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, CStarControlSub5 *sub5) { + // TODO +} + +void CBaseStar::clear() { + _data.clear(); +} + +void CBaseStar::initialize() { + _minVal = 9.9999998e10; + _maxVal = -9.9999998e10; + _sub4.initialize(); + + for (uint idx = 0; idx < _data.size(); ++idx) { + const CBaseStarEntry *entry = getDataPtr(idx); + _sub4.checkEntry(entry->_val); + + if (entry->_value < _minVal) + _minVal = entry->_value; + if (entry->_value > _maxVal) + _maxVal = entry->_value; + } + + _range = (_maxVal - _minVal) / 1.0; +} + +CBaseStarEntry *CBaseStar::getDataPtr(int index) { + return (index >= 0 && index < (int)_data.size()) ? &_data[index] : nullptr; +} + +void CBaseStar::loadData(Common::SeekableReadStream &s) { + uint headerId = s.readUint32LE(); + uint count = s.readUint32LE(); + if (headerId != 100 || count == 0) + error("Invalid star data"); + + // Initialize the data array + clear(); + _data.resize(count); + + // Iterate through reading the data for each entry + for (uint idx = 0; idx < count; ++idx) + _data[idx].load(s); +} + +void CBaseStar::loadData(const CString &resName) { + // Get a stream to read the data from the DAT file + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource(resName); + assert(stream); + + // Load the stream + loadData(*stream); + delete stream; +} + +void CBaseStar::resetEntry(CBaseStarEntry &entry) { + entry._field0 = 0xFF; + entry._field1 = 0xFF; + entry._field2 = 0xFF; + entry._field3 = 0; + entry._val._v1 = 0; + entry._val._v2 = 0; + entry._val._v3 = 0; + for (int idx = 0; idx < 5; ++idx) + entry._data[idx] = 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/base_star.h b/engines/titanic/star_control/base_star.h new file mode 100644 index 0000000000..cf5cbc72d2 --- /dev/null +++ b/engines/titanic/star_control/base_star.h @@ -0,0 +1,110 @@ +/* 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_STAR_CONTROL_SUB3_H +#define TITANIC_STAR_CONTROL_SUB3_H + +#include "titanic/support/simple_file.h" +#include "titanic/star_control/star_control_sub4.h" +#include "titanic/star_control/star_control_sub5.h" +#include "titanic/star_control/surface_area.h" + +namespace Titanic { + +class CStarControlSub12; + +struct CBaseStarEntry { + byte _field0; + byte _field1; + byte _field2; + byte _field3; + double _value; + CBaseStarVal _val; + uint _data[5]; + + CBaseStarEntry(); + void load(Common::SeekableReadStream &s); +}; + +class CBaseStar { +protected: + Common::Array<CBaseStarEntry> _data; + CStarControlSub4 _sub4; + double _minVal; + double _maxVal; + double _range; +protected: + /** + * Get a pointer to a data entry + */ + CBaseStarEntry *getDataPtr(int index); + + /** + * Load entry data from a passed stream + */ + void loadData(Common::SeekableReadStream &s); + + /** + * Load entry data from a specified resource + */ + void loadData(const CString &resName); + + /** + * Reset the data for an entry + */ + void resetEntry(CBaseStarEntry &entry); +public: + CBaseStar(); + virtual ~CBaseStar() {} + + /** + * Draw the item + */ + virtual void draw(CSurfaceArea *surfaceArea, CStarControlSub12 *sub12, CStarControlSub5 *sub5); + + virtual bool loadYale(int v1) { return true; } + virtual bool proc4(int v1, int v2, int v3, int v4, int v5) { return false; } + virtual bool proc5(int v1) { return false; } + virtual bool loadStar() { return false; } + virtual bool proc7(int v1, int v2) { return true; } + + /** + * Load the item's data + */ + virtual void load(SimpleFile *file) {} + + /** + * Save the item's data + */ + virtual void save(SimpleFile *file, int indent) {} + + /** + * Clear allocated data + */ + void clear(); + + void initialize(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB3_H */ diff --git a/engines/titanic/star_control/dmatrix.cpp b/engines/titanic/star_control/dmatrix.cpp new file mode 100644 index 0000000000..70008054b6 --- /dev/null +++ b/engines/titanic/star_control/dmatrix.cpp @@ -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. + * + */ + +#include "titanic/star_control/dmatrix.h" +#include "titanic/star_control/fmatrix.h" +#include "titanic/star_control/star_control_sub26.h" + +namespace Titanic { + +DMatrix *DMatrix::_static; + +DMatrix::DMatrix() : + _row1(1.0, 0.0, 0.0), _row2(0.0, 1.0, 0.0), _row3(0.0, 0.0, 1.0) { +} + +DMatrix::DMatrix(int mode, const FMatrix *src) { + assert(!mode); + + _row1._x = 1.0; + _row2._y = 1.0; + _row3._z = 1.0; + _frow1._x = src->_row1._x; + _frow1._y = src->_row1._y; + _frow1._z = src->_row1._z; + _frow2._x = src->_row2._x; + _frow2._y = src->_row2._y; + _frow2._z = src->_row2._z; +} + +DMatrix::DMatrix(int mode, double val) { + set(mode, val); +} + +void DMatrix::init() { + _static = nullptr; +} + +void DMatrix::deinit() { + delete _static; + _static = nullptr; +} + +void DMatrix::set(int mode, double amount) { + const double FACTOR = 0.0174532925199433; + double sinVal = sin(amount * FACTOR); + double cosVal = cos(amount * FACTOR); + + switch (mode) { + case 0: + _row1._x = 1.0; + _row2._y = cosVal; + _row2._z = sinVal; + _row3._y = -sinVal; + _row3._z = cosVal; + break; + + case 1: + _row1._x = cosVal; + _row1._z = sinVal; + _row2._y = 1.0; + _row3._x = -sinVal; + _row3._z = cosVal; + break; + + case 2: + _row1._x = cosVal; + _row1._y = sinVal; + _row2._x = -sinVal; + _row2._y = cosVal; + _row3._z = 1.0; + break; + + default: + break; + } +} + +void DMatrix::fn3(CStarControlSub26 *sub26) { + double v = sub26->fn1(); + v = (v < 0.0) ? 0.0 : 2.0 / v; + + error("TODO: DMatrix::fn3 %d", (int)v); +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/dmatrix.h b/engines/titanic/star_control/dmatrix.h new file mode 100644 index 0000000000..14f6bb0331 --- /dev/null +++ b/engines/titanic/star_control/dmatrix.h @@ -0,0 +1,65 @@ +/* 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_DMATRIX_H +#define TITANIC_DMATRIX_H + +#include "titanic/star_control/dvector.h" +#include "titanic/star_control/fvector.h" + +namespace Titanic { + +class FMatrix; +class CStarControlSub26; + +/** + * Double based matrix class. + * @remarks TODO: See if it can be merged with FMatrix + */ +class DMatrix { +private: + static DMatrix *_static; +public: + DVector _row1; + DVector _row2; + DVector _row3; + FVector _frow1; + FVector _frow2; +public: + static void init(); + static void deinit(); +public: + DMatrix(); + DMatrix(int mode, const FMatrix *src); + DMatrix(int mode, double val); + + /** + * Sets up data for the matrix + */ + void set(int mode, double amount); + + void fn3(CStarControlSub26 *sub26); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DMATRIX_H */ diff --git a/engines/titanic/star_control/dvector.cpp b/engines/titanic/star_control/dvector.cpp new file mode 100644 index 0000000000..e4c5b15cb0 --- /dev/null +++ b/engines/titanic/star_control/dvector.cpp @@ -0,0 +1,37 @@ +/* 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/star_control/dvector.h" +#include "common/algorithm.h" + +namespace Titanic { + +void DVector::fn3() { + double hyp = sqrt(_x * _x + _y * _y + _z * _z); + assert(hyp); + + _x *= 1.0 / hyp; + _y *= 1.0 / hyp; + _z *= 1.0 / hyp; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/dvector.h b/engines/titanic/star_control/dvector.h new file mode 100644 index 0000000000..7aca407c1c --- /dev/null +++ b/engines/titanic/star_control/dvector.h @@ -0,0 +1,44 @@ +/* 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_DVECTOR_H +#define TITANIC_DVECTOR_H + +namespace Titanic { + +/** + * Double based vector class. + * @remarks TODO: See if it can be merged with FVector + */ +class DVector { +public: + double _x, _y, _z; +public: + DVector() : _x(0), _y(0), _z(0) {} + DVector(double x, double y, double z) : _x(x), _y(y), _z(z) {} + + void fn3(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DVECTOR_H */ diff --git a/engines/titanic/star_control/error_code.h b/engines/titanic/star_control/error_code.h new file mode 100644 index 0000000000..52b0fb9f9e --- /dev/null +++ b/engines/titanic/star_control/error_code.h @@ -0,0 +1,51 @@ +/* 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_ERROR_CODE_H +#define TITANIC_ERROR_CODE_H + +namespace Titanic { + +class CErrorCode { +private: + int _value; +public: + CErrorCode() : _value(0) {} + + /** + * Sets the error code + */ + void set() { _value = 1; } + + /** + * Gets the error code and resets it + */ + int get() { + int result = _value; + _value = 0; + return result; + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_ERROR_CODE_H */ diff --git a/engines/titanic/star_control/fmatrix.cpp b/engines/titanic/star_control/fmatrix.cpp new file mode 100644 index 0000000000..af15477d04 --- /dev/null +++ b/engines/titanic/star_control/fmatrix.cpp @@ -0,0 +1,136 @@ +/* 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/star_control/fmatrix.h" + +namespace Titanic { + +FMatrix::FMatrix() : + _row1(1.0, 0.0, 0.0), _row2(0.0, 1.0, 0.0), _row3(0.0, 0.0, 1.0) { +} + +FMatrix::FMatrix(DMatrix *src) { + copyFrom(src); +} + +FMatrix::FMatrix(FMatrix *src) { + _row1 = src->_row1; + _row2 = src->_row2; + _row3 = src->_row3; +} + +void FMatrix::copyFrom(const DMatrix *src) { + // TODO +} + +void FMatrix::load(SimpleFile *file, int param) { + _row1._x = file->readFloat(); + _row1._y = file->readFloat(); + _row1._z = file->readFloat(); + _row2._x = file->readFloat(); + _row2._y = file->readFloat(); + _row2._z = file->readFloat(); + _row3._x = file->readFloat(); + _row3._y = file->readFloat(); + _row3._z = file->readFloat(); +} + +void FMatrix::save(SimpleFile *file, int indent) { + file->writeFloatLine(_row1._x, indent); + file->writeFloatLine(_row1._y, indent); + file->writeFloatLine(_row1._z, indent); + file->writeFloatLine(_row2._x, indent); + file->writeFloatLine(_row2._y, indent); + file->writeFloatLine(_row2._z, indent); + file->writeFloatLine(_row3._x, indent); + file->writeFloatLine(_row3._y, indent); + file->writeFloatLine(_row3._z, indent); +} + +void FMatrix::clear() { + _row1 = FVector(1.0, 0.0, 0.0); + _row2 = FVector(0.0, 1.0, 0.0); + _row3 = FVector(0.0, 0.0, 1.0); +} + +void FMatrix::set(FVector *row1, FVector *row2, FVector *row3) { + _row1 = *row1; + _row2 = *row2; + _row3 = *row3; +} + +void FMatrix::fn1(const FVector *v) { + _row3._x = v->_x; + + FVector tempVector; + _row3.fn1(&tempVector); + + _row2._x = tempVector._x; + _row2._y = tempVector._y; + _row2._z = tempVector._z; + + _row3.multiply(&tempVector, &_row2); + _row1._x = _row2._x; + _row1._y = _row2._y; + _row1._z = _row2._z; + _row1.fn3(); + + _row3.multiply(&tempVector, &_row1); + _row2._x = _row1._x; + _row2._y = _row1._y; + _row2._z = _row1._z; + _row2.fn3(); +} + +void FMatrix::fn2(FMatrix *m) { + double x1 = _row1._y * m->_row2._x + _row1._z * m->_row3._x + _row1._x * m->_row1._x; + double y1 = _row1._x * m->_row1._y + m->_row2._y * _row1._y + m->_row3._y * _row1._z; + double z1 = _row1._x * m->_row1._z + _row1._y * m->_row2._z + _row1._z * m->_row3._z; + double x2 = m->_row1._x * _row2._x + m->_row3._x * _row2._z + m->_row2._x * _row2._y; + double y2 = m->_row3._y * _row2._z + m->_row1._y * _row2._x + m->_row2._y * _row2._y; + double z2 = _row2._z * m->_row3._z + _row2._x * m->_row1._z + _row2._y * m->_row2._z; + double x3 = m->_row1._x * _row3._x + _row3._z * m->_row3._x + _row3._y * m->_row2._x; + double y3 = _row3._y * m->_row2._y + _row3._z * m->_row3._y + _row3._x * m->_row1._y; + double z3 = _row3._x * m->_row1._z + _row3._y * m->_row2._z + _row3._z * m->_row3._z; + + _row1 = FVector(x1, y1, z1); + _row2 = FVector(x2, y2, z2); + _row3 = FVector(x3, y3, z3); +} + +void FMatrix::fn3(FMatrix *m) { + double x1 = _row2._x * m->_row1._y + m->_row1._z * _row3._x + _row1._x * m->_row1._x; + double y1 = m->_row1._x * _row1._y + _row3._y * m->_row1._z + _row2._y * m->_row1._y; + double z1 = m->_row1._x * _row1._z + m->_row1._y * _row2._z + m->_row1._z * _row3._z; + double x2 = _row1._x * m->_row2._x + _row2._x * m->_row2._y + _row3._x * m->_row2._z; + double y2 = _row3._y * m->_row2._z + _row1._y * m->_row2._x + _row2._y * m->_row2._y; + double z2 = m->_row2._z * _row3._z + m->_row2._x * _row1._z + m->_row2._y * _row2._z; + double x3 = _row1._x * m->_row3._x + m->_row3._z * _row3._x + m->_row3._y * _row2._x; + double y3 = m->_row3._y * _row2._y + m->_row3._z * _row3._y + m->_row3._x * _row1._y; + double z3 = m->_row3._x * _row1._z + m->_row3._y * _row2._z + m->_row3._z * _row3._z; + + _row1 = FVector(x1, y1, z1); + _row2 = FVector(x2, y2, z2); + _row3 = FVector(x3, y3, z3); +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/fmatrix.h b/engines/titanic/star_control/fmatrix.h new file mode 100644 index 0000000000..d7c4acfbdc --- /dev/null +++ b/engines/titanic/star_control/fmatrix.h @@ -0,0 +1,94 @@ +/* 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_FMATRIX_H +#define TITANIC_FMATRIX_H + +#include "titanic/support/simple_file.h" +#include "titanic/star_control/fvector.h" + +namespace Titanic { + +class DMatrix; + +/** + * Floating point matrix class. + * @remarks TODO: See if it can be merged with DMatrix + */ +class FMatrix { +private: + /** + * Copys data from a given source + */ + void copyFrom(const DMatrix *src); +public: + FVector _row1; + FVector _row2; + FVector _row3; +public: + FMatrix(); + FMatrix(DMatrix *src); + FMatrix(FMatrix *src); + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file, int param); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file, int indent); + + /** + * Clears the matrix + */ + void clear(); + + /** + * Sets the data for the matrix + */ + void set(FVector *row1, FVector *row2, FVector *row3); + + void fn1(const FVector *v); + + void fn2(FMatrix *m); + void fn3(FMatrix *m); + + /** + * Returns true if the passed matrix equals this one + */ + bool operator==(const FMatrix &src) { + return _row1 == src._row1 && _row2 == src._row2 && _row3 == src._row3; + } + + /** + * Returns true if the passed matrix does not equal this one + */ + bool operator!=(const FMatrix &src) { + return !operator==(src); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MATRIX3_H */ diff --git a/engines/titanic/star_control/fpoint.cpp b/engines/titanic/star_control/fpoint.cpp new file mode 100644 index 0000000000..f3d7008324 --- /dev/null +++ b/engines/titanic/star_control/fpoint.cpp @@ -0,0 +1,28 @@ +/* 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/star_control/fpoint.h" + +namespace Titanic { + + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/fpoint.h b/engines/titanic/star_control/fpoint.h new file mode 100644 index 0000000000..f2cef18ea5 --- /dev/null +++ b/engines/titanic/star_control/fpoint.h @@ -0,0 +1,41 @@ +/* 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_FPOINT_H +#define TITANIC_FPOINT_H + +namespace Titanic { + +/** + * Floating point Point class + */ +class FPoint { +public: + double _x, _y; +public: + FPoint() : _x(0), _y(0) {} + FPoint(double x, double y) : _x(x), _y(y) {} +}; + +} // End of namespace Titanic + +#endif /* TITANIC_FPOINT_H */ diff --git a/engines/titanic/star_control/fvector.cpp b/engines/titanic/star_control/fvector.cpp new file mode 100644 index 0000000000..aa99e8b4d1 --- /dev/null +++ b/engines/titanic/star_control/fvector.cpp @@ -0,0 +1,71 @@ +/* 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/star_control/fvector.h" +#include "titanic/star_control/star_control_sub6.h" +#include "common/algorithm.h" +#include "common/textconsole.h" + +namespace Titanic { + +void FVector::fn1(FVector *v) { + v->_x = (ABS(_x - _y) < 0.00001 && ABS(_y - _z) < 0.00001 && + ABS(_x - _z) < 0.00001) ? -_x : _x; + v->_y = _y; + v->_z = _z; +} + +void FVector::multiply(FVector *dest, const FVector *src) { + dest->_x = (src->_z * _y) - (_z * src->_y); + dest->_y = (src->_x * _z) - (_x * src->_z); + dest->_z = (src->_y * _x) - (_y * src->_x); +} + +void FVector::fn3() { + double hyp = sqrt(_x * _x + _y * _y + _z * _z); + assert(hyp); + + _x *= 1.0 / hyp; + _y *= 1.0 / hyp; + _z *= 1.0 / hyp; +} + +double FVector::getDistance(const FVector *src) const { + double xd = src->_x - _x; + double yd = src->_y - _y; + double zd = src->_z - _z; + + return sqrt(xd * xd + yd * yd + zd * zd); +} + +void FVector::fn4(FVector *dest, const FVector *v1, const FVector *v2) { + FVector tempVector(v1->_x + v2->_x, v1->_y + v2->_y, v1->_z + v2->_z); + tempVector.fn3(); + + *dest = tempVector; +} + +void FVector::fn5(FVector *dest, const CStarControlSub6 *sub6) const { + error("TODO: FVector::fn5"); +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/fvector.h b/engines/titanic/star_control/fvector.h new file mode 100644 index 0000000000..8e1ba47a3e --- /dev/null +++ b/engines/titanic/star_control/fvector.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_FVECTOR_H +#define TITANIC_FVECTOR_H + +namespace Titanic { + +class CStarControlSub6; + +/** + * Floating point vector class. + * @remarks TODO: See if it can be merged with DVector + */ +class FVector { +public: + double _x, _y, _z; +public: + FVector() : _x(0), _y(0), _z(0) {} + FVector(double x, double y, double z) : _x(x), _y(y), _z(z) {} + + void fn1(FVector *v); + void multiply(FVector *dest, const FVector *src); + void fn3(); + + /** + * Returns the distance between a specified point and this one + */ + double getDistance(const FVector *src) const; + + static void fn4(FVector *dest, const FVector *v1, const FVector *v2); + void fn5(FVector *dest, const CStarControlSub6 *sub6) const; + + /** + * Returns true if the passed vector equals this one + */ + bool operator==(const FVector &src) const { + return _x != src._x || _y != src._y || _z != src._z; + } + + /** + * Returns true if the passed vector does not equal this one + */ + bool operator!=(const FVector &src) const { + return !operator==(src); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_FVECTOR_H */ diff --git a/engines/titanic/star_control/star_control.cpp b/engines/titanic/star_control/star_control.cpp new file mode 100644 index 0000000000..7ba160cd37 --- /dev/null +++ b/engines/titanic/star_control/star_control.cpp @@ -0,0 +1,148 @@ +/* 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/support/screen_manager.h" +#include "titanic/star_control/star_control.h" +#include "titanic/star_control/dmatrix.h" +#include "titanic/star_control/error_code.h" +#include "titanic/star_control/star_control_sub6.h" +#include "titanic/star_control/star_control_sub12.h" + +namespace Titanic { + +BEGIN_MESSAGE_MAP(CStarControl, CGameObject) + ON_MESSAGE(MouseMoveMsg) + ON_MESSAGE(MouseButtonDownMsg) + ON_MESSAGE(KeyCharMsg) + ON_MESSAGE(FrameMsg) +END_MESSAGE_MAP() + +CStarControl::CStarControl() : _fieldBC(0), _field80B0(0), + _starRect(20, 10, 620, 350) { + CStarControlSub6::init(); + CStarControlSub12::init(); + DMatrix::init(); +} + +CStarControl::~CStarControl() { + CStarControlSub6::deinit(); + CStarControlSub12::deinit(); + DMatrix::deinit(); +} + +void CStarControl::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + _starField.save(file, indent); + _view.save(file, indent); + CGameObject::save(file, indent); +} + +void CStarControl::load(SimpleFile *file) { + int val = file->readNumber(); + + if (!val) { + _starField.load(file); + if (!_starField.initDocument()) + error("Couldn't initialise the StarField document"); + + _view.load(file, 0); + CScreenManager *screenManager = CScreenManager::setCurrent(); + if (!screenManager) + error("There's no screen manager during loading"); + + _view.setup(screenManager, &_starField, this); + _view.reset(); + + _fieldBC = 1; + } + + CGameObject::load(file); +} + +void CStarControl::draw(CScreenManager *screenManager) { + if (_visible) + _view.draw(screenManager); +} + +bool CStarControl::MouseButtonDownMsg(CMouseButtonDownMsg *msg) { + if (_visible && _starRect.contains(msg->_mousePos)) { + _view.MouseButtonDownMsg(0, Point(msg->_mousePos.x - 20, + msg->_mousePos.y - 10)); + return true; + } else { + return false; + } +} + +bool CStarControl::MouseMoveMsg(CMouseMoveMsg *msg) { + if (_visible && _starRect.contains(msg->_mousePos)) { + _view.MouseMoveMsg(0, Point(msg->_mousePos.x - 20, + msg->_mousePos.y - 10)); + makeDirty(); + return true; + } else { + return false; + } +} + +bool CStarControl::KeyCharMsg(CKeyCharMsg *msg) { + if (_visible) + _view.KeyCharMsg(msg->_key); + + return false; +} + +bool CStarControl::FrameMsg(CFrameMsg *msg) { + if (_visible) { + Point pt = getMousePos(); + if (_starRect.contains(pt)) + _view.MouseMoveMsg(0, pt); + + newFrame(); + makeDirty(); + return true; + } else { + return false; + } +} + +void CStarControl::newFrame() { + // TODO +} + +void CStarControl::fn1(int action) { + // TODO +} + +bool CStarControl::fn4() { + return _starField.get6(); +} + +bool CStarControl::canSetStarDestination() const { + return _view.canSetStarDestination(); +} + +void CStarControl::starDestinationSet() { + _view.starDestinationSet(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control.h b/engines/titanic/star_control/star_control.h new file mode 100644 index 0000000000..c0561ce908 --- /dev/null +++ b/engines/titanic/star_control/star_control.h @@ -0,0 +1,85 @@ +/* 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_STAR_CONTROL_H +#define TITANIC_STAR_CONTROL_H + +#include "titanic/core/game_object.h" +#include "titanic/star_control/star_field.h" +#include "titanic/star_control/star_view.h" + +namespace Titanic { + +class CStarControl : public CGameObject { + DECLARE_MESSAGE_MAP; + bool MouseButtonDownMsg(CMouseButtonDownMsg *msg); + bool MouseMoveMsg(CMouseMoveMsg *msg); + bool KeyCharMsg(CKeyCharMsg *msg); + bool FrameMsg(CFrameMsg *msg); +private: + int _fieldBC; + CStarField _starField; + CStarView _view; + Rect _starRect; + int _field80B0; +private: + /** + * Called for ever new game frame + */ + void newFrame(); +public: + CLASSDEF; + CStarControl(); + virtual ~CStarControl(); + + /** + * 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); + + void fn1(int action); + bool fn4(); + + /** + * Returns true if a star destination can be set + */ + bool canSetStarDestination() const; + + /** + * Called when a star destination is set + */ + void starDestinationSet(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_H */ diff --git a/engines/titanic/star_control/star_control_sub12.cpp b/engines/titanic/star_control/star_control_sub12.cpp new file mode 100644 index 0000000000..5840495d34 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub12.cpp @@ -0,0 +1,283 @@ +/* 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/star_control/star_control_sub12.h" +#include "titanic/star_control/star_control_sub21.h" +#include "titanic/star_control/star_control_sub22.h" + +namespace Titanic { + +FMatrix *CStarControlSub12::_matrix1; +FMatrix *CStarControlSub12::_matrix2; + +CStarControlSub12::CStarControlSub12(void *val1, const CStar20Data *data) : + _currentIndex(-1), _handlerP(nullptr), _field108(0), + _sub13(val1) { + setupHandler(data); +} + +CStarControlSub12::CStarControlSub12(CStarControlSub13 *src) : + _currentIndex(-1), _handlerP(nullptr), _field108(0), _sub13(src) { +} + +void CStarControlSub12::init() { + _matrix1 = nullptr; + _matrix2 = nullptr; +} + +void CStarControlSub12::deinit() { + delete _matrix1; + delete _matrix2; + _matrix1 = nullptr; + _matrix2 = nullptr; +} + +CStarControlSub12::~CStarControlSub12() { + deleteHandler(); +} + +void CStarControlSub12::proc2(const void *src) { + _sub13.copyFrom(src); +} + +void CStarControlSub12::proc3(const CStar20Data *src) { + _handlerP->copyFrom(src); +} + +void CStarControlSub12::setPosition(const FVector &v) { + if (!isLocked()) { + _sub13.setPosition(v); + set108(); + } +} + +void CStarControlSub12::proc5(const FVector &v) { + if (!isLocked()) + _sub13.fn11(v); +} + +void CStarControlSub12::proc6(int v) { + if (!isLocked()) + _sub13.setC(v); +} + +void CStarControlSub12::proc7(int v) { + if (!isLocked()) + _sub13.set10(v); +} + +void CStarControlSub12::proc8(int v) { + if (!isLocked()) + _sub13.set14(v); +} + +void CStarControlSub12::proc9(int v) { + if (!isLocked()) + _sub13.set18(v); +} + +void CStarControlSub12::proc10(int v) { + if (!isLocked()) + _sub13.set1C(v); +} + +void CStarControlSub12::proc11() { + if (!isLocked()) + _sub13.fn12(); +} + +void CStarControlSub12::proc12(double v1, double v2) { + if (!isLocked()) + _sub13.fn13(v1, v2); +} + +void CStarControlSub12::proc13(CStarControlSub13 *dest) { + *dest = _sub13; +} + +void CStarControlSub12::proc14(int v) { + FMatrix matrix; + _sub13.getMatrix(&matrix); + FVector vector = _sub13._position; + + _handlerP->proc9(&vector, v, &matrix); +} + +void CStarControlSub12::proc15(int v) { + if (!_matrix1) + _matrix1 = new FMatrix(); + if (!_matrix2) + _matrix2 = new FMatrix(); + + _sub13.getMatrix(_matrix1); + *_matrix2 = *_matrix1; + + FVector v1 = _sub13._position; + FVector v2 = _sub13._position; + CErrorCode errorCode; + _handlerP->proc11(errorCode, v2, _matrix2); + + if (v1 != v2) { + _sub13.setPosition(v2); + set108(); + } + + if (_matrix1 != _matrix2) { + _sub13.setMatrix(_matrix2); + } +} + +void CStarControlSub12::proc16() { + _handlerP->proc4(); +} + +void CStarControlSub12::proc17() { + _handlerP->proc5(); +} + +void CStarControlSub12::proc18() { + _handlerP->proc6(); +} + +void CStarControlSub12::proc19() { + _handlerP->proc7(); +} + +void CStarControlSub12::proc20(double v) { + if (!isLocked()) + _sub13.fn14(v); +} + +void CStarControlSub12::proc21(CStarControlSub6 &sub6) { + if (!isLocked()) { + _sub13.setPosition(sub6); + set108(); + } +} + +void CStarControlSub12::proc22(FMatrix &m) { + if (!isLocked()) + _sub13.fn15(m); +} + +CStarControlSub6 CStarControlSub12::proc23() { + return _sub13.getSub1(); +} + +CStarControlSub6 CStarControlSub12::proc24() { + return _sub13.getSub2(); +} + +double CStarControlSub12::proc25() const { + return _sub13._field10; +} + +double CStarControlSub12::proc26() const { + return _sub13._field14; +} + +int CStarControlSub12::proc27() const { + return _sub13._field24; +} + +FVector CStarControlSub12::proc28(int index, const void *v2) { + error("TODO: CStarControlSub12::proc28"); + return FVector(); +} + +FVector CStarControlSub12::proc29(const FVector &v) { + return _sub13.fn16(v); +} + +FVector CStarControlSub12::proc30(int index, const FVector &v) { + return _sub13.fn17(index, v); +} + +FVector CStarControlSub12::proc31(int index, const FVector &v) { + return _sub13.fn18(index, v); +} + +void CStarControlSub12::proc32(double v1, double v2) { + error("TODO: CStarControlSub12::proc32"); +} + +bool CStarControlSub12::setArrayVector(const FVector &v) { + if (_currentIndex >= 2) + return false; + + error("TODO: CStarControlSub12::setArrayVector"); +} + +bool CStarControlSub12::proc35() { + if (_currentIndex == -1) + return false; + + error("TODO: CStarControlSub12::proc35"); +} + +void CStarControlSub12::proc36(double *v1, double *v2, double *v3, double *v4) { + _sub13.fn19(v1, v2, v3, v4); +} + +void CStarControlSub12::load(SimpleFile *file, int param) { + _sub13.load(file, param); +} + +void CStarControlSub12::save(SimpleFile *file, int indent) { + _sub13.save(file, indent); +} + +bool CStarControlSub12::setupHandler(const CStar20Data *src) { + CStarControlSub20 *handler = nullptr; + + switch (_currentIndex) { + case -1: + handler = new CStarControlSub21(src); + break; + + case 0: + case 1: + case 2: + handler = new CStarControlSub22(src); + break; + + default: + break; + } + + if (handler) { + assert(!_handlerP); + _handlerP = handler; + return true; + } else { + return false; + } +} + +void CStarControlSub12::deleteHandler() { + if (_handlerP) { + delete _handlerP; + _handlerP = nullptr; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub12.h b/engines/titanic/star_control/star_control_sub12.h new file mode 100644 index 0000000000..8da45df5c0 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub12.h @@ -0,0 +1,120 @@ +/* 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_STAR_CONTROL_SUB12_H +#define TITANIC_STAR_CONTROL_SUB12_H + +#include "titanic/support/simple_file.h" +#include "titanic/star_control/fmatrix.h" +#include "titanic/star_control/star_control_sub13.h" +#include "titanic/star_control/star_control_sub20.h" + +namespace Titanic { + +class CStarControlSub12 { +private: + static FMatrix *_matrix1; + static FMatrix *_matrix2; +private: + int _currentIndex; + FVector _array[3]; + CStarControlSub20 *_handlerP; + CStarControlSub13 _sub13; + int _field108; +private: + /** + * Set up a handler + */ + bool setupHandler(const CStar20Data *src); + + /** + * Deletes any previous handler + */ + void deleteHandler(); + + /** + * Return whether the handler is locked + */ + bool isLocked() { return _handlerP->isLocked(); } +public: + static void init(); + static void deinit(); +public: + CStarControlSub12(void *val1, const CStar20Data *data); + CStarControlSub12(CStarControlSub13 *src); + virtual ~CStarControlSub12(); + + virtual void proc2(const void *src); + virtual void proc3(const CStar20Data *src); + virtual void setPosition(const FVector &v); + virtual void proc5(const FVector &v); + virtual void proc6(int v); + virtual void proc7(int v); + virtual void proc8(int v); + virtual void proc9(int v); + virtual void proc10(int v); + virtual void proc11(); + virtual void proc12(double v1, double v2); + virtual void proc13(CStarControlSub13 *dest); + virtual void proc14(int v); + virtual void proc15(int v); + virtual void proc16(); + virtual void proc17(); + virtual void proc18(); + virtual void proc19(); + virtual void proc20(double v); + virtual void proc21(CStarControlSub6 &sub6); + virtual void proc22(FMatrix &m); + virtual CStarControlSub6 proc23(); + virtual CStarControlSub6 proc24(); + virtual double proc25() const; + virtual double proc26() const; + virtual int proc27() const; + virtual FVector proc28(int index, const void *v2); + virtual FVector proc29(const FVector &v); + virtual FVector proc30(int index, const FVector &v); + virtual FVector proc31(int index, const FVector &v); + virtual void proc32(double v1, double v2); + virtual int getCurrentIndex() const { return _currentIndex; } + virtual bool setArrayVector(const FVector &v); + virtual bool proc35(); + virtual void proc36(double *v1, double *v2, double *v3, double *v4); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file, int param); + + /** + * Save the data for the class to file + */ + virtual void save(SimpleFile *file, int indent); + + + bool is108() const { return _field108; } + void set108() { _field108 = true; } + void reset108() { _field108 = false; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB12_H */ diff --git a/engines/titanic/star_control/star_control_sub13.cpp b/engines/titanic/star_control/star_control_sub13.cpp new file mode 100644 index 0000000000..cc9e239194 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub13.cpp @@ -0,0 +1,236 @@ +/* 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/star_control/star_control_sub13.h" + +namespace Titanic { + +CStarControlSub13::CStarControlSub13(void *src) : + _fieldC0(0), _fieldC4(0), _fieldC8(0), _fieldCC(0), _fieldD0(0) { + if (src) { + setup(src); + } else { + _fieldC = 0; + _field10 = 0x44480000; + _field14 = 0x461C4000; + _field18 = 0x41A00000; + _field1C = 0x41A00000; + _width = 600; + _height = 340; + _field24 = 0; + } + + _fieldD4 = 0; +} + +CStarControlSub13::CStarControlSub13(CStarControlSub13 *src) : + _matrix(&src->_matrix), _sub1(&src->_sub1), _sub2(&src->_sub2) { + _position = src->_position; + _fieldC = src->_fieldC; + _field10 = src->_field10; + _field14 = src->_field14; + _field18 = src->_field18; + _field1C = src->_field1C; + _width = src->_width; + _height = src->_height; + + _fieldCC = src->_fieldCC; + _fieldD0 = src->_fieldD0; + _fieldC0 = src->_fieldC0; + _fieldC4 = src->_fieldC4; + _fieldC8 = src->_fieldC8; + _field24 = src->_field24; + + _valArray[0] = src->_valArray[0]; + _valArray[2] = src->_valArray[2]; + _valArray[3] = src->_valArray[3]; + _fieldD4 = 0; +} + +void CStarControlSub13::setup(void *ptr) { + // TODO +} + +void CStarControlSub13::copyFrom(const void *src) { + if (!src) + return; +/* + _field0 = src->_field0; + _field4 = src->_field4; + _field8 = src->_field8; + _fieldC = src->_field18; + _field10 = src->_field1C; + */ +} + +void CStarControlSub13::load(SimpleFile *file, int param) { + _position._x = file->readFloat(); + _position._y = file->readFloat(); + _position._z = file->readFloat(); + _fieldC = file->readFloat(); + _field10 = file->readFloat(); + _field14 = file->readFloat(); + _field18 = file->readFloat(); + _field1C = file->readFloat(); + + int widthHeight = file->readNumber(); + _width = widthHeight & 0xff; + _height = _width >> 16; + _field24 = file->readNumber(); + + for (int idx = 0; idx < 5; ++idx) + _valArray[idx] = file->readFloat(); + + _matrix.load(file, param); + _fieldD4 = 0; +} + +void CStarControlSub13::save(SimpleFile *file, int indent) { + file->writeFloatLine(_position._x, indent); + file->writeFloatLine(_position._y, indent); + file->writeFloatLine(_position._z, indent); + file->writeFloatLine(_fieldC, indent); + file->writeFloatLine(_field10, indent); + file->writeFloatLine(_field14, indent); + file->writeFloatLine(_field18, indent); + file->writeFloatLine(_field1C, indent); + file->writeFloatLine(_width | (_height << 16), indent); + + for (int idx = 0; idx < 5; ++idx) + file->writeFloatLine(_valArray[idx], indent); + + _matrix.save(file, indent); +} + +void CStarControlSub13::setPosition(const FVector &v) { + _position = v; + _fieldD4 = 0; +} + +void CStarControlSub13::setPosition(const CStarControlSub6 &sub6) { + FVector vector; + _position.fn5(&vector, &sub6); + _position = sub6._matrix._row1; + _fieldD4 = 0; +} + +void CStarControlSub13::setMatrix(const FMatrix &m) { + _matrix = m; + _fieldD4 = 0; +} + +void CStarControlSub13::fn11(const FVector &v) { + _matrix.fn1(&v); + _fieldD4 = 0; +} + +void CStarControlSub13::setC(int v) { + _fieldC = v; + _fieldD4 = 0; +} + +void CStarControlSub13::set10(int v) { + _field10 = v; + _fieldD4 = 0; +} + +void CStarControlSub13::set14(int v) { + _field10 = v; +} + +void CStarControlSub13::set18(int v) { + _field18 = v; + _fieldD4 = 0; +} + +void CStarControlSub13::set1C(int v) { + _field1C = v; + _fieldD4 = 0; +} + +void CStarControlSub13::fn12() { + _matrix.clear(); + error("TODO: CStarControlSub13::fn12"); +} + +void CStarControlSub13::fn13(double v1, double v2) { + if (v1 == 0.0) { + _valArray[0] = v2; + _valArray[1] = -v2; + } else { + _valArray[3] = v2; + _valArray[4] = -v2; + } + + _valArray[2] = 0.0; + _field24 = v2 ? 2 : 0; +} + +void CStarControlSub13::fn14(double v) { + error("TODO: CStarControlSub13::fn14"); +} + +void CStarControlSub13::fn15(FMatrix &matrix) { + _matrix.fn3(&matrix); + _fieldD4 = 0; +} + +CStarControlSub6 CStarControlSub13::getSub1() { + if (!_fieldD4) + reset(); + + return _sub1; +} + +CStarControlSub6 CStarControlSub13::getSub2() { + if (!_fieldD4) + reset(); + + return _sub2; +} + +FVector CStarControlSub13::fn16(const FVector &v) { + error("TODO: CStarControlSub13::fn16"); +} + +FVector CStarControlSub13::fn17(int index, const FVector &v) { + error("TODO: CStarControlSub13::fn17"); +} + +FVector CStarControlSub13::fn18(int index, const FVector &v) { + error("TODO: CStarControlSub13::fn17"); +} + +void CStarControlSub13::fn19(double *v1, double *v2, double *v3, double *v4) { + error("TODO: CStarControlSub13::fn19"); +} + +void CStarControlSub13::reset() { + const double FACTOR = 3.1415927 * 0.0055555557; + error("TODO: CStarControlSub13::reset"); +} + +void CStarControlSub13::getMatrix(FMatrix *matrix) { + *matrix = _matrix; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub13.h b/engines/titanic/star_control/star_control_sub13.h new file mode 100644 index 0000000000..2f0b479cec --- /dev/null +++ b/engines/titanic/star_control/star_control_sub13.h @@ -0,0 +1,115 @@ +/* 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_STAR_CONTROL_SUB13_H +#define TITANIC_STAR_CONTROL_SUB13_H + +#include "titanic/support/simple_file.h" +#include "titanic/star_control/star_control_sub6.h" +#include "titanic/star_control/fmatrix.h" + +namespace Titanic { + +class CStarControlSub13 { +private: + double _fieldC; + double _field18; + double _field1C; + int _width; + int _height; + double _valArray[5]; + FMatrix _matrix; + CStarControlSub6 _sub1; + CStarControlSub6 _sub2; + double _fieldC0; + double _fieldC4; + int _fieldC8; + int _fieldCC; + double _fieldD0; + int _fieldD4; +private: + void setup(void *ptr); + + void reset(); +public: + FVector _position; + double _field10; + double _field14; + int _field24; +public: + CStarControlSub13(void *ptr); + CStarControlSub13(CStarControlSub13 *src); + + void copyFrom(const void *src); + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file, int param); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file, int indent); + + /** + * Sets the position + */ + void setPosition(const FVector &v); + + /** + * Sets the position + */ + void setPosition(const CStarControlSub6 &sub6); + + /** + * Sets the matrix + */ + void setMatrix(const FMatrix &m); + + void fn11(const FVector &v); + void fn12(); + void fn13(double v1, double v2); + void fn14(double v); + void fn15(FMatrix &matrix); + CStarControlSub6 getSub1(); + CStarControlSub6 getSub2(); + FVector fn16(const FVector &v); + FVector fn17(int index, const FVector &v); + FVector fn18(int index, const FVector &v); + void fn19(double *v1, double *v2, double *v3, double *v4); + + /** + * Makes a copy of the instance's matrix into the passed matrix + */ + void getMatrix(FMatrix *matrix); + + void setC(int v); + void set10(int v); + void set14(int v); + void set18(int v); + void set1C(int v); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB13_H */ diff --git a/engines/titanic/star_control/star_control_sub2.cpp b/engines/titanic/star_control/star_control_sub2.cpp new file mode 100644 index 0000000000..fcbb70cbcb --- /dev/null +++ b/engines/titanic/star_control/star_control_sub2.cpp @@ -0,0 +1,53 @@ +/* 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/star_control/star_control_sub2.h" + +namespace Titanic { + +bool CStarControlSub2::proc3(int v1) { + clear(); + // TODO + return true; +} + +bool CStarControlSub2::proc4(int v1, int v2, int v3, int v4, int v5) { + // TODO + return true; +} + +bool CStarControlSub2::loadStar() { + // TODO + return true; +} + +bool CStarControlSub2::proc7(int v1, int v2) { + // TODO + return true; +} + +bool CStarControlSub2::setup() { + // TODO + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub2.h b/engines/titanic/star_control/star_control_sub2.h new file mode 100644 index 0000000000..cd7781548f --- /dev/null +++ b/engines/titanic/star_control/star_control_sub2.h @@ -0,0 +1,47 @@ +/* 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_STAR_CONTROL_SUB2_H +#define TITANIC_STAR_CONTROL_SUB2_H + +#include "titanic/star_control/base_star.h" + +namespace Titanic { + +class CStarControlSub2: public CBaseStar { +public: + virtual ~CStarControlSub2() {} + + virtual bool proc3(int v1); + virtual bool proc4(int v1, int v2, int v3, int v4, int v5); + virtual bool loadStar(); + virtual bool proc7(int v1, int v2); + + /** + * Setup the control + */ + bool setup(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB2_H */ diff --git a/engines/titanic/star_control/star_control_sub20.cpp b/engines/titanic/star_control/star_control_sub20.cpp new file mode 100644 index 0000000000..5c6c243eaa --- /dev/null +++ b/engines/titanic/star_control/star_control_sub20.cpp @@ -0,0 +1,144 @@ +/* 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/star_control/star_control_sub20.h" +#include "common/textconsole.h" + +namespace Titanic { + +CStarControlSub20::CStarControlSub20(const CStar20Data *src) { + _lockCounter = 0; + _dataP = nullptr; + + if (src) { + copyFrom(src); + } else { + _field0 = 0.0; + _field4 = 0.0; + _field8 = 20.0; + _fieldC = 0.0; + _field10 = 50000.0; + _field14 = 1.0; + _field18 = 1.0; + _field1C = 0.0; + } +} + +CStarControlSub20::~CStarControlSub20() { + clear(); +} + +void CStarControlSub20::copyFrom(const CStar20Data *src) { + *((CStar20Data *)this) = *src; +} + +void CStarControlSub20::copyTo(CStar20Data *dest) { + *dest = *((CStar20Data *)this); +} + +void CStarControlSub20::proc4() { + if (!isLocked() && _field0 < _field10) { + _field4 += _field0; + if (_field8 == _field4) + _field0 -= _field4; + else + _field0 += _field4; + } +} + +void CStarControlSub20::proc5() { + if (!isLocked()) { + _field4 -= _field8; + if (_field4 == _field0) + _field0 += _field4; + else + _field0 -= _field4; + + if (_field4 < 0.0) + _field4 = 0.0; + } +} + +void CStarControlSub20::proc6() { + if (!isLocked()) + _field0 = _field10; +} + +void CStarControlSub20::proc7() { + if (!isLocked()) { + _field0 = 0.0; + _field4 = 0.0; + } +} + +void CStarControlSub20::proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m) { + if (_field0 > 0.0) { + warning("TODO: CStarControlSub20::proc11"); + } +} + +void CStarControlSub20::setData(void *data) { + clear(); + _dataP = (byte *)data; +} + +void CStarControlSub20::clear() { + if (_dataP) { + delete _dataP; + _dataP = nullptr; + } +} + +void CStarControlSub20::load(SimpleFile *file, int val) { + if (!val) { + _field0 = file->readFloat(); + _field4 = file->readFloat(); + _field8 = file->readFloat(); + _fieldC = file->readFloat(); + _field10 = file->readFloat(); + _field14 = file->readFloat(); + _field18 = file->readFloat(); + _field1C = file->readFloat(); + } +} + +void CStarControlSub20::save(SimpleFile *file, int indent) { + file->writeFloatLine(_field0, indent); + file->writeFloatLine(_field4, indent); + file->writeFloatLine(_field8, indent); + file->writeFloatLine(_fieldC, indent); + file->writeFloatLine(_field10, indent); + file->writeFloatLine(_field14, indent); + file->writeFloatLine(_field18, indent); + file->writeFloatLine(_field1C, indent); +} + +void CStarControlSub20::incLockCount() { + ++_lockCounter; +} + +void CStarControlSub20::decLockCount() { + if (_lockCounter > 0) + --_lockCounter; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub20.h b/engines/titanic/star_control/star_control_sub20.h new file mode 100644 index 0000000000..9dbabbb7f1 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub20.h @@ -0,0 +1,100 @@ +/* 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_STAR_CONTROL_SUB20_H +#define TITANIC_STAR_CONTROL_SUB20_H + +#include "titanic/support/simple_file.h" +#include "titanic/star_control/error_code.h" +#include "titanic/star_control/fmatrix.h" + +namespace Titanic { + +struct CStar20Data { + double _field0; + double _field4; + double _field8; + double _fieldC; + double _field10; + double _field14; + double _field18; + double _field1C; +}; + +class CStarControlSub20 : public CStar20Data { +public: + int _lockCounter; + byte *_dataP; +public: + CStarControlSub20(const CStar20Data *src); + virtual ~CStarControlSub20(); + + virtual void copyFrom(const CStar20Data *src); + virtual void copyTo(CStar20Data *dest); + virtual void proc4(); + virtual void proc5(); + virtual void proc6(); + virtual void proc7(); + virtual void proc8() {} + virtual void proc9(FVector *v, int v2, FMatrix *matrix) {} + virtual void proc10() {} + virtual void proc11(CErrorCode &errorCode, FVector &v, const FMatrix &m); + + /** + * Set the data + */ + virtual void setData(void *data); + + /** + * Clear the class + */ + virtual void clear(); + + /** + * Load the class + */ + virtual void load(SimpleFile *file, int val = 0); + + /** + * Save the class + */ + virtual void save(SimpleFile *file, int indent); + + /** + * Increment tthe lock counter + */ + void incLockCount(); + + /** + * Decrement the lock counter + */ + void decLockCount(); + + /** + * Returns true if the lock counter is non-zero + */ + bool isLocked() const { return _lockCounter > 0; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB20_H */ diff --git a/engines/titanic/star_control/star_control_sub21.cpp b/engines/titanic/star_control/star_control_sub21.cpp new file mode 100644 index 0000000000..1730244184 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub21.cpp @@ -0,0 +1,32 @@ +/* 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/star_control/star_control_sub21.h" +#include "common/textconsole.h" + +namespace Titanic { + +CStarControlSub21::CStarControlSub21(const CStar20Data *src) : + CStarControlSub20(src), _sub24() { +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub21.h b/engines/titanic/star_control/star_control_sub21.h new file mode 100644 index 0000000000..5febda0ebb --- /dev/null +++ b/engines/titanic/star_control/star_control_sub21.h @@ -0,0 +1,40 @@ +/* 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_STAR_CONTROL_SUB21_H +#define TITANIC_STAR_CONTROL_SUB21_H + +#include "titanic/star_control/star_control_sub20.h" +#include "titanic/star_control/star_control_sub24.h" + +namespace Titanic { + +class CStarControlSub21 : public CStarControlSub20 { +private: + CStarControlSub24 _sub24; +public: + CStarControlSub21(const CStar20Data *src); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB21_H */ diff --git a/engines/titanic/star_control/star_control_sub22.cpp b/engines/titanic/star_control/star_control_sub22.cpp new file mode 100644 index 0000000000..b06731b6d2 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub22.cpp @@ -0,0 +1,32 @@ +/* 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/star_control/star_control_sub22.h" +#include "common/textconsole.h" + +namespace Titanic { + +CStarControlSub22::CStarControlSub22(const CStar20Data *src) : + CStarControlSub20(src), _sub27() { +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub22.h b/engines/titanic/star_control/star_control_sub22.h new file mode 100644 index 0000000000..88a114f8c3 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub22.h @@ -0,0 +1,40 @@ +/* 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_STAR_CONTROL_SUB22_H +#define TITANIC_STAR_CONTROL_SUB22_H + +#include "titanic/star_control/star_control_sub20.h" +#include "titanic/star_control/star_control_sub27.h" + +namespace Titanic { + +class CStarControlSub22 : public CStarControlSub20 { +private: + CStarControlSub27 _sub27; +public: + CStarControlSub22(const CStar20Data *src); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB22_H */ diff --git a/engines/titanic/star_control/star_control_sub23.cpp b/engines/titanic/star_control/star_control_sub23.cpp new file mode 100644 index 0000000000..b009cbc35b --- /dev/null +++ b/engines/titanic/star_control/star_control_sub23.cpp @@ -0,0 +1,28 @@ +/* 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/star_control/star_control_sub23.h" +#include "common/textconsole.h" + +namespace Titanic { + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub23.h b/engines/titanic/star_control/star_control_sub23.h new file mode 100644 index 0000000000..136401e329 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub23.h @@ -0,0 +1,33 @@ +/* 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_STAR_CONTROL_SUB23_H +#define TITANIC_STAR_CONTROL_SUB23_H + +namespace Titanic { + +class CStarControlSub23 { +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB23_H */ diff --git a/engines/titanic/star_control/star_control_sub24.cpp b/engines/titanic/star_control/star_control_sub24.cpp new file mode 100644 index 0000000000..6f17eb7193 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub24.cpp @@ -0,0 +1,29 @@ +/* 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/star_control/star_control_sub24.h" +#include "common/textconsole.h" + +namespace Titanic { + + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub24.h b/engines/titanic/star_control/star_control_sub24.h new file mode 100644 index 0000000000..e0970fc1de --- /dev/null +++ b/engines/titanic/star_control/star_control_sub24.h @@ -0,0 +1,35 @@ +/* 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_STAR_CONTROL_SUB24_H +#define TITANIC_STAR_CONTROL_SUB24_H + +#include "titanic/star_control/star_control_sub23.h" + +namespace Titanic { + +class CStarControlSub24 : public CStarControlSub23 { +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB24_H */ diff --git a/engines/titanic/star_control/star_control_sub25.cpp b/engines/titanic/star_control/star_control_sub25.cpp new file mode 100644 index 0000000000..f91c75af6a --- /dev/null +++ b/engines/titanic/star_control/star_control_sub25.cpp @@ -0,0 +1,28 @@ +/* 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/star_control/star_control_sub25.h" +#include "common/textconsole.h" + +namespace Titanic { + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub25.h b/engines/titanic/star_control/star_control_sub25.h new file mode 100644 index 0000000000..e943782e37 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub25.h @@ -0,0 +1,43 @@ +/* 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_STAR_CONTROL_SUB25_H +#define TITANIC_STAR_CONTROL_SUB25_H + +#include "titanic/star_control/fmatrix.h" +#include "titanic/star_control/star_control_sub26.h" + +namespace Titanic { + +class CStarControlSub25 { +public: + FMatrix _matrix1; + FMatrix _matrix2; + CStarControlSub26 _sub1; + CStarControlSub26 _sub2; +public: + +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB25_H */ diff --git a/engines/titanic/star_control/star_control_sub26.cpp b/engines/titanic/star_control/star_control_sub26.cpp new file mode 100644 index 0000000000..89ff93c347 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub26.cpp @@ -0,0 +1,34 @@ +/* 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/star_control/star_control_sub26.h" +#include "common/textconsole.h" + +namespace Titanic { + +double CStarControlSub26::fn1() const { + return _sub._v1 * _sub._v1 + _sub._v2 * _sub._v2 + + _sub._v3 * _sub._v3 + _field0 * _field0; +} + + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub26.h b/engines/titanic/star_control/star_control_sub26.h new file mode 100644 index 0000000000..4054a2ba6e --- /dev/null +++ b/engines/titanic/star_control/star_control_sub26.h @@ -0,0 +1,47 @@ +/* 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_STAR_CONTROL_SUB26_H +#define TITANIC_STAR_CONTROL_SUB26_H + +namespace Titanic { + +class CStarControlSub26 { + struct Sub { + double _v1; + double _v2; + double _v3; + + Sub() : _v1(0.0), _v2(0.0), _v3(0.0) {} + }; +public: + double _field0; + Sub _sub; +public: + CStarControlSub26() : _field0(1.0) {} + + double fn1() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB26_H */ diff --git a/engines/titanic/star_control/star_control_sub27.cpp b/engines/titanic/star_control/star_control_sub27.cpp new file mode 100644 index 0000000000..6f17eb7193 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub27.cpp @@ -0,0 +1,29 @@ +/* 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/star_control/star_control_sub24.h" +#include "common/textconsole.h" + +namespace Titanic { + + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub27.h b/engines/titanic/star_control/star_control_sub27.h new file mode 100644 index 0000000000..01782b69ca --- /dev/null +++ b/engines/titanic/star_control/star_control_sub27.h @@ -0,0 +1,35 @@ +/* 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_STAR_CONTROL_SUB27_H +#define TITANIC_STAR_CONTROL_SUB27_H + +#include "titanic/star_control/star_control_sub23.h" + +namespace Titanic { + +class CStarControlSub27 : public CStarControlSub23 { +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB27_H */ diff --git a/engines/titanic/star_control/star_control_sub4.cpp b/engines/titanic/star_control/star_control_sub4.cpp new file mode 100644 index 0000000000..f765acbbc1 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub4.cpp @@ -0,0 +1,45 @@ +/* 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/algorithm.h" +#include "titanic/star_control/star_control_sub4.h" + +namespace Titanic { + +CStarControlSub4::CStarControlSub4() { +} + +void CStarControlSub4::initialize() { + _min._v1 = _min._v2 = _min._v3 = 9.9999994e27; + _max._v1 = _max._v2 = _max._v3 = -9.9999994e27; +} + +void CStarControlSub4::checkEntry(const CBaseStarVal &val) { + _min._v1 = MIN(_min._v1, val._v1); + _min._v2 = MIN(_min._v2, val._v2); + _min._v3 = MIN(_min._v3, val._v3); + _max._v1 = MAX(_max._v1, val._v1); + _max._v2 = MAX(_max._v2, val._v2); + _max._v3 = MAX(_max._v3, val._v3); +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub4.h b/engines/titanic/star_control/star_control_sub4.h new file mode 100644 index 0000000000..f0fcfaf7f4 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub4.h @@ -0,0 +1,47 @@ +/* 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_STAR_CONTROL_SUB4_H +#define TITANIC_STAR_CONTROL_SUB4_H + +namespace Titanic { + +struct CBaseStarVal { + double _v1, _v2, _v3; + CBaseStarVal() : _v1(0), _v2(0), _v3(0) {} +}; + +class CStarControlSub4 { +private: + CBaseStarVal _min; + CBaseStarVal _max; +public: + CStarControlSub4(); + + void initialize(); + + void checkEntry(const CBaseStarVal &val); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB4_H */ diff --git a/engines/titanic/star_control/star_control_sub5.cpp b/engines/titanic/star_control/star_control_sub5.cpp new file mode 100644 index 0000000000..e2899220c8 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub5.cpp @@ -0,0 +1,44 @@ +/* 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/star_control/star_control_sub5.h" + +namespace Titanic { + +CStarControlSub5::CStarControlSub5() : + _field4(1), _field78AC(0), _field78B0(0) { +} + +bool CStarControlSub5::setup() { + // TODO + return true; +} + +void CStarControlSub5::proc2() { + // TODO +} + +void CStarControlSub5::proc3(CErrorCode *errorCode) { + // TODO +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub5.h b/engines/titanic/star_control/star_control_sub5.h new file mode 100644 index 0000000000..ce92ef1135 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub5.h @@ -0,0 +1,59 @@ +/* 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_STAR_CONTROL_SUB5_H +#define TITANIC_STAR_CONTROL_SUB5_H + +#include "titanic/star_control/star_control_sub6.h" +#include "titanic/star_control/error_code.h" + +namespace Titanic { + +class CStarControlSub5 { + struct SubEntry { + int _field0; + int _field4; + int _field8; + int _fieldC; + }; +private: + int _field4; + SubEntry _array[5]; + CStarControlSub6 _sub1, _sub2; + int _field7914; + int _field78AC; + int _field78B0; +public: + CStarControlSub5(); + virtual ~CStarControlSub5() {} + + virtual bool setup(); + virtual void proc2(); + virtual void proc3(CErrorCode *errorCode); + + int get4() const { return _field4; } + void set4(int val) { _field4 = val; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB5_H */ diff --git a/engines/titanic/star_control/star_control_sub6.cpp b/engines/titanic/star_control/star_control_sub6.cpp new file mode 100644 index 0000000000..a5a1d81aa8 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub6.cpp @@ -0,0 +1,115 @@ +/* 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/star_control/star_control_sub6.h" + +namespace Titanic { + +CStarControlSub6 *CStarControlSub6::_static; + +CStarControlSub6::CStarControlSub6() { + clear(); +} + +CStarControlSub6::CStarControlSub6(int mode, double val) { + set(mode, val); +} + +CStarControlSub6::CStarControlSub6(const CStarControlSub6 *src) { + copyFrom(src); +} + +void CStarControlSub6::init() { + _static = nullptr; +} + +void CStarControlSub6::deinit() { + delete _static; + _static = nullptr; +} + +void CStarControlSub6::clear() { + _matrix.clear(); + _field24 = 0; + _field28 = 0; + _field2C = 0; +} + +void CStarControlSub6::set(int mode, double amount) { + const double ROTATION = 3.1415927 * 0.0055555557; + double sinVal = sin(amount * ROTATION); + double cosVal = cos(amount * ROTATION); + + switch (mode) { + case 0: + _matrix._row1._x = 1.0; + _matrix._row1._y = 0.0; + _matrix._row1._z = 0.0; + _matrix._row2._x = 0.0; + _matrix._row2._y = cosVal; + _matrix._row2._z = sinVal; + _matrix._row3._x = 0.0; + _matrix._row3._y = -sinVal; + _matrix._row3._z = cosVal; + break; + + case 1: + _matrix._row1._x = cosVal; + _matrix._row1._y = 0.0; + _matrix._row1._z = sinVal; + _matrix._row2._x = 0.0; + _matrix._row2._y = 1.0; + _matrix._row2._z = 0.0; + _matrix._row3._x = -sinVal; + _matrix._row3._y = 0.0; + _matrix._row3._z = sinVal; + break; + + case 2: + _matrix._row1._x = cosVal; + _matrix._row1._y = sinVal; + _matrix._row1._z = 0.0; + _matrix._row2._x = -sinVal; + _matrix._row2._y = cosVal; + _matrix._row2._z = 0.0; + _matrix._row3._x = 0.0; + _matrix._row3._y = 0.0; + _matrix._row3._z = 1.0; + break; + + default: + break; + } + + _field24 = 0.0; + _field28 = 0.0; + _field2C = 0.0; +} + +void CStarControlSub6::copyFrom(const CStarControlSub6 *src) { + _matrix = src->_matrix; + _field24 = src->_field24; + _field28 = src->_field28; + _field2C = src->_field2C; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub6.h b/engines/titanic/star_control/star_control_sub6.h new file mode 100644 index 0000000000..118c7c7f10 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub6.h @@ -0,0 +1,62 @@ +/* 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_STAR_CONTROL_SUB6_H +#define TITANIC_STAR_CONTROL_SUB6_H + +#include "titanic/star_control/fmatrix.h" + +namespace Titanic { + +class CStarControlSub6 { +private: + int _field24; + int _field28; + int _field2C; +private: + static CStarControlSub6 *_static; +public: + static void init(); + static void deinit(); +public: + FMatrix _matrix; +public: + CStarControlSub6(); + CStarControlSub6(int mode, double amount); + CStarControlSub6(const CStarControlSub6 *src); + + /** + * Clear the item + */ + void clear(); + + /** + * Sets the default data + */ + void set(int mode, double val); + + void copyFrom(const CStarControlSub6 *src); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB6_H */ diff --git a/engines/titanic/star_control/star_control_sub7.cpp b/engines/titanic/star_control/star_control_sub7.cpp new file mode 100644 index 0000000000..b33f8be582 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub7.cpp @@ -0,0 +1,36 @@ +/* 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/star_control/star_control_sub7.h" + +namespace Titanic { + +void CStarControlSub7::proc2(int v1, int v2, int v3) { + // TODO +} + +bool CStarControlSub7::proc5(int v1) { + // TODO + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub7.h b/engines/titanic/star_control/star_control_sub7.h new file mode 100644 index 0000000000..b73124ddd7 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub7.h @@ -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. + * + */ + +#ifndef TITANIC_STAR_CONTROL_SUB7_H +#define TITANIC_STAR_CONTROL_SUB7_H + +#include "titanic/star_control/base_star.h" +namespace Titanic { + +class CStarControlSub7 : public CBaseStar { +public: + virtual ~CStarControlSub7() { clear(); } + + virtual void proc2(int v1, int v2, int v3); + virtual bool proc5(int v1); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB7_H */ diff --git a/engines/titanic/star_control/star_control_sub8.cpp b/engines/titanic/star_control/star_control_sub8.cpp new file mode 100644 index 0000000000..cdb249b663 --- /dev/null +++ b/engines/titanic/star_control/star_control_sub8.cpp @@ -0,0 +1,31 @@ +/* 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/star_control/star_control_sub8.h" + +namespace Titanic { + +CStarControlSub8::CStarControlSub8() : + _field0(0), _field4(0), _field8(-1), _fieldC(-1) { +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_control_sub8.h b/engines/titanic/star_control/star_control_sub8.h new file mode 100644 index 0000000000..6d8d1f0c7d --- /dev/null +++ b/engines/titanic/star_control/star_control_sub8.h @@ -0,0 +1,60 @@ +/* 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_STAR_CONTROL_SUB8_H +#define TITANIC_STAR_CONTROL_SUB8_H + +#include "titanic/support/simple_file.h" + +namespace Titanic { + +class CStarControlSub8 { + struct StructEntry { + int _field0; + int _field4; + int _field8; + int _fieldC; + }; +private: + int _field0; + int _field4; + int _fieldC; + StructEntry _array[3]; +public: + int _field8; +public: + CStarControlSub8(); + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file) {} + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file, int indent) {} +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB8_H */ diff --git a/engines/titanic/star_control/star_field.cpp b/engines/titanic/star_control/star_field.cpp new file mode 100644 index 0000000000..c50e8466ec --- /dev/null +++ b/engines/titanic/star_control/star_field.cpp @@ -0,0 +1,130 @@ +/* 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/star_control/star_field.h" +#include "titanic/star_control/surface_area.h" + +namespace Titanic { + +CStarField::CStarField() : _val1(0), _val2(0), _val3(0), _val4(true), + _val5(0), _val6(false) { +} + +void CStarField::load(SimpleFile *file) { + _sub7.load(file); + _sub8.load(file); + _val1 = file->readNumber(); + _val2 = file->readNumber(); + _val3 = file->readNumber(); + _val4 = file->readNumber(); + _val6 = file->readNumber(); +} + +void CStarField::save(SimpleFile *file, int indent) { + _sub7.save(file, indent); + _sub8.save(file, indent); + file->writeNumberLine(_val1, indent); + file->writeNumberLine(_val2, indent); + file->writeNumberLine(_val3, indent); + file->writeNumberLine(_val4, indent); + file->writeNumberLine(_val6, indent); +} + +bool CStarField::initDocument() { + bool valid = setup() && _points1.initialize(); + if (valid) + valid = _sub5.setup(); + if (valid) + valid = _points1.initialize(); + if (valid) + valid = _points2.initialize(); + + return valid; +} + +void CStarField::render(CVideoSurface *surface, CStarControlSub12 *sub12) { + CSurfaceArea surfaceArea(surface); + draw(&surfaceArea, sub12, &_sub5); + + + // TODO +} + +int CStarField::get1() const { + return _val1; +} + +void CStarField::set1(int val) { + _val1 = val; +} + +int CStarField::get2() const { + return _val2; +} + +void CStarField::set2(int val) { + _val2 = val; +} + +int CStarField::get54() const { + return _sub5.get4(); +} + +void CStarField::set54(int val) { + _sub5.set4(val); +} + +int CStarField::get3() const { + return _val3; +} + +void CStarField::set3(int val) { + _val3 = val; +} + +void CStarField::toggle4() { + _val4 = !_val4; +} + +bool CStarField::set4(bool val) { + bool oldVal = _val4; + _val4 = val; + return oldVal; +} + +int CStarField::get88() const { + return _sub8._field8; +} + +int CStarField::get5() const { + return _val5; +} + +void CStarField::update6() { + _val6 = _sub8._field8 == 2; +} + +int CStarField::get6() const { + return _val6; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_field.h b/engines/titanic/star_control/star_field.h new file mode 100644 index 0000000000..ef1ee29737 --- /dev/null +++ b/engines/titanic/star_control/star_field.h @@ -0,0 +1,86 @@ +/* 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_STAR_FIELD_H +#define TITANIC_STAR_FIELD_H + +#include "titanic/star_control/star_control_sub2.h" +#include "titanic/star_control/star_control_sub5.h" +#include "titanic/star_control/star_control_sub7.h" +#include "titanic/star_control/star_control_sub8.h" +#include "titanic/star_control/star_points1.h" +#include "titanic/star_control/star_points2.h" + +namespace Titanic { + +class CStarField : public CStarControlSub2 { +private: + CStarControlSub7 _sub7; + CStarControlSub8 _sub8; + CStarPoints1 _points1; + CStarPoints2 _points2; + CStarControlSub5 _sub5; + int _val1; + int _val2; + int _val3; + bool _val4; + int _val5; + bool _val6; +public: + CStarField(); + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file, int indent); + + bool initDocument(); + + /** + * Renders the contents of the starfield + */ + void render(CVideoSurface *surface, CStarControlSub12 *sub12); + + int get1() const; + void set1(int val); + int get2() const; + void set2(int val); + int get54() const; + void set54(int val); + int get3() const; + void set3(int val); + void toggle4(); + bool set4(bool val); + int get88() const; + int get5() const; + void update6(); + int get6() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_FIELD_H */ diff --git a/engines/titanic/star_control/star_points1.cpp b/engines/titanic/star_control/star_points1.cpp new file mode 100644 index 0000000000..6e698d61f7 --- /dev/null +++ b/engines/titanic/star_control/star_points1.cpp @@ -0,0 +1,69 @@ +/* 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/star_control/star_points1.h" +#include "titanic/star_control/star_control_sub12.h" +#include "titanic/titanic.h" + +namespace Titanic { + +#define ARRAY_COUNT 876 +const double FACTOR = 3.1415927 * 0.0055555557; + +CStarPoints1::CStarPoints1() { +} + +bool CStarPoints1::initialize() { + // Get a reference to the starfield points resource + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource("STARFIELD/POINTS"); + assert(stream && stream->size() == (12 * ARRAY_COUNT)); + + _data.resize(ARRAY_COUNT); + for (int idx = 0; idx < ARRAY_COUNT; ++idx) { + FVector &entry = _data[idx]; + + // Get the next set of values + double v1 = stream->readUint32LE(); + double v2 = stream->readUint32LE(); + stream->readUint32LE(); + + v1 *= 0.0099999998 * FACTOR; + v2 *= 0.015 * FACTOR; + + entry._x = cos(v2) * 3000000.0 * cos(v1); + entry._y = sin(v2) * 3000000.0 * cos(v1); + entry._z = sin(v1) * 3000000.0; + } + + return true; +} + +void CStarPoints1::draw(CSurfaceArea *surface, CStarControlSub12 *img) { + if (_data.empty()) + return; + + + + // TODO +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_points1.h b/engines/titanic/star_control/star_points1.h new file mode 100644 index 0000000000..a6e4ee2ec9 --- /dev/null +++ b/engines/titanic/star_control/star_points1.h @@ -0,0 +1,53 @@ +/* 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_STAR_POINTS1_H +#define TITANIC_STAR_POINTS1_H + +#include "common/array.h" +#include "titanic/star_control/surface_area.h" +#include "titanic/star_control/fvector.h" + +namespace Titanic { + +class CStarControlSub12; + +class CStarPoints1 { +private: + Common::Array<FVector> _data; +public: + CStarPoints1(); + + /** + * Initialize the array + */ + bool initialize(); + + /** + * Draw the starfield points + */ + void draw(CSurfaceArea *surface, CStarControlSub12 *img); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_POINTS1_H */ diff --git a/engines/titanic/star_control/star_points2.cpp b/engines/titanic/star_control/star_points2.cpp new file mode 100644 index 0000000000..4fea298f93 --- /dev/null +++ b/engines/titanic/star_control/star_points2.cpp @@ -0,0 +1,59 @@ +/* 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/star_control/star_points2.h" +#include "titanic/titanic.h" + +namespace Titanic { + +#define ARRAY_COUNT 80 +const double FACTOR = 3.1415927 * 0.0055555557; + +bool CStarPoints2::initialize() { + // Get a reference to the starfield points resource + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource("STARFIELD/POINTS2"); + + _data.resize(ARRAY_COUNT); + for (int rootCtr = 0; rootCtr < ARRAY_COUNT; ++rootCtr) { + // Get the number of sub-entries for this entry + int count = stream->readUint32LE(); + double v1, v2; + + // Read in the sub-entries + RootEntry &rootEntry = _data[rootCtr]; + rootEntry.resize(count * 2); + for (int idx = 0; idx < count * 2; ++idx) { + DataEntry &entry = rootEntry[idx]; + v1 = stream->readSint32LE(); + v2 = stream->readSint32LE(); + v1 *= 0.015 * FACTOR; + v2 *= 0.0099999998 * FACTOR; + entry._v1 = cos(v1) * 3000000.0 * cos(v2); + entry._v2 = sin(v1) * 3000000.0 * cos(v2); + entry._v3 = sin(v2) * 3000000.0; + } + } + + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_points2.h b/engines/titanic/star_control/star_points2.h new file mode 100644 index 0000000000..31bded4069 --- /dev/null +++ b/engines/titanic/star_control/star_points2.h @@ -0,0 +1,53 @@ +/* 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_STAR_POINTS2_H +#define TITANIC_STAR_POINTS2_H + +#include "common/array.h" + +namespace Titanic { + +class CStarPoints2 { + struct DataEntry { + int _v1; + int _v2; + int _v3; + }; + + class RootEntry : public Common::Array<DataEntry> { + public: + int _field0; + RootEntry() : _field0(0) {} + }; +private: + Common::Array<RootEntry> _data; +public: + /** + * Initializes the data + */ + bool initialize(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_POINTS2_H */ diff --git a/engines/titanic/star_control/star_view.cpp b/engines/titanic/star_control/star_view.cpp new file mode 100644 index 0000000000..f5d1d36c49 --- /dev/null +++ b/engines/titanic/star_control/star_view.cpp @@ -0,0 +1,135 @@ +/* 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/support/screen_manager.h" +#include "titanic/star_control/star_view.h" +#include "titanic/star_control/star_control.h" +#include "titanic/star_control/star_field.h" +#include "titanic/core/game_object.h" + +namespace Titanic { + +CStarView::CStarView() : _sub12(nullptr, nullptr), _sub13((void *)nullptr), + _owner(nullptr), _starField(nullptr), _videoSurface(nullptr), _field118(0), + _videoSurface2(nullptr), _field210(0), _homePhotoMask(nullptr), + _field218(0), _field21C(0) { + CStar20Data data = { 0, 0, 0x47C35000, 0, 0x41A00000, + 0x3F800000, 0x3F800000, 0x3F800000 }; + + _sub12.proc3(&data); +} + +void CStarView::load(SimpleFile *file, int param) { + if (!param) { + _sub12.load(file, param); + + _field118 = file->readNumber(); + if (_field118) + _sub13.load(file, 0); + + _field218 = file->readNumber(); + _field21C = file->readNumber(); + } +} + +void CStarView::save(SimpleFile *file, int indent) { + _sub12.save(file, indent); + + file->writeNumberLine(_field118, indent); + if (_field118) + _sub13.save(file, indent); + + file->writeNumberLine(_field218, indent); + file->writeNumberLine(_field21C, indent); +} + +void CStarView::setup(CScreenManager *screenManager, CStarField *starField, CStarControl *starControl) { + _starField = starField; + _owner = starControl; +} + +void CStarView::reset() { + // TODO +} + +void CStarView::draw(CScreenManager *screenManager) { + if (!screenManager || !_videoSurface || !_starField) + return; + + if (_fader.isActive()) { + CVideoSurface *surface = _field21C ? _videoSurface2 : _videoSurface; + surface = _fader.fade(screenManager, surface); + screenManager->blitFrom(SURFACE_PRIMARY, surface); + } else { + Point destPos(20, 10); + + if (_field21C) { + screenManager->blitFrom(SURFACE_PRIMARY, _videoSurface2, &destPos); + + if (!_homePhotoMask && _owner) { + _homePhotoMask = _owner->getHiddenObject("HomePhotoMask"); + } + + if (_homePhotoMask) + _homePhotoMask->draw(screenManager, Point(20, 187)); + } else { + fn1(); + + // Render the display + _videoSurface->clear(); + _videoSurface->lock(); + _starField->render(_videoSurface, &_sub12); + _videoSurface->unlock(); + + // Blit the resulting surface to the screen + screenManager->blitFrom(SURFACE_PRIMARY, _videoSurface, &destPos); + } + } +} + +void CStarView::MouseButtonDownMsg(int unused, const Point &pt) { + // TODO +} + +void CStarView::MouseMoveMsg(int unused, const Point &pt) { + // TODO +} + +CErrorCode CStarView::KeyCharMsg(int key) { + // TODO + return CErrorCode(); +} + +bool CStarView::canSetStarDestination() const { + // TODO + return false; +} + +void CStarView::starDestinationSet() { + // TODO +} + +void CStarView::fn1() { + // TODO +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/star_view.h b/engines/titanic/star_control/star_view.h new file mode 100644 index 0000000000..bcba5ac436 --- /dev/null +++ b/engines/titanic/star_control/star_view.h @@ -0,0 +1,107 @@ +/* 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_STAR_VIEW_H +#define TITANIC_STAR_VIEW_H + +#include "titanic/support/simple_file.h" +#include "titanic/support/video_surface.h" +#include "titanic/star_control/star_control_sub12.h" +#include "titanic/star_control/star_control_sub13.h" +#include "titanic/star_control/surface_fader.h" +#include "titanic/star_control/error_code.h" + +namespace Titanic { + +class CStarControl; +class CStarField; + +class CStarView { +private: + CStarControl *_owner; + CStarField *_starField; + CVideoSurface *_videoSurface; + CStarControlSub12 _sub12; + int _field118; + CStarControlSub13 _sub13; + CSurfaceFader _fader; + CVideoSurface *_videoSurface2; + int _field210; + CGameObject *_homePhotoMask; + int _field218; + int _field21C; +private: + void fn1(); +public: + CStarView(); + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file, int param); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file, int indent); + + /** + * Sets references used by the view + */ + void setup(CScreenManager *screenManager, CStarField *starField, CStarControl *starControl); + + void reset(); + + /** + * Allows the item to draw itself + */ + void draw(CScreenManager *screenManager); + + /** + * Handles mouse down messages + */ + void MouseButtonDownMsg(int unused, const Point &pt); + + /** + * Handles mouse move messages + */ + void MouseMoveMsg(int unused, const Point &pt); + + /** + * Handles keyboard messages + */ + CErrorCode KeyCharMsg(int key); + + /** + * Returns true if a star destination can be set + */ + bool canSetStarDestination() const; + + /** + * Called when a star destination is set + */ + void starDestinationSet(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_RENDERER_H */ diff --git a/engines/titanic/star_control/surface_area.cpp b/engines/titanic/star_control/surface_area.cpp new file mode 100644 index 0000000000..77f8222dad --- /dev/null +++ b/engines/titanic/star_control/surface_area.cpp @@ -0,0 +1,50 @@ +/* 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/star_control/surface_area.h" + +namespace Titanic { + +CSurfaceArea::CSurfaceArea(CVideoSurface *surface) { + _width = surface->getWidth(); + _height = surface->getHeight(); + _pitch = surface->getPitch(); + + // Original supported other pixel depths + _bpp = surface->getPixelDepth(); + assert(_bpp == 2); + _pixelsPtr = surface->getPixels(); + + initialize(); +} + +void CSurfaceArea::initialize() { + _bounds = Rect(0, 0, _width - 1, _height - 1); + _centroid = Point(_width / 2, _height / 2); + _field22 = _field21 = _field20 = 0xFF; + _field27 = _field26 = _field25 = 0; + _field24 = _field23 = 0; + _field28 = _field2C = 0; + _field38 = 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/surface_area.h b/engines/titanic/star_control/surface_area.h new file mode 100644 index 0000000000..4d1913123c --- /dev/null +++ b/engines/titanic/star_control/surface_area.h @@ -0,0 +1,65 @@ +/* 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_SURFACE_OBJ_H +#define TITANIC_SURFACE_OBJ_H + +#include "titanic/support/rect.h" +#include "titanic/support/video_surface.h" + +namespace Titanic { + +class CSurfaceArea { +private: + /** + * Initialize data for the class + */ + void initialize(); +public: + int _field0; + int _width; + int _height; + int _pitch; + int _bpp; + uint16 *_pixelsPtr; + Point _centroid; + byte _field20; + byte _field21; + byte _field22; + byte _field23; + byte _field24; + byte _field25; + byte _field26; + byte _field27; + int _field28; + int _field2C; + int _field30; + int _field34; + int _field38; + Rect _bounds; +public: + CSurfaceArea(CVideoSurface *surface); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STAR_CONTROL_SUB16_H */ diff --git a/engines/titanic/star_control/surface_fader.cpp b/engines/titanic/star_control/surface_fader.cpp new file mode 100644 index 0000000000..089ad51717 --- /dev/null +++ b/engines/titanic/star_control/surface_fader.cpp @@ -0,0 +1,73 @@ +/* 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/star_control/surface_fader.h" +#include "common/system.h" +#include "graphics/pixelformat.h" + +namespace Titanic { + +CSurfaceFader::CSurfaceFader() : CSurfaceFaderBase() { + _dataP = new byte[_count]; + + for (int idx = 0; idx < _count; ++idx) { + // TODO: Setup data bytes + } +} + +CSurfaceFader::~CSurfaceFader() { + delete[] _dataP; +} + +void CSurfaceFader::copySurface(CSurfaceArea &srcSurface, CSurfaceArea &destSurface) { + const uint16 *srcPixelP = srcSurface._pixelsPtr; + uint16 *destPixelP = destSurface._pixelsPtr; + + // Currently we only support 2 bytes per pixel surfaces + assert(srcSurface._bpp == 2); + + byte dataVal = _dataP[_index]; + double fraction = (double)dataVal / ((double)(_count - 1)); + if (!_fadeIn) + // For fade outs, reverse the percentage visibility + fraction = 1.0 - fraction; + + // Iterate through the pixels + byte r, g, b; + Graphics::PixelFormat format = g_system->getScreenFormat(); + + for (int yp = 0; yp < srcSurface._height; ++yp) { + for (int xp = 0; xp < srcSurface._width; ++xp, ++srcPixelP, ++destPixelP) { + format.colorToRGB(*srcPixelP, r, g, b); + r = (byte)((double)r * fraction); + g = (byte)((double)g * fraction); + b = (byte)((double)b * fraction); + *destPixelP = format.RGBToColor(r, g, b); + } + } +} + +void CSurfaceFader::setFadeIn(bool fadeIn) { + _fadeIn = fadeIn; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/surface_fader.h b/engines/titanic/star_control/surface_fader.h new file mode 100644 index 0000000000..650cbbb19b --- /dev/null +++ b/engines/titanic/star_control/surface_fader.h @@ -0,0 +1,51 @@ +/* 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_SURFACE_FADER_H +#define TITANIC_SURFACE_FADER_H + +#include "titanic/star_control/surface_fader_base.h" + +namespace Titanic { + +class CSurfaceFader: public CSurfaceFaderBase { +private: + byte *_dataP; + bool _fadeIn; +protected: + /** + * Create a faded version of the source surface at the given dest + */ + virtual void copySurface(CSurfaceArea &srcSurface, CSurfaceArea &destSurface); +public: + CSurfaceFader(); + virtual ~CSurfaceFader(); + + /** + * Sets whether a fade in (versus a fade out) should be done + */ + void setFadeIn(bool fadeIn); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SURFACE_SHADER_H */ diff --git a/engines/titanic/star_control/surface_fader_base.cpp b/engines/titanic/star_control/surface_fader_base.cpp new file mode 100644 index 0000000000..dfd7c4ab1d --- /dev/null +++ b/engines/titanic/star_control/surface_fader_base.cpp @@ -0,0 +1,78 @@ +/* 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/star_control/surface_fader_base.h" + +namespace Titanic { + +CSurfaceFaderBase::CSurfaceFaderBase() : _index(-1), _count(32), + _videoSurface(nullptr) { +} + +CSurfaceFaderBase::~CSurfaceFaderBase() { + delete _videoSurface; +} + +void CSurfaceFaderBase::reset() { + _index = 0; +} + +bool CSurfaceFaderBase::setupSurface(CScreenManager *screenManager, CVideoSurface *srcSurface) { + int width = srcSurface->getWidth(); + int height = srcSurface->getHeight(); + + if (_videoSurface) { + if (width == _videoSurface->getWidth() && _videoSurface->getHeight()) + // Allocated surface already matches new size + return true; + + // Different sizes, so delete old surface + delete _videoSurface; + } + + _videoSurface = screenManager->createSurface(width, height); + return true; +} + +CVideoSurface *CSurfaceFaderBase::fade(CScreenManager *screenManager, CVideoSurface *srcSurface) { + if (_index == -1 || _index >= _count) + return srcSurface; + + if (!_count && !setupSurface(screenManager, srcSurface)) + return nullptr; + + srcSurface->lock(); + _videoSurface->lock(); + CSurfaceArea srCSurfaceArea(srcSurface); + CSurfaceArea destSurfaceObj(_videoSurface); + + // Copy the surface with fading + copySurface(srCSurfaceArea, destSurfaceObj); + + srcSurface->unlock(); + _videoSurface->unlock(); + + ++_index; + return _videoSurface; +} + +} // End of namespace Titanic diff --git a/engines/titanic/star_control/surface_fader_base.h b/engines/titanic/star_control/surface_fader_base.h new file mode 100644 index 0000000000..463183537b --- /dev/null +++ b/engines/titanic/star_control/surface_fader_base.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_SURFACE_FADER_BASE_H +#define TITANIC_SURFACE_FADER_BASE_H + +#include "titanic/support/video_surface.h" +#include "titanic/support/screen_manager.h" +#include "titanic/star_control/surface_area.h" + +namespace Titanic { + +class CSurfaceFaderBase { +private: + /** + * Sets up an internal surface to match the size of the specified one + */ + bool setupSurface(CScreenManager *screenManager, CVideoSurface *srcSurface); +protected: + /** + * Create a faded version of the source surface at the given dest + */ + virtual void copySurface(CSurfaceArea &srcSurface, CSurfaceArea &destSurface) = 0; +public: + int _index; + int _count; + CVideoSurface *_videoSurface; +public: + CSurfaceFaderBase(); + virtual ~CSurfaceFaderBase(); + + /** + * Reset fading back to the start + */ + virtual void reset(); + + /** + * Creates a faded version of the passed source surface, based on a percentage + * visibility specified by _index of _count + */ + virtual CVideoSurface *fade(CScreenManager *screenManager, CVideoSurface *srcSurface); + + /** + * Returns true if a fade is in progress + */ + bool isActive() const { return _index != -1 && _index < _count; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SURFACE_FADER_BASE_H */ diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp new file mode 100644 index 0000000000..c37bd83616 --- /dev/null +++ b/engines/titanic/support/avi_surface.cpp @@ -0,0 +1,361 @@ +/* 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/support/avi_surface.h" +#include "titanic/support/screen_manager.h" +#include "titanic/support/video_surface.h" +#include "common/system.h" +#include "graphics/pixelformat.h" +#include "video/avi_decoder.h" + +namespace Titanic { + +Video::AVIDecoder::AVIVideoTrack &AVIDecoder::getVideoTrack() { + for (TrackListIterator it = getTrackListBegin(); it != getTrackListEnd(); it++) + if ((*it)->getTrackType() == Track::kTrackTypeVideo) + return *static_cast<AVIVideoTrack *>(*it); + + error("Could not find video track"); +} + +/** + * Track filter for AVIDecoder that filters out any secondary video track + */ +static bool primaryTrackSelect(bool isVideo, int trackCounter) { + return !isVideo || trackCounter == 0; +} + +/** + * Track filter for AVIDecoder that only accepts the secondary video track + * for a video, if present + */ +static bool secondaryTrackSelect(bool isVideo, int trackCounter) { + return isVideo && trackCounter > 0; +} + +AVISurface::AVISurface(const CResourceKey &key) { + _videoSurface = nullptr; + _streamCount = 0; + _movieFrameSurface[0] = _movieFrameSurface[1] = nullptr; + + // Reset current frame. We need to keep track of frames separately from the decoders, + // since it needs to be able to go beyond the frame count or to negative to allow + // correct detection of when range playbacks have finished + _currentFrame = -1; + _isReversed = false; + + // Create a decoder for the audio (if any) and primary video track + _decoders[0] = new AVIDecoder(Audio::Mixer::kPlainSoundType, primaryTrackSelect); + if (!_decoders[0]->loadFile(key.getString())) + error("Could not open video - %s", key.getString().c_str()); + + _streamCount = 1; + + // Create a decoder for any secondary video track + AVIDecoder *decoder2 = new AVIDecoder(Audio::Mixer::kPlainSoundType, secondaryTrackSelect); + if (decoder2->loadFile(key.getString())) { + _decoders[1] = decoder2; + ++_streamCount; + } else { + delete decoder2; + _decoders[1] = nullptr; + } +} + +AVISurface::~AVISurface() { + if (_videoSurface) + _videoSurface->_transBlitFlag = false; + delete _movieFrameSurface[0]; + delete _movieFrameSurface[1]; + delete _decoders[0]; + delete _decoders[1]; +} + +bool AVISurface::play(uint flags, CGameObject *obj) { + if (flags & MOVIE_REVERSE) + return play(_decoders[0]->getFrameCount() - 1, 0, flags, obj); + else + return play(0, _decoders[0]->getFrameCount() - 1, flags, obj); +} + +bool AVISurface::play(int startFrame, int endFrame, uint flags, CGameObject *obj) { + if (flags & MOVIE_STOP_PREVIOUS) + stop(); + + return play(startFrame, endFrame, -1, flags, obj); +} + +bool AVISurface::play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj) { + CMovieRangeInfo *info = new CMovieRangeInfo(); + info->_startFrame = startFrame; + info->_endFrame = endFrame; + info->_isReversed = endFrame < startFrame; + info->_initialFrame = 0; + info->_isRepeat = flags & MOVIE_REPEAT; + + if (obj) { + CMovieEvent *me = new CMovieEvent(); + me->_type = MET_MOVIE_END; + me->_startFrame = startFrame; + me->_endFrame = endFrame; + me->_initialFrame = 0; + me->_gameObject = obj; + + info->addEvent(me); + } + + _movieRangeInfo.push_back(info); + + if (_movieRangeInfo.size() == 1) { + // First play call, so start the movie playing + setReversed(info->_isReversed); + return startAtFrame(initialFrame); + } else { + return true; + } +} + +void AVISurface::stop() { + _decoders[0]->stop(); + if (_decoders[1]) + _decoders[1]->stop(); + + _movieRangeInfo.destroyContents(); +} + +bool AVISurface::startAtFrame(int frameNumber) { + if (isPlaying()) + // If it's already playing, then don't allow it + return false; + + if (frameNumber == -1) + // Default to starting frame of first movie range + frameNumber = _movieRangeInfo.front()->_startFrame; + + // Get the initial frame + seekToFrame(frameNumber); + renderFrame(); + + // Start the playback + _decoders[0]->start(); + if (_decoders[1]) + _decoders[1]->start(); + + return true; +} + +void AVISurface::seekToFrame(uint frameNumber) { + if ((int)frameNumber != getFrame()) { + _decoders[0]->seekToFrame(frameNumber); + if (_decoders[1]) + _decoders[1]->seekToFrame(frameNumber); + + _currentFrame = (int)frameNumber; + } + + renderFrame(); +} + +void AVISurface::setReversed(bool isReversed) { + _decoders[0]->setReverse(isReversed); + if (_decoders[1]) + _decoders[1]->setReverse(isReversed); + + _isReversed = isReversed; +} + +bool AVISurface::handleEvents(CMovieEventList &events) { + if (!isPlaying()) + return true; + + CMovieRangeInfo *info = _movieRangeInfo.front(); + _currentFrame += _isReversed ? -1 : 1; + + int newFrame = _currentFrame; + if ((info->_isReversed && newFrame <= info->_endFrame) || + (!info->_isReversed && newFrame >= info->_endFrame)) { + if (info->_isRepeat) { + newFrame = info->_startFrame; + } else { + info->getMovieEnd(events); + _movieRangeInfo.remove(info); + delete info; + + if (_movieRangeInfo.empty()) { + // NO more ranges, so stop playback + stop(); + } else { + // Not empty, so move onto new first one + info = _movieRangeInfo.front(); + newFrame = info->_startFrame; + } + } + } + + if (isPlaying()) { + if (newFrame != getFrame()) { + // The frame has been changed, so move to new position + setReversed(info->_isReversed); + seekToFrame(newFrame); + } + + // Get any events for the given position + info->getMovieFrame(events, newFrame); + return renderFrame(); + } else { + return false; + } +} + +void AVISurface::setVideoSurface(CVideoSurface *surface) { + _videoSurface = surface; + + // Handling for secondary video stream + if (_decoders[1]) { + const Common::String &streamName = _decoders[1]->getVideoTrack().getName(); + + if (streamName == "mask0") { + _videoSurface->_transparencyMode = TRANS_MASK0; + } else if (streamName == "mask255") { + _videoSurface->_transparencyMode = TRANS_MASK255; + } else if (streamName == "alpha0") { + _videoSurface->_transparencyMode = TRANS_ALPHA0; + } else if (streamName == "alpha255") { + _videoSurface->_transparencyMode = TRANS_ALPHA255; + } + } + + setupDecompressor(); +} + +void AVISurface::setupDecompressor() { + for (int idx = 0; idx < 2; ++idx) { + if (!_decoders[idx]) + continue; + AVIDecoder &decoder = *_decoders[idx]; + + // Setup frame surface + _movieFrameSurface[idx] = new Graphics::ManagedSurface(decoder.getWidth(), decoder.getHeight(), + g_system->getScreenFormat()); + + // TODO: See whether this simplified form of original works + if (idx == 1) + _videoSurface->_transBlitFlag = true; + } +} + +uint AVISurface::getWidth() const { + return _decoders[0]->getWidth(); +} + +uint AVISurface::getHeight() const { + return _decoders[0]->getHeight(); +} + +void AVISurface::setFrame(int frameNumber) { + // If playback was in process, stop it + if (isPlaying()) + stop(); + + // Ensure the frame number is valid + if (frameNumber >= (int)_decoders[0]->getFrameCount()) + frameNumber = _decoders[0]->getFrameCount() - 1; + + seekToFrame(frameNumber); + renderFrame(); +} + +bool AVISurface::isNextFrame() const { + return _decoders[0]->getTimeToNextFrame() == 0; +} + +bool AVISurface::renderFrame() { + // Check there's a frame ready for display + if (!_decoders[0]->needsUpdate()) + return false; + + // Decode each decoder's video stream into the appropriate surface + for (int idx = 0; idx < _streamCount; ++idx) { + const Graphics::Surface *frame = _decoders[idx]->decodeNextFrame(); + + if (_movieFrameSurface[idx]->format == frame->format) { + _movieFrameSurface[idx]->blitFrom(*frame); + } else { + // Format mis-match, so we need to convert the frame + Graphics::Surface *s = frame->convertTo(_movieFrameSurface[idx]->format, + _decoders[idx]->getPalette()); + _movieFrameSurface[idx]->blitFrom(*s); + s->free(); + delete s; + } + } + + // Blit the primary video frame onto the main overall surface + _videoSurface->lock(); + _videoSurface->getRawSurface()->blitFrom(*_movieFrameSurface[0]); + _videoSurface->unlock(); + + return false; +} + +bool AVISurface::addEvent(int frameNumber, CGameObject *obj) { + if (!_movieRangeInfo.empty()) { + CMovieRangeInfo *tail = _movieRangeInfo.back(); + if (frameNumber == -1) + frameNumber = tail->_startFrame; + + CMovieEvent *me = new CMovieEvent(); + me->_type = MET_FRAME; + me->_startFrame = 0; + me->_endFrame = 0; + me->_initialFrame = frameNumber; + me->_gameObject = obj; + tail->addEvent(me); + + return _movieRangeInfo.size() == 1 && frameNumber == getFrame(); + } + + return false; +} + +void AVISurface::setFrameRate(double rate) { + _decoders[0]->setRate(Common::Rational(rate)); + if (_decoders[1]) + _decoders[1]->setRate(Common::Rational(rate)); +} + +Graphics::ManagedSurface *AVISurface::getSecondarySurface() { + return _streamCount <= 1 ? nullptr : _movieFrameSurface[1]; +} + +Graphics::ManagedSurface *AVISurface::duplicateSecondaryFrame() const { + if (_streamCount <= 1) { + return nullptr; + } else { + Graphics::ManagedSurface *dest = new Graphics::ManagedSurface(_movieFrameSurface[1]->w, + _movieFrameSurface[1]->h, _movieFrameSurface[1]->format); + dest->blitFrom(*_movieFrameSurface[1]); + return dest; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/avi_surface.h b/engines/titanic/support/avi_surface.h new file mode 100644 index 0000000000..d21182bca9 --- /dev/null +++ b/engines/titanic/support/avi_surface.h @@ -0,0 +1,183 @@ +/* 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_AVI_SURFACE_H +#define TITANIC_AVI_SURFACE_H + +#include "video/avi_decoder.h" +#include "graphics/managed_surface.h" +#include "titanic/core/resource_key.h" +#include "titanic/support/movie_range_info.h" + +namespace Titanic { + +class CSoundManager; +class CVideoSurface; + +enum MovieFlag { + MOVIE_REPEAT = 1, MOVIE_STOP_PREVIOUS = 2, MOVIE_NOTIFY_OBJECT = 4, + MOVIE_REVERSE = 8, MOVIE_GAMESTATE = 0x10 +}; + +class AVIDecoder : public Video::AVIDecoder { +public: + AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType, SelectTrackFn trackFn = nullptr) : + Video::AVIDecoder(soundType, trackFn) {} + AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType, + SelectTrackFn trackFn = nullptr) : Video::AVIDecoder(frameRateOverride, soundType, trackFn) {} + + Video::AVIDecoder::AVIVideoTrack &getVideoTrack(); +}; + +class AVISurface { +private: + AVIDecoder *_decoders[2]; + CVideoSurface *_videoSurface; + CMovieRangeInfoList _movieRangeInfo; + int _streamCount; + Graphics::ManagedSurface *_movieFrameSurface[2]; + bool _isReversed; + int _currentFrame; +private: + /** + * Render a frame to the video surface + */ + bool renderFrame(); + + /** + * Sets up for video decompression + */ + void setupDecompressor(); +protected: + /** + * Start playback at the specified frame + */ + bool startAtFrame(int frameNumber); + + /** + * Sets whether the movie is playing in reverse + */ + void setReversed(bool isReversed); + + /** + * Seeks to a given frame number in the video + */ + virtual void seekToFrame(uint frameNumber); +public: + CSoundManager *_soundManager; + bool _hasAudio; + double _frameRate; +public: + AVISurface(const CResourceKey &key); + virtual ~AVISurface(); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(uint flags, CGameObject *obj); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(int startFrame, int endFrame, uint flags, CGameObject *obj); + + /** + * Start playing the loaded AVI video + */ + virtual bool play(int startFrame, int endFrame, int initialFrame, uint flags, CGameObject *obj); + + /** + * Stop the currently playing video + */ + virtual void stop(); + + /** + * Return true if a video is currently playing + */ + virtual bool isPlaying() const { return _decoders[0]->isPlaying(); } + + /** + * Handle any movie events relevent for the frame + */ + virtual bool handleEvents(CMovieEventList &events); + + /** + * Set the video surface the AVI Surface will render on + */ + void setVideoSurface(CVideoSurface *surface); + + /** + * Get the width of the video + */ + uint getWidth() const; + + /** + * Get the height of the video + */ + uint getHeight() const; + + /** + * Set the current frame + */ + void setFrame(int frameNumber); + + /** + * Gets the current frame + */ + int getFrame() const { return _currentFrame; } + + /** + * Add a movie event + */ + bool addEvent(int frameNumber, CGameObject *obj); + + /** + * Set the frame rate + */ + void setFrameRate(double rate); + + /** + * Returns the surface for the secondary video track frame, if present + */ + Graphics::ManagedSurface *getSecondarySurface(); + + /** + * Get a reference to the movie range info list + */ + const CMovieRangeInfoList *getMovieRangeInfo() const { + return &_movieRangeInfo; + } + + /** + * Duplicates the secondary frame, if the movie has a second video track + */ + Graphics::ManagedSurface *duplicateSecondaryFrame() const; + + /** + * Returns true if it's time for the next + */ + bool isNextFrame() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_AVI_SURFACE_H */ diff --git a/engines/titanic/support/credit_text.cpp b/engines/titanic/support/credit_text.cpp new file mode 100644 index 0000000000..0e9715aaa6 --- /dev/null +++ b/engines/titanic/support/credit_text.cpp @@ -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. + * + */ + +#include "titanic/support/credit_text.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CCreditText::CCreditText() : _screenManagerP(nullptr), _field14(0), + _ticks(0), _fontHeight(1), _objectP(nullptr), _totalHeight(0), + _field40(0), _field44(0), _field48(0), _field4C(0), _field50(0), + _field54(0), _field58(0), _field5C(0) { +} + +void CCreditText::clear() { + _groups.destroyContents(); + _objectP = nullptr; +} + +void CCreditText::load(CGameObject *obj, CScreenManager *screenManager, + const Rect &rect, int v) { + _objectP = obj; + _screenManagerP = screenManager; + _field14 = v; + + setup(); + + _ticks = g_vm->_events->getTicksCount(); + _field40 = 0; + _field44 = 0xFF; + _field48 = 0xFF; + _field4C = 0xFF; + _field50 = 0; + _field54 = 0; + _field58 = 0; + _field5C = 0; +} + +void CCreditText::setup() { + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource( + CString::format("TEXT/155")); + int oldFontNumber = _screenManagerP->setFontNumber(3); + _fontHeight = _screenManagerP->getFontHeight(); + + while (stream->pos() < stream->size()) { + // Read in the line + CString srcLine = readLine(stream); + + // Create a new group and line within it + CCreditLineGroup *group = new CCreditLineGroup(); + CCreditLine *line = new CCreditLine(srcLine, + _screenManagerP->stringWidth(srcLine)); + group->_lines.push_back(line); + + // Loop to add more lines to the group + bool hasDots = false; + while (stream->pos() < stream->size()) { + srcLine = readLine(stream); + if (srcLine.empty()) + break; + + line = new CCreditLine(srcLine, + _screenManagerP->stringWidth(srcLine)); + group->_lines.push_back(line); + + if (srcLine.contains("....")) + hasDots = true; + } + + _groups.push_back(group); + } + + _groupIt = _groups.begin(); + _lineIt = (*_groupIt)->_lines.begin(); + _totalHeight = _objectP->getBounds().height() + _fontHeight * 2; +} + +CString CCreditText::readLine(Common::SeekableReadStream *stream) { + CString line; + char c = stream->readByte(); + + while (c != '\r' && c != '\n' && c != '\0') { + line += c; + + if (stream->pos() == stream->size()) + break; + c = stream->readByte(); + } + + if (c == '\r') { + // Read following '\n' + stream->readByte(); + } + + return line; +} + +void CCreditText::handleDots(CCreditLineGroup *group) { + uint maxWidth = 0; + CCreditLines::iterator second = group->_lines.begin(); + ++second; + + // Figure out the maximum width of secondary lines + for (CCreditLines::iterator i = second; i != group->_lines.end(); ++i) + maxWidth = MAX(maxWidth, (*i)->_lineWidth); + + int charWidth = _screenManagerP->stringWidth("."); + + // Process the secondary lines + for (CCreditLines::iterator i = second; i != group->_lines.end(); ++i) { + CCreditLine *line = *i; + if (line->_lineWidth >= maxWidth) + continue; + + int dotsCount = (maxWidth + charWidth / 2 - line->_lineWidth) / charWidth; + int dotIndex = line->_line.indexOf("...."); + + if (dotIndex > 0) { + CString leftStr = line->_line.left(dotIndex); + CString dotsStr('.', dotsCount); + CString rightStr = line->_line.right(dotIndex); + + line->_line = CString::format("%s%s%s", leftStr.c_str(), + dotsStr.c_str(), rightStr.c_str()); + line->_lineWidth = maxWidth; + } + } +} + +bool CCreditText::draw() { + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/credit_text.h b/engines/titanic/support/credit_text.h new file mode 100644 index 0000000000..ec8fc22cda --- /dev/null +++ b/engines/titanic/support/credit_text.h @@ -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. + * + */ + +#ifndef TITANIC_CREDIT_TEXT_H +#define TITANIC_CREDIT_TEXT_H + +#include "titanic/core/list.h" + +namespace Titanic { + +class CGameObject; +class CScreenManager; + +class CCreditLine : public ListItem { +public: + CString _line; + uint _lineWidth; +public: + CCreditLine() : _lineWidth(0) {} + CCreditLine(const CString &line, uint lineWidth) : _line(line), _lineWidth(lineWidth) {} +}; +typedef List<CCreditLine> CCreditLines; + +class CCreditLineGroup : public ListItem { +public: + CCreditLines _lines; +}; +typedef List<CCreditLineGroup> CCreditLineGroups; + +class CCreditText { +private: + /** + * Sets up needed data + */ + void setup(); + + /** + * Read in a text line from the passed stream + */ + CString readLine(Common::SeekableReadStream *stream); + + /** + * Handles a group where the .... sequence was encountered + */ + void handleDots(CCreditLineGroup *group); +public: + CScreenManager *_screenManagerP; + Rect _rect; + int _field14; + CCreditLineGroups _groups; + uint _ticks; + uint _fontHeight; + CGameObject *_objectP; + CCreditLineGroups::iterator _groupIt; + CCreditLines::iterator _lineIt; + uint _totalHeight; + int _field40; + int _field44; + int _field48; + int _field4C; + int _field50; + int _field54; + int _field58; + int _field5C; +public: + CCreditText(); + + /** + * Clears the object + */ + void clear(); + + /** + * Sets the game object this override is associated with + */ + void load(CGameObject *obj, CScreenManager *screenManager, + const Rect &rect, int v = 0); + + /** + * Draw the item + */ + bool draw(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_CREDIT_TEXT_H */ diff --git a/engines/titanic/support/direct_draw.cpp b/engines/titanic/support/direct_draw.cpp new file mode 100644 index 0000000000..6958896077 --- /dev/null +++ b/engines/titanic/support/direct_draw.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/debug.h" +#include "engines/util.h" +#include "graphics/pixelformat.h" +#include "titanic/support/direct_draw.h" +#include "titanic/titanic.h" + +namespace Titanic { + +DirectDraw::DirectDraw(TitanicEngine *vm) : _vm(vm), + _windowed(false), _fieldC(0), _width(0), _height(0), + _bpp(0), _numBackSurfaces(0), _field24(0) { +} + +void DirectDraw::setDisplayMode(int width, int height, int bpp, int refreshRate) { + debugC(ERROR_BASIC, kDebugGraphics, "DirectDraw::SetDisplayMode (%d x %d), %d bpp", + width, height, bpp); + assert(bpp == 16); + + Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); + initGraphics(width, height, true, &pixelFormat); +} + +void DirectDraw::diagnostics() { + debugC(ERROR_BASIC, kDebugGraphics, "Running DirectDraw Diagnostic..."); +} + +DirectDrawSurface *DirectDraw::createSurfaceFromDesc(const DDSurfaceDesc &desc) { + DirectDrawSurface *surface = new DirectDrawSurface(); + surface->create(desc._w, desc._h); + + return surface; +} + +/*------------------------------------------------------------------------*/ + +DirectDrawManager::DirectDrawManager(TitanicEngine *vm, bool windowed) : _directDraw(vm) { + _mainSurface = nullptr; + _backSurfaces[0] = _backSurfaces[1] = nullptr; + _directDraw._windowed = windowed; +} + +void DirectDrawManager::initVideo(int width, int height, int bpp, int numBackSurfaces) { + debugC(ERROR_BASIC, kDebugGraphics, "Initialising video surfaces"); + _directDraw._width = width; + _directDraw._numBackSurfaces = numBackSurfaces; + _directDraw._height = height; + _directDraw._bpp = bpp; + + if (_directDraw._windowed) { + initWindowed(); + } else { + initFullScreen(); + } +} + +void DirectDrawManager::setResolution() { + // TODO +} + +void DirectDrawManager::proc2() { + +} + +void DirectDrawManager::proc3() { + +} + +void DirectDrawManager::initFullScreen() { + debugC(ERROR_BASIC, kDebugGraphics, "Creating surfaces"); + _directDraw.setDisplayMode(_directDraw._width, _directDraw._height, + _directDraw._bpp, 0); + + _mainSurface = new DirectDrawSurface(); + _mainSurface->create(g_vm->_screen); + _backSurfaces[0] = new DirectDrawSurface(); + _backSurfaces[0]->create(_directDraw._width, _directDraw._height); +} + +DirectDrawSurface *DirectDrawManager::createSurface(int w, int h, int surfaceNum) { + if (surfaceNum) + return nullptr; + + assert(_mainSurface); + return _directDraw.createSurfaceFromDesc(DDSurfaceDesc(w, h)); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/direct_draw.h b/engines/titanic/support/direct_draw.h new file mode 100644 index 0000000000..85c344c600 --- /dev/null +++ b/engines/titanic/support/direct_draw.h @@ -0,0 +1,105 @@ +/* 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_DIRECT_DRAW_H +#define TITANIC_DIRECT_DRAW_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "titanic/support/direct_draw_surface.h" + +namespace Titanic { + +class TitanicEngine; + +class DirectDraw { +private: + TitanicEngine *_vm; +public: + bool _windowed; + int _fieldC; + int _width; + int _height; + int _bpp; + int _numBackSurfaces; + int _field24; +public: + DirectDraw(TitanicEngine *vm); + + /** + * Sets a new display mode + */ + void setDisplayMode(int width, int height, int bpp, int refreshRate); + + /** + * Logs diagnostic information + */ + void diagnostics(); + + /** + * Create a surface from a passed description record + */ + DirectDrawSurface *createSurfaceFromDesc(const DDSurfaceDesc &desc); +}; + +class DirectDrawManager { +public: + DirectDraw _directDraw; + DirectDrawSurface *_mainSurface; + DirectDrawSurface *_backSurfaces[2]; +public: + DirectDrawManager(TitanicEngine *vm, bool windowed); + + /** + * Initializes video surfaces + * @param width Screen width + * @param height Screen height + * @param bpp Bits per pixel + * @param numBackSurfaces Number of back surfaces + */ + void initVideo(int width, int height, int bpp, int numBackSurfaces); + + void setResolution(); + + void proc2(); + + void proc3(); + + /** + * Initializes the surfaces in windowed mode + */ + void initWindowed() { initFullScreen(); } + + /** + * Initializes the surfaces for the screen + */ + void initFullScreen(); + + /** + * Create a surface + */ + DirectDrawSurface *createSurface(int w, int h, int surfaceNum); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DIRECT_DRAW_H */ diff --git a/engines/titanic/support/direct_draw_surface.cpp b/engines/titanic/support/direct_draw_surface.cpp new file mode 100644 index 0000000000..9ebda15b0e --- /dev/null +++ b/engines/titanic/support/direct_draw_surface.cpp @@ -0,0 +1,100 @@ +/* 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/support/direct_draw_surface.h" + +namespace Titanic { + +DirectDrawSurface::DirectDrawSurface() : _surface(nullptr), + _disposeAfterUse(DisposeAfterUse::YES) { +} + +DirectDrawSurface::~DirectDrawSurface() { + free(); +} + +void DirectDrawSurface::create(Graphics::ManagedSurface *surface) { + free(); + _surface = surface; + _disposeAfterUse = DisposeAfterUse::NO; +} + +void DirectDrawSurface::create(int w, int h) { + Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); + _surface = new Graphics::ManagedSurface(w, h, pixelFormat); + _disposeAfterUse = DisposeAfterUse::YES; +} + +void DirectDrawSurface::free() { + if (_disposeAfterUse == DisposeAfterUse::YES) + delete _surface; + _surface = nullptr; + _disposeAfterUse = DisposeAfterUse::NO; +} + +Graphics::ManagedSurface *DirectDrawSurface::lock(const Rect *bounds, int flags) { + assert(!_surface->empty()); + return _surface; +} + +void DirectDrawSurface::unlock() { + assert(_surface->w != 0 && _surface->h != 0); +} + +void DirectDrawSurface::fill(const Rect *bounds, uint32 color) { + Rect tempBounds; + + assert(_surface); + if (bounds) { + // Bounds are provided, clip them to the bounds of this surface + tempBounds = *bounds; + tempBounds.clip(Rect(0, 0, _surface->w, _surface->h)); + } else { + // No bounds provided, so use the entire surface + tempBounds = Rect(0, 0, _surface->w, _surface->h); + } + + // Fill the area + _surface->fillRect(tempBounds, color); +} + +void DirectDrawSurface::fillRect(Rect *rect, byte r, byte g, byte b) { + uint color = _surface->format.RGBToColor(r, g, b); + Rect tempRect = rect ? *rect : Rect(0, 0, getWidth(), getHeight()); + + _surface->fillRect(tempRect, color); +} + +void DirectDrawSurface::blit(const Rect &destRect, DirectDrawSurface *srcSurface, Rect &srcRect) { + assert(srcSurface); + if (!destRect.isEmpty()) + _surface->transBlitFrom(*srcSurface->_surface, srcRect, destRect, (uint)-1); +} + +void DirectDrawSurface::blit(const Point &destPos, DirectDrawSurface *srcSurface, Rect *bounds) { + if (bounds) + _surface->blitFrom(*srcSurface->_surface, *bounds, destPos); + else + _surface->blitFrom(*srcSurface->_surface, destPos); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/direct_draw_surface.h b/engines/titanic/support/direct_draw_surface.h new file mode 100644 index 0000000000..af19e369d2 --- /dev/null +++ b/engines/titanic/support/direct_draw_surface.h @@ -0,0 +1,126 @@ +/* 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_DIRECT_DRAW_SURFACE_H +#define TITANIC_DIRECT_DRAW_SURFACE_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "graphics/managed_surface.h" +#include "titanic/support/rect.h" + +namespace Titanic { + +class TitanicEngine; + +struct DDSurfaceDesc { + int _w; + int _h; + int _flags; + int _caps; + + DDSurfaceDesc(int w, int h) : _w(w), _h(h), _flags(0x1006), _caps(64) {} +}; + +class DirectDrawSurface { +private: + Graphics::ManagedSurface *_surface; + DisposeAfterUse::Flag _disposeAfterUse; +public: + DirectDrawSurface(); + ~DirectDrawSurface(); + + /** + * Create a surface + */ + void create(int w, int h); + + /** + * Create a surface based on a passed surface + */ + void create(Graphics::ManagedSurface *surface); + + /** + * Frees the surface + */ + void free(); + + /** + * Return the size of the surface in ytes + */ + int getSize() const { return _surface->pitch * _surface->h; } + + /** + * Return the surface width + */ + int getWidth() const { return _surface->w; } + + /** + * Return the surface width + */ + int getHeight() const { return _surface->h; } + + /** + * Return the surface pitch + */ + int getPitch() const { return _surface->pitch; } + + /** + * Return the surface's format + */ + const Graphics::PixelFormat &getFormat() { return _surface->format; } + + /** + * Lock the surface for access + */ + Graphics::ManagedSurface *lock(const Rect *bounds, int flags); + + /** + * Unlocks the surface at the end of direct accesses + */ + void unlock(); + + /** + * Fills an area of the surfae with the specified color. If no bounds are passed, + * then the entire surface is filled + */ + void fill(const Rect *bounds, uint32 color); + + /** + * Fill an area with a specific color + */ + void fillRect(Rect *rect, byte r, byte g, byte b); + + /** + * Copy data from a source surfcae into this one + */ + void blit(const Rect &destRect, DirectDrawSurface *srcSurface, Rect &srcRect); + + /** + * Copy data from a source surfcae into this one + */ + void blit(const Point &destPos, DirectDrawSurface *srcSurface, Rect *bounds); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DIRECT_DRAW_SURFACE_H */ diff --git a/engines/titanic/support/exe_resources.cpp b/engines/titanic/support/exe_resources.cpp new file mode 100644 index 0000000000..2b2c9c7635 --- /dev/null +++ b/engines/titanic/support/exe_resources.cpp @@ -0,0 +1,38 @@ +/* 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/support/exe_resources.h" +#include "titanic/true_talk/script_handler.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CExeResources::CExeResources() : _owner(nullptr), _field4(0), _field8(0), + _fieldC(0), _field10(0), _field14(0), _field18(0) { +} + +void CExeResources::reset(CScriptHandler *owner, int val1, int val2) { + _owner = owner; + _field18 = val2; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/exe_resources.h b/engines/titanic/support/exe_resources.h new file mode 100644 index 0000000000..993c34db97 --- /dev/null +++ b/engines/titanic/support/exe_resources.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_EXE_RESOURCES_H +#define TITANIC_EXE_RESOURCES_H + +namespace Titanic { + +class CScriptHandler; + +enum FileHandle { HANDLE_STDIN = 0, HANDLE_STDOUT = 1, HANDLE_STDERR = 2 }; + +class CExeResources { +public: + CScriptHandler *_owner; + int _field4; + int _field8; + int _fieldC; + int _field10; + int _field14; + int _field18; +public: + CExeResources(); + + void reset(CScriptHandler *owner, int val1, int val2); + + bool is18Equals(int val) const { return _field18 == val; } + int get18() const { return _field18; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_EXE_RESOURCES_H */ diff --git a/engines/titanic/support/files_manager.cpp b/engines/titanic/support/files_manager.cpp new file mode 100644 index 0000000000..89e0a1d10e --- /dev/null +++ b/engines/titanic/support/files_manager.cpp @@ -0,0 +1,134 @@ +/* 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/file.h" +#include "common/memstream.h" +#include "titanic/support/files_manager.h" +#include "titanic/game_manager.h" + +namespace Titanic { + +CFilesManager::CFilesManager() : _gameManager(nullptr), _assetsPath("Assets"), + _field0(0), _drive(-1), _field18(0), _field1C(0), _field3C(0) { + loadResourceIndex(); +} + +CFilesManager::~CFilesManager() { + _datFile.close(); +} + +void CFilesManager::loadResourceIndex() { + if (!_datFile.open("titanic.dat")) + error("Could not find titanic.dat data file"); + + uint headerId = _datFile.readUint32BE(); + uint version = _datFile.readUint16LE(); + if (headerId != MKTAG('S', 'V', 'T', 'N') || version < 1) + error("Invalid data file"); + + // Read in entries + uint offset, size; + char c; + Common::String resourceName; + for (;;) { + offset = _datFile.readUint32LE(); + size = _datFile.readUint32LE(); + if (offset == 0 && size == 0) + break; + + Common::String resName; + while ((c = _datFile.readByte()) != '\0') + resName += c; + + _resources[resName] = ResourceEntry(offset, size); + } +} + +bool CFilesManager::fileExists(const CString &name) { + Common::File f; + return f.exists(name); +} + +bool CFilesManager::scanForFile(const CString &name) { + if (name.empty()) + return false; + + CString filename = name; + filename.toLowercase(); + + if (filename[0] == 'y' || filename[0] == 'z') + return true; + else if (filename[0] < 'a' || filename[0] > 'c') + return false; + + CString fname = filename; + int idx = fname.indexOf('#'); + if (idx >= 0) { + fname = fname.left(idx); + fname += ".st"; + } + + // Return true if the file exists + if (fileExists(fname)) + return true; + + // Couldn't find file. Start by calling the game manager's viewChange + // method, which handles all active scene objects freeing their resources + if (_gameManager) + _gameManager->viewChange(); + + return false; +} + +void CFilesManager::loadDrive() { + assert(_drive == -1); + resetView(); +} + +void CFilesManager::debug(CScreenManager *screenManager) { + warning("TODO: CFilesManager::debug"); +} + +void CFilesManager::resetView() { + if (_gameManager) { + _gameManager->_gameState.setMode(GSMODE_INTERACTIVE); + _gameManager->initBounds(); + } +} + +void CFilesManager::fn4(const CString &name) { + warning("TODO: CFilesManager::fn4"); +} + +void CFilesManager::preload(const CString &name) { + // We don't currently do any preloading of resources +} + +Common::SeekableReadStream *CFilesManager::getResource(const CString &str) { + ResourceEntry resEntry = _resources[str]; + _datFile.seek(resEntry._offset); + + return (resEntry._size > 0) ? _datFile.readStream(resEntry._size) : + new Common::MemoryReadStream(nullptr, 0); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/files_manager.h b/engines/titanic/support/files_manager.h new file mode 100644 index 0000000000..ec0c7fc008 --- /dev/null +++ b/engines/titanic/support/files_manager.h @@ -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. + * + */ + +#ifndef TITANIC_FILES_MANAGER_H +#define TITANIC_FILES_MANAGER_H + +#include "common/hashmap.h" +#include "titanic/core/list.h" +#include "titanic/support/screen_manager.h" + +namespace Titanic { + +class CGameManager; + +class CFilesManagerList : public List<ListItem> { +}; + +class CFilesManager { + struct ResourceEntry { + uint _offset; + uint _size; + + ResourceEntry() : _offset(0), _size(0) {} + ResourceEntry(uint offset, uint size) : _offset(offset), _size(size) {} + }; + typedef Common::HashMap<Common::String, ResourceEntry> ResourceHash; +private: + CGameManager *_gameManager; + Common::File _datFile; + ResourceHash _resources; + CFilesManagerList _list; + CString _string1; + CString _string2; + int _field0; + int _drive; + int _field18; + int _field1C; + int _field3C; + const CString _assetsPath; +private: + void loadResourceIndex(); +public: + CFilesManager(); + ~CFilesManager(); + + /** + * Sets the game manager + */ + void setGameManager(CGameManager *gameManager) { + _gameManager = gameManager; + } + + /** + * Returns true if a file of the given name exists + */ + static bool fileExists(const CString &name); + + /** + * Scans for a file with a matching name + */ + bool scanForFile(const CString &name); + + /** + * Handles displaying a load drive view if necessary + */ + void loadDrive(); + + void debug(CScreenManager *screenManager); + + /** + * Resets the view being displayed + */ + void resetView(); + + void fn4(const CString &name); + + /** + * Preloads and caches a file for access shortly + */ + void preload(const CString &name); + + /** + * Get a resource from the executable + */ + Common::SeekableReadStream *getResource(const CString &str); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_FILES_MANAGER_H */ diff --git a/engines/titanic/support/font.cpp b/engines/titanic/support/font.cpp new file mode 100644 index 0000000000..69c0efe504 --- /dev/null +++ b/engines/titanic/support/font.cpp @@ -0,0 +1,281 @@ +/* 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/support/font.h" +#include "titanic/support/files_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +STFont::STFont() { + _dataPtr = nullptr; + _dataSize = 0; + _fontHeight = 0; + _dataWidth = 0; + _fontR = _fontG = _fontB = 0; +} + +STFont::~STFont() { + delete[] _dataPtr; +} + +void STFont::load(int fontNumber) { + assert(!_dataPtr); + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource( + CString::format("STFONT/%d", fontNumber)); + if (!stream) + error("Could not locate the specified font"); + + _fontHeight = stream->readUint32LE(); + _dataWidth = stream->readUint32LE(); + for (uint idx = 0; idx < 256; ++idx) + _chars[idx]._width = stream->readUint32LE(); + for (uint idx = 0; idx < 256; ++idx) + _chars[idx]._offset = stream->readUint32LE(); + + _dataSize = stream->readUint32LE(); + _dataPtr = new byte[_dataSize]; + stream->read(_dataPtr, _dataSize); + + delete stream; +} + +void STFont::setColor(byte r, byte g, byte b) { + _fontR = r; + _fontG = g; + _fontB = b; +} + +uint16 STFont::getColor() const { + return g_system->getScreenFormat().RGBToColor(_fontR, _fontG, _fontB); +} + +int STFont::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const { + Point textSize; + + // Reset output dimensions if provided + if (sizeOut) + *sizeOut = Point(0, 0); + + if (_fontHeight == 0 || !_dataPtr) + // No font, so return immediately + return 0; + + // Loop through the characters of the string + if (!str.empty()) { + for (const char *strP = str.c_str(); *strP; ++strP) { + if (*strP == TEXTCMD_NPC) { + strP += 3; + } else if (*strP == TEXTCMD_SET_COLOR) { + strP += 4; + } else { + if (*strP == ' ') { + // Check fo rline wrapping + checkLineWrap(textSize, maxWidth, strP); + } + + extendBounds(textSize, *strP, maxWidth); + } + } + } + + if (sizeOut) + *sizeOut = textSize; + + return textSize.y + _fontHeight; +} + +int STFont::stringWidth(const CString &text) const { + if (text.empty()) + return 0; + + const char *srcP = text.c_str(); + int total = 0; + char c; + while ((c = *srcP++)) { + if (c == 26) { + // Skip over command parameter bytes + srcP += 3; + } else if (c == TEXTCMD_SET_COLOR) { + // Skip over command parameter bytes + srcP += 4; + } else if (c != '\n') { + total += _chars[(byte)c]._width; + } + } + + return total; +} + +int STFont::writeString(CVideoSurface *surface, const Rect &rect1, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor) { + if (!_fontHeight || !_dataPtr) + return -1; + + Point textSize(0, -yOffset); + Rect destBounds = destRect; + destBounds.constrain(rect1); + if (destBounds.isEmpty()) + return -1; + + const char *endP = nullptr; + const char *strEndP = str.c_str() + str.size() - 1; + for (const char *srcP = str.c_str(); *srcP; ++srcP) { + if (*srcP == TEXTCMD_NPC) { + srcP += 3; + } else if (*srcP == TEXTCMD_SET_COLOR) { + // Change the color used for characters + byte r = *++srcP; + byte g = *++srcP; + byte b = *++srcP; + ++srcP; + setColor(r, g, b); + } else { + if (*srcP == ' ') { + // Check fo rline wrapping + checkLineWrap(textSize, rect1.width(), srcP); + if (!*srcP) + return endP - str.c_str(); + } + + if (*srcP != '\n') { + WriteCharacterResult result = writeChar(surface, *srcP, textSize, rect1, &destBounds); + if (result == WC_OUTSIDE_BOTTOM) + return endP - str.c_str(); + else if (result == WC_IN_BOUNDS) + endP = srcP; + } + + if (srcP < strEndP) + extendBounds(textSize, *srcP, rect1.width()); + } + } + + if (textCursor && textCursor->getMode() == -2) { + Point cursorPos(rect1.left + textSize.x, rect1.top + textSize.y); + textCursor->setPos(cursorPos); + } + + return endP ? endP - str.c_str() : 0; +} + +WriteCharacterResult STFont::writeChar(CVideoSurface *surface, unsigned char c, const Point &pt, + const Rect &destRect, const Rect *srcRect) { + if (c == 233) + c = '$'; + + Rect tempRect; + tempRect.left = _chars[c]._offset; + tempRect.right = _chars[c]._offset + _chars[c]._width; + tempRect.top = 0; + tempRect.bottom = _fontHeight; + Point destPos(pt.x + destRect.left, pt.y + destRect.top); + + if (srcRect->isEmpty()) + srcRect = &destRect; + if (destPos.y > srcRect->bottom) + return WC_OUTSIDE_BOTTOM; + + if ((destPos.y + tempRect.height()) > srcRect->bottom) { + tempRect.bottom += tempRect.top - destPos.y; + } + + if (destPos.y < srcRect->top) { + if ((tempRect.height() + destPos.y) < srcRect->top) + return WC_OUTSIDE_TOP; + + tempRect.top += srcRect->top - destPos.y; + destPos.y = srcRect->top; + } + + if (destPos.x < srcRect->left) { + if ((tempRect.width() + destPos.x) < srcRect->left) + return WC_OUTSIDE_LEFT; + + tempRect.left += srcRect->left - destPos.x; + destPos.x = srcRect->left; + } else { + if ((tempRect.width() + destPos.x) > srcRect->right) { + if (destPos.x > srcRect->right) + return WC_OUTSIDE_RIGHT; + + tempRect.right += srcRect->left - destPos.x; + } + } + + copyRect(surface, destPos, tempRect); + return WC_IN_BOUNDS; +} + +void STFont::copyRect(CVideoSurface *surface, const Point &pt, Rect &rect) { + if (surface->lock()) { + uint16 *lineP = surface->getBasePtr(pt.x, pt.y); + uint16 color = getColor(); + + for (int yp = rect.top; yp < rect.bottom; ++yp, lineP += surface->getWidth()) { + uint16 *destP = lineP; + for (int xp = rect.left; xp < rect.right; ++xp, ++destP) { + const byte *srcP = _dataPtr + yp * _dataWidth + xp; + surface->changePixel(destP, &color, *srcP >> 3, true); + } + } + + surface->unlock(); + } +} + +void STFont::extendBounds(Point &textSize, byte c, int maxWidth) const { + textSize.x += _chars[c]._width; + + if (c == '\n' || textSize.x > maxWidth) { + textSize.x = 0; + textSize.y += _fontHeight; + } +} + +void STFont::checkLineWrap(Point &textSize, int maxWidth, const char *&str) const { + bool flag = false; + int totalWidth = 0; + for (const char *srcPtr = str; *srcPtr && *srcPtr != ' '; ++srcPtr) { + if (*srcPtr == ' ' && flag) + break; + + if (*srcPtr == TEXTCMD_NPC) { + srcPtr += 3; + } else if (*srcPtr == TEXTCMD_SET_COLOR) { + srcPtr += 4; + } else { + totalWidth += _chars[(byte)*srcPtr]._width; + flag = true; + } + } + + if ((textSize.x + totalWidth) >= maxWidth && totalWidth < maxWidth) { + // Word wrap + textSize.x = 0; + textSize.y += _fontHeight; + ++str; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/font.h b/engines/titanic/support/font.h new file mode 100644 index 0000000000..591fb4661c --- /dev/null +++ b/engines/titanic/support/font.h @@ -0,0 +1,123 @@ +/* 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_FONT_H +#define TITANIC_FONT_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "titanic/support/rect.h" +#include "titanic/support/string.h" +#include "titanic/support/text_cursor.h" + +namespace Titanic { + +enum TextCommand { TEXTCMD_NPC = 26, TEXTCMD_SET_COLOR = 27 }; + +enum WriteCharacterResult { + WC_IN_BOUNDS = 0, WC_OUTSIDE_TOP = -1, WC_OUTSIDE_BOTTOM = -2, + WC_OUTSIDE_LEFT = -3, WC_OUTSIDE_RIGHT = -4 +}; + +class CVideoSurface; + +class STFont { + struct CharEntry { + uint _width; + uint _offset; + }; +private: + /** + * Copys a rectangle representing a character in the font data to + * a given destination position in the surface + */ + void copyRect(CVideoSurface *surface, const Common::Point &destPos, + Rect &srcRect); + + /** + * Write a character + */ + WriteCharacterResult writeChar(CVideoSurface *surface, unsigned char c, + const Common::Point &pt, const Rect &destRect, const Rect *srcRect); + + /** + * Extends a passed text area by the space required for + * the given character + */ + void extendBounds(Point &textSize, byte c, int maxWidth) const; + + /** + * Called at spacing between words, checks for line wrapping + */ + void checkLineWrap(Point &textSize, int maxWidth, const char *&str) const; +public: + byte *_dataPtr; + size_t _dataSize; + int _fontHeight; + uint _dataWidth; + CharEntry _chars[256]; + byte _fontR, _fontG, _fontB; +public: + STFont(); + ~STFont(); + + /** + * Load a specified font + */ + void load(int fontNumber); + + /** + * Return the width in pixels of the specified text + */ + int stringWidth(const CString &text) const; + + /** + * Write a string to the specified surface + * @returns The index of the last character that was visible + * with the drawing area + */ + int writeString(CVideoSurface *surface, const Rect &rect1, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor); + + /** + * Get the text area a string will fit into + * @param str String + * @param maxWidth Maximum width in pixels + * @param sizeOut Optional pointer to output size (width, height) + * @returns Required height + */ + int getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const; + + /** + * Sets the font color + */ + void setColor(byte r, byte g, byte b); + + /** + * Gets the font color + */ + uint16 getColor() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_FONT_H */ diff --git a/engines/titanic/support/image.cpp b/engines/titanic/support/image.cpp new file mode 100644 index 0000000000..2da2179af0 --- /dev/null +++ b/engines/titanic/support/image.cpp @@ -0,0 +1,56 @@ +/* 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/support/image.h" +#include "image/bmp.h" +#include "titanic/titanic.h" + +namespace Titanic { + +void Image::load(const CString &resName) { + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource(resName); + loadBitmap(*stream); + delete stream; +} + +void Image::loadBitmap(Common::SeekableReadStream &s) { + ::Image::BitmapDecoder decoder; + decoder.loadStream(s); + const Graphics::Surface *src = decoder.getSurface(); + Graphics::PixelFormat scrFormat = g_system->getScreenFormat(); + + if (src->format == scrFormat) { + create(src->w, src->h, scrFormat); + blitFrom(*src); + } else { + // Convert the loaded surface to the screen surface format + const byte *palette = decoder.getPalette(); + Graphics::Surface *surface = src->convertTo(scrFormat, palette); + create(surface->w, surface->h, scrFormat); + blitFrom(*surface); + + surface->free(); + delete surface; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/image.h b/engines/titanic/support/image.h new file mode 100644 index 0000000000..9876f15c40 --- /dev/null +++ b/engines/titanic/support/image.h @@ -0,0 +1,43 @@ +/* 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_IMAGE_H +#define TITANIC_IMAGE_H + +#include "common/stream.h" +#include "graphics/managed_surface.h" +#include "titanic/support/string.h" + +namespace Titanic { + +class Image : public Graphics::ManagedSurface { +private: + void loadBitmap(Common::SeekableReadStream &s); +public: + virtual ~Image() {} + + void load(const CString &resName); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_IMAGE_H */ diff --git a/engines/titanic/support/image_decoders.cpp b/engines/titanic/support/image_decoders.cpp new file mode 100644 index 0000000000..495d1d0982 --- /dev/null +++ b/engines/titanic/support/image_decoders.cpp @@ -0,0 +1,81 @@ +/* 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/support/image_decoders.h" + +namespace Titanic { + +void CJPEGDecode::decode(OSVideoSurface &surface, const CString &name) { + // Open up the resource + StdCWadFile file; + file.open(name); + + // Use the ScucmmVM deoder to decode it + loadStream(*file.readStream()); + const Graphics::Surface *srcSurf = getSurface(); + + // Resize the surface if necessary + if (!surface.hasSurface() || surface.getWidth() != srcSurf->w + || surface.getHeight() != srcSurf->h) + surface.recreate(srcSurf->w, srcSurf->h); + + // Convert the decoded surface to the correct pixel format, and then copy it over + surface.lock(); + Graphics::Surface *convertedSurface = srcSurf->convertTo(surface._rawSurface->format); + + Common::copy((byte *)convertedSurface->getPixels(), (byte *)convertedSurface->getPixels() + + surface.getPitch() * surface.getHeight(), (byte *)surface._rawSurface->getPixels()); + + convertedSurface->free(); + delete convertedSurface; + surface.unlock(); +} + +/*------------------------------------------------------------------------*/ + +void CTargaDecode::decode(OSVideoSurface &surface, const CString &name) { + // Open up the resource + StdCWadFile file; + file.open(name); + + // Use the ScucmmVM deoder to decode it + loadStream(*file.readStream()); + const Graphics::Surface *srcSurf = getSurface(); + + // Resize the surface if necessary + if (!surface.hasSurface() || surface.getWidth() != srcSurf->w + || surface.getHeight() != srcSurf->h) + surface.recreate(srcSurf->w, srcSurf->h); + + // Convert the decoded surface to the correct pixel format, and then copy it over + surface.lock(); + Graphics::Surface *convertedSurface = srcSurf->convertTo(surface._rawSurface->format); + + Common::copy((byte *)convertedSurface->getPixels(), (byte *)convertedSurface->getPixels() + + surface.getPitch() * surface.getHeight(), (byte *)surface._rawSurface->getPixels()); + + convertedSurface->free(); + delete convertedSurface; + surface.unlock(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/image_decoders.h b/engines/titanic/support/image_decoders.h new file mode 100644 index 0000000000..b824b786a7 --- /dev/null +++ b/engines/titanic/support/image_decoders.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_IMAGE_DECODERS_H +#define TITANIC_IMAGE_DECODERS_H + +#include "image/jpeg.h" +#include "image/tga.h" +#include "titanic/support/string.h" +#include "titanic/support/simple_file.h" +#include "titanic/support/video_surface.h" + +namespace Titanic { + +class CJPEGDecode : public Image::JPEGDecoder { +public: + /** + * Decode the image file onto the passed surface + */ + void decode(OSVideoSurface &surface, const CString &name); +}; + +class CTargaDecode : public Image::TGADecoder { +public: + /** + * Decode the image file onto the passed surface + */ + void decode(OSVideoSurface &surface, const CString &name); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_IMAGE_DECODERS_H */ diff --git a/engines/titanic/support/mouse_cursor.cpp b/engines/titanic/support/mouse_cursor.cpp new file mode 100644 index 0000000000..068267cb18 --- /dev/null +++ b/engines/titanic/support/mouse_cursor.cpp @@ -0,0 +1,135 @@ +/* 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/memstream.h" +#include "common/textconsole.h" +#include "graphics/cursorman.h" +#include "titanic/support/mouse_cursor.h" +#include "titanic/support/movie.h" +#include "titanic/support/screen_manager.h" +#include "titanic/support/video_surface.h" +#include "titanic/core/resource_key.h" +#include "titanic/titanic.h" + +namespace Titanic { + +static const int CURSOR_DATA[NUM_CURSORS][4] = { + { 1, 136, 19, 18 }, + { 2, 139, 1, 1 }, + { 3, 140, 32, 1 }, + { 4, 137, 13, 0 }, + { 5, 145, 13, 0 }, + { 6, 144, 13, 22 }, + { 7, 137, 14, 0 }, + { 8, 148, 22, 40 }, + { 9, 136, 19, 18 }, + { 10, 143, 11, 11 }, + { 11, 146, 11, 11 }, + { 12, 136, 19, 18 }, + { 13, 136, 19, 25 }, + { 14, 136, 13, 22 }, + { 15, 138, 20, 28 } +}; + +CMouseCursor::CursorEntry::~CursorEntry() { + delete _videoSurface; + delete _frameSurface; +} + +CMouseCursor::CMouseCursor(CScreenManager *screenManager) : + _screenManager(screenManager), _cursorId(CURSOR_HOURGLASS), + _setCursorCount(0), _fieldE4(0), _fieldE8(0) { + loadCursorImages(); + setCursor(CURSOR_ARROW); +} + +CMouseCursor::~CMouseCursor() { +} + +void CMouseCursor::loadCursorImages() { + const CResourceKey key("ycursors.avi"); + g_vm->_filesManager->fn4(key.getString()); + + // Iterate through getting each cursor + for (int idx = 0; idx < NUM_CURSORS; ++idx) { + assert(CURSOR_DATA[idx][0] == (idx + 1)); + _cursors[idx]._centroid = Common::Point(CURSOR_DATA[idx][2], + CURSOR_DATA[idx][3]); + + // Create the surface + CVideoSurface *surface = _screenManager->createSurface(64, 64); + _cursors[idx]._videoSurface = surface; + + // Open the cursors video and move to the given frame + OSMovie movie(key, surface); + movie.setFrame(idx); + + Graphics::ManagedSurface *frameSurface = movie.duplicateFrame(); + _cursors[idx]._frameSurface = frameSurface; + surface->setMovieFrameSurface(frameSurface); + } +} + +void CMouseCursor::show() { + CursorMan.showMouse(true); +} + +void CMouseCursor::hide() { + CursorMan.showMouse(false); +} + +void CMouseCursor::setCursor(CursorId cursorId) { + ++_setCursorCount; + + if (cursorId != _cursorId) { + CursorEntry &ce = _cursors[cursorId - 1]; + CVideoSurface &surface = *ce._videoSurface; + surface.lock(); + + CursorMan.replaceCursor(surface.getPixels(), surface.getWidth(), surface.getHeight(), + ce._centroid.x, ce._centroid.y, 0, false, &g_vm->_screen->format); + surface.unlock(); + + _cursorId = cursorId; + } +} + +void CMouseCursor::update() { + // No implementation needed +} + +void CMouseCursor::lockE4() { + _fieldE4 = 0; + CScreenManager::_screenManagerPtr->_inputHandler->incLockCount(); +} + +void CMouseCursor::unlockE4() { + _fieldE4 = 1; + _fieldE8 = 0; + CScreenManager::_screenManagerPtr->_inputHandler->decLockCount(); +} + +void CMouseCursor::saveState(int v1, int v2, int v3) { + // TODO +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/mouse_cursor.h b/engines/titanic/support/mouse_cursor.h new file mode 100644 index 0000000000..7a81ad43fa --- /dev/null +++ b/engines/titanic/support/mouse_cursor.h @@ -0,0 +1,114 @@ +/* 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_MOUSE_CURSOR_H +#define TITANIC_MOUSE_CURSOR_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "graphics/managed_surface.h" + +namespace Titanic { + +#define NUM_CURSORS 15 + +enum CursorId { + CURSOR_ARROW = 1, + CURSOR_MOVE_LEFT = 2, + CURSOR_MOVE_RIGHT = 3, + CURSOR_MOVE_FORWARD = 4, + CURSOR_MOVE_UP = 5, + CURSOR_MOVE_DOWN1 = 6, + CURSOR_MOVE_FORWARD2 = 7, + CURSOR_HAND = 8, + CURSOR_ACTIVATE = 9, + CURSOR_INVALID = 10, + CURSOR_MAGNIFIER = 11, + CURSOR_IGNORE = 12, + CURSOR_BACKWARDS = 13, + CURSOR_DOWN = 14, + CURSOR_HOURGLASS = 15 +}; + +class CScreenManager; +class CVideoSurface; + +class CMouseCursor { + struct CursorEntry { + CVideoSurface *_videoSurface; + Graphics::ManagedSurface *_frameSurface; + Common::Point _centroid; + + CursorEntry() : _videoSurface(nullptr), _frameSurface(nullptr) {} + ~CursorEntry(); + }; +private: + CScreenManager *_screenManager; + CursorId _cursorId; + CursorEntry _cursors[NUM_CURSORS]; + uint _setCursorCount; + int _fieldE4; + int _fieldE8; + + /** + * Load the images for each cursor + */ + void loadCursorImages(); +public: + CMouseCursor(CScreenManager *screenManager); + ~CMouseCursor(); + + /** + * Make the mouse cursor visible + */ + void show(); + + /** + * Hide the mouse cursor + */ + void hide(); + + /** + * Set the cursor + */ + void setCursor(CursorId cursorId); + + /** + * Updates the mouse cursor + */ + void update(); + + /** + * Returns the number of times the cursor has been set + */ + uint getChangeCount() const { return _setCursorCount; } + + void lockE4(); + void unlockE4(); + + void saveState(int v1, int v2, int v3); +}; + + +} // End of namespace Titanic + +#endif /* TITANIC_MOUSE_CURSOR_H */ diff --git a/engines/titanic/support/movie.cpp b/engines/titanic/support/movie.cpp new file mode 100644 index 0000000000..50a55c8218 --- /dev/null +++ b/engines/titanic/support/movie.cpp @@ -0,0 +1,218 @@ +/* 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/support/movie.h" +#include "titanic/support/avi_surface.h" +#include "titanic/sound/sound_manager.h" +#include "titanic/messages/messages.h" +#include "titanic/titanic.h" + +namespace Titanic { + +#define CLIP_WIDTH 600 +#define CLIP_WIDTH_REDUCED (CLIP_WIDTH / 2) +#define CLIP_HEIGHT 340 +#define CLIP_HEIGHT_REDUCED (CLIP_HEIGHT / 2) + +CMovieList *CMovie::_playingMovies; +CVideoSurface *CMovie::_movieSurface; + +CMovie::CMovie() : ListItem(), _handled(false), _hasVideoFrame(false), + _hasAudioTiming(false) { +} + +CMovie::~CMovie() { + removeFromPlayingMovies(); +} + +void CMovie::init() { + _playingMovies = new CMovieList(); + _movieSurface = nullptr; +} + +void CMovie::deinit() { + // Delete each movie in turn + for (CMovieList::iterator i = _playingMovies->begin(); i != _playingMovies->end(); ) { + // We need to increment iterator before deleting movie, + // since the CMovie destructor calls removeFromPlayingMovies + CMovie *movie = *i; + ++i; + delete movie; + } + + delete _playingMovies; + delete _movieSurface; +} + +void CMovie::addToPlayingMovies() { + if (!isActive()) + _playingMovies->push_back(this); +} + +void CMovie::removeFromPlayingMovies() { + _playingMovies->remove(this); +} + +bool CMovie::isActive() const { + return _playingMovies->contains(this); +} + +bool CMovie::hasVideoFrame() { + if (_hasVideoFrame) { + _hasVideoFrame = 0; + return true; + } else { + return false; + } +} + +/*------------------------------------------------------------------------*/ + +OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) : + _aviSurface(name), _videoSurface(surface) { + _field18 = 0; + _field24 = 0; + _field28 = 0; + _field2C = 0; + + surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight()); + _aviSurface.setVideoSurface(surface); +} + +OSMovie::~OSMovie() { +} + +void OSMovie::play(uint flags, CGameObject *obj) { + _aviSurface.play(flags, obj); + + if (_aviSurface.isPlaying()) + movieStarted(); +} + +void OSMovie::play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) { + _aviSurface.play(startFrame, endFrame, flags, obj); + + if (_aviSurface.isPlaying()) + movieStarted(); +} + +void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) { + _aviSurface.play(startFrame, endFrame, initialFrame, flags, obj); + + if (_aviSurface.isPlaying()) + movieStarted(); +} + +void OSMovie::playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) { + if (!_movieSurface) + _movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340); + + bool widthLess = _videoSurface->getWidth() < 600; + bool heightLess = _videoSurface->getHeight() < 340; + Rect r(drawRect.left, drawRect.top, + drawRect.left + (widthLess ? CLIP_WIDTH_REDUCED : CLIP_WIDTH), + drawRect.top + (heightLess ? CLIP_HEIGHT_REDUCED : CLIP_HEIGHT) + ); + + uint timePerFrame = (uint)(1000.0 / _aviSurface._frameRate); + + for (; startFrame < endFrame; ++startFrame) { + // Set the frame + _aviSurface.setFrame(startFrame); + + // TODO: See if we need to do anything further here. The original had a bunch + // of calls and using of the _movieSurface; perhaps to allow scaling down + // videos to half-size + if (widthLess || heightLess) + warning("Not properly reducing clip size: %d %d", r.width(), r.height()); + + // Wait for the next frame, unless the user interrupts the clip + if (g_vm->_events->waitForPress(timePerFrame)) + break; + } +} + +void OSMovie::stop() { + _aviSurface.stop(); + removeFromPlayingMovies(); +} + +void OSMovie::addEvent(int frameNumber, CGameObject *obj) { + if (_aviSurface.addEvent(frameNumber, obj)) { + CMovieFrameMsg frameMsg(frameNumber, 0); + frameMsg.execute(obj); + } +} + +void OSMovie::setFrame(uint frameNumber) { + _aviSurface.setFrame(frameNumber); + _videoSurface->setMovieFrameSurface(_aviSurface.getSecondarySurface()); +} + +bool OSMovie::handleEvents(CMovieEventList &events) { + if (!_aviSurface.isPlaying()) + return false; + if (!_aviSurface.isNextFrame()) + return _aviSurface.isPlaying(); + + // Handle updating the frame + while (_aviSurface.isPlaying() && _aviSurface.isNextFrame()) { + _aviSurface.handleEvents(events); + _videoSurface->setMovieFrameSurface(_aviSurface.getSecondarySurface()); + } + + // Flag there's a video frame + _hasVideoFrame = true; + + return _aviSurface.isPlaying(); +} + +const CMovieRangeInfoList *OSMovie::getMovieRangeInfo() const { + return _aviSurface.getMovieRangeInfo(); +} + +void OSMovie::setSoundManager(CSoundManager *soundManager) { + _aviSurface._soundManager = soundManager; +} + +int OSMovie::getFrame() const { + return _aviSurface.getFrame(); +} + +void OSMovie::movieStarted() { + //if (_aviSurface._hasAudio) + // _aviSurface._soundManager->movieStarted(); + + // Register the movie in the playing list + addToPlayingMovies(); + _hasVideoFrame = true; +} + +void OSMovie::setFrameRate(double rate) { + _aviSurface.setFrameRate(rate); +} + +Graphics::ManagedSurface *OSMovie::duplicateFrame() const { + return _aviSurface.duplicateSecondaryFrame(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/movie.h b/engines/titanic/support/movie.h new file mode 100644 index 0000000000..8c89f9e6dd --- /dev/null +++ b/engines/titanic/support/movie.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_MOVIE_H +#define TITANIC_MOVIE_H + +#include "common/list.h" +#include "video/video_decoder.h" +#include "titanic/core/list.h" +#include "titanic/core/resource_key.h" +#include "titanic/support/avi_surface.h" +#include "titanic/support/movie_range_info.h" + +namespace Titanic { + +class CGameObject; +class CMovie; +class CSoundManager; +class CVideoSurface; + +class CMovieList : public List<CMovie> { +public: +}; + +class CMovie : public ListItem { +protected: + /** + * Adds the movie to the list of currently playing movies + */ + void addToPlayingMovies(); +public: + bool _handled; + bool _hasVideoFrame; + bool _hasAudioTiming; +public: + static CMovieList *_playingMovies; + static CVideoSurface *_movieSurface; + + /** + * Initializes statics + */ + static void init(); + + /** + * Deinitializes statics + */ + static void deinit(); +public: + CMovie(); + virtual ~CMovie(); + + /** + * Starts playing the movie + */ + virtual void play(uint flags, CGameObject *obj) = 0; + + /** + * Starts playing the movie + */ + virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0; + + /** + * Starts playing the movie + */ + virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0; + + /** + * Plays a sub-section of a movie, and doesn't return until either + * the playback ends or a key has been pressed + */ + virtual void playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) = 0; + + /** + * Stops the movie + */ + virtual void stop() = 0; + + /** + * Add a playback event + */ + virtual void addEvent(int frameNumber, CGameObject *obj) = 0; + + /** + * Set the current frame number + */ + virtual void setFrame(uint frameNumber) = 0; + + /** + * Handle any pending movie events + */ + virtual bool handleEvents(CMovieEventList &events) = 0; + + /** + * Return any movie range info associated with the movie + */ + virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0; + + /** + * Set the sound manager reference + */ + virtual void setSoundManager(CSoundManager *soundManager) = 0; + + /** + * Get the current movie frame + */ + virtual int getFrame() const = 0; + + /** + * Set the frame rate for the movie + */ + virtual void setFrameRate(double rate) = 0; + + /** + * Creates a duplicate of the movie's frame + */ + virtual Graphics::ManagedSurface *duplicateFrame() const = 0; + + /** + * Removes the movie from the list of currently playing movies + */ + void removeFromPlayingMovies(); + + /** + * Returns true if the movie is currently active + */ + bool isActive() const; + + /** + * Returns true if there's a video frame + */ + bool hasVideoFrame(); +}; + +class OSMovie : public CMovie { +private: + AVISurface _aviSurface; + CVideoSurface *_videoSurface; + int _field18; + int _field24; + int _field28; + int _field2C; +private: + /** + * Called when a movie is started playing + */ + void movieStarted(); +public: + OSMovie(const CResourceKey &name, CVideoSurface *surface); + virtual ~OSMovie(); + + /** + * Starts playing the movie + */ + virtual void play(uint flags, CGameObject *obj); + + /** + * Starts playing the movie + */ + virtual void play(uint startFrame, uint endFrame, uint flags, CGameObject *obj); + + /** + * Starts playing the movie + */ + virtual void play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj); + + /** + * Plays a sub-section of a movie, and doesn't return until either + * the playback ends or a key has been pressed + */ + virtual void playCutscene(const Rect &drawRect, uint startFrame, uint endFrame); + + /** + * Stops the movie + */ + virtual void stop(); + + /** + * Add a playback event + */ + virtual void addEvent(int eventId, CGameObject *obj); + + /** + * Set the current frame number + */ + virtual void setFrame(uint frameNumber); + + /** + * Handle any pending movie events + */ + virtual bool handleEvents(CMovieEventList &events); + + /** + * Get the current frame number + */ + virtual int getFrame() const; + + /** + * Return any movie range info associated with the movie + */ + virtual const CMovieRangeInfoList *getMovieRangeInfo() const; + + /** + * Set the sound manager reference + */ + virtual void setSoundManager(CSoundManager *soundManager); + + /** + * Set the frame rate for the movie + */ + virtual void setFrameRate(double rate); + + /** + * Creates a duplicate of the frame info + */ + virtual Graphics::ManagedSurface *duplicateFrame() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MOVIE_H */ diff --git a/engines/titanic/support/movie_clip.cpp b/engines/titanic/support/movie_clip.cpp new file mode 100644 index 0000000000..1f2ef66428 --- /dev/null +++ b/engines/titanic/support/movie_clip.cpp @@ -0,0 +1,100 @@ +/* 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/support/movie_clip.h" +#include "titanic/core/game_object.h" + +namespace Titanic { + +CMovieClip::CMovieClip(): ListItem(), _startFrame(0), _endFrame(0) { +} + +CMovieClip::CMovieClip(const CString &name, int startFrame, int endFrame): + ListItem(), _name(name), _startFrame(startFrame), _endFrame(endFrame) { +} + +void CMovieClip::save(SimpleFile *file, int indent) { + file->writeNumberLine(2, indent); + file->writeQuotedLine("Clip", indent); + file->writeQuotedLine(_name, indent); + file->writeNumberLine(_startFrame, indent); + file->writeNumberLine(_endFrame, indent); + + ListItem::save(file, indent); +} + +void CMovieClip::load(SimpleFile *file) { + int val = file->readNumber(); + + switch (val) { + case 1: + // This should never be used + assert(0); + break; + + case 2: + file->readString(); + _name = file->readString(); + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + break; + + default: + break; + } + + ListItem::load(file); +} + +/*------------------------------------------------------------------------*/ + +CMovieClip *CMovieClipList::findByName(const Common::String &name) const { + for (const_iterator i = begin(); i != end(); ++i) { + CMovieClip *clip = *i; + if (clip->_name == name) + return clip; + } + + return nullptr; +} + +bool CMovieClipList::existsByStart(const CString &name, int startFrame) const { + for (const_iterator i = begin(); i != end(); ++i) { + CMovieClip *clip = *i; + if (clip->_startFrame == startFrame && clip->_name == name) + return true; + } + + return false; +} + +bool CMovieClipList::existsByEnd(const CString &name, int endFrame) const { + for (const_iterator i = begin(); i != end(); ++i) { + CMovieClip *clip = *i; + if (clip->_endFrame == endFrame && clip->_name == name) + return true; + } + + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/movie_clip.h b/engines/titanic/support/movie_clip.h new file mode 100644 index 0000000000..513ed4a339 --- /dev/null +++ b/engines/titanic/support/movie_clip.h @@ -0,0 +1,92 @@ +/* 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_MOVIE_CLIP_H +#define TITANIC_MOVIE_CLIP_H + +#include "titanic/core/list.h" + +namespace Titanic { + +enum ClipFlag { + CLIPFLAG_HAS_END_FRAME = 1, + CLIPFLAG_4 = 4, + CLIPFLAG_HAS_START_FRAME = 8, + CLIPFLAG_PLAY = 0x10 +}; + +class CGameObject; + +/** + * Movie clip + */ +class CMovieClip : public ListItem { +private: + Common::List<void *> _items; + CString _string2; + CString _string3; +public: + CString _name; + int _startFrame; + int _endFrame; +public: + CLASSDEF; + CMovieClip(); + CMovieClip(const CString &name, int startFrame, int endFrame); + + /** + * 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); +}; + +/** + * Movie clip list + */ +class CMovieClipList: public List<CMovieClip> { +public: + /** + * Finds and returns a movie clip in the list by name + */ + CMovieClip *findByName(const Common::String &name) const; + + /** + * Returns true if a clip exists in the list with a given name + * and starting frame number + */ + bool existsByStart(const CString &name, int startFrame = 0) const; + + /** + * Returns true if a clip exists in the list with a given name + * and starting frame number + */ + bool existsByEnd(const CString &name, int endFrame = 0) const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MOVIE_CLIP_H */ diff --git a/engines/titanic/support/movie_event.cpp b/engines/titanic/support/movie_event.cpp new file mode 100644 index 0000000000..5f8a6da019 --- /dev/null +++ b/engines/titanic/support/movie_event.cpp @@ -0,0 +1,64 @@ +/* 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/support/movie_event.h" +#include "titanic/core/game_object.h" + +namespace Titanic { + +CMovieEvent::CMovieEvent() : ListItem(), _type(MET_PLAY), _startFrame(0), + _endFrame(0), _initialFrame(0), _gameObject(nullptr) { +} + +CMovieEvent::CMovieEvent(const CMovieEvent *src) { + _type = src->_type; + _startFrame = src->_startFrame; + _endFrame = src->_endFrame; + _initialFrame = src->_initialFrame; + _gameObject = src->_gameObject; +} + +void CMovieEvent::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + file->writeNumberLine(_startFrame, indent + 1); + file->writeNumberLine(_endFrame, indent + 1); + error("FIXME: Original save/loaded object pointer"); + // file->writeNumberLine(_gameObject, indent + 1); + file->writeNumberLine(_initialFrame, indent + 1); + + ListItem::save(file, indent); +} + +void CMovieEvent::load(SimpleFile *file) { + int val = file->readNumber(); + if (!val) { + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + file->readNumber(); + error("FIXME: Original save/loaded object pointer"); + _initialFrame = file->readNumber(); + } + + ListItem::load(file); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/movie_event.h b/engines/titanic/support/movie_event.h new file mode 100644 index 0000000000..af93c76a31 --- /dev/null +++ b/engines/titanic/support/movie_event.h @@ -0,0 +1,66 @@ +/* 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_MOVIE_EVENT_H +#define TITANIC_MOVIE_EVENT_H + +#include "titanic/core/list.h" + +namespace Titanic { + +enum MovieEventType { MET_PLAY = 0, MET_MOVIE_END = 1, MET_FRAME = 2 }; + +class CGameObject; + +class CMovieEvent : public ListItem { +public: + MovieEventType _type; + int _startFrame; + int _endFrame; + CGameObject *_gameObject; + int _initialFrame; +public: + CMovieEvent(); + CMovieEvent(const CMovieEvent *src); + virtual ~CMovieEvent() {} + + /** + * 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); +}; + +class CMovieEventList : public List<CMovieEvent> { +}; + +class CSharedMovieEventList : public Common::List<CMovieEvent> { +}; + + +} // End of namespace Titanic + +#endif /* TITANIC_MOVIE_EVENT_H */ diff --git a/engines/titanic/support/movie_manager.cpp b/engines/titanic/support/movie_manager.cpp new file mode 100644 index 0000000000..bfeb081b5c --- /dev/null +++ b/engines/titanic/support/movie_manager.cpp @@ -0,0 +1,35 @@ +/* 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/support/movie_manager.h" +#include "titanic/support/movie.h" +#include "titanic/support/video_surface.h" + +namespace Titanic { + +CMovie *CMovieManager::createMovie(const CResourceKey &key, CVideoSurface *surface) { + CMovie *movie = new OSMovie(key, surface); + movie->setSoundManager(_soundManager); + return movie; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/movie_manager.h b/engines/titanic/support/movie_manager.h new file mode 100644 index 0000000000..2920d909b7 --- /dev/null +++ b/engines/titanic/support/movie_manager.h @@ -0,0 +1,65 @@ +/* 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_MOVIE_MANAGER_H +#define TITANIC_MOVIE_MANAGER_H + +#include "titanic/core/list.h" +#include "titanic/core/resource_key.h" +#include "titanic/sound/sound_manager.h" + +namespace Titanic { + +class CMovie; +class CVideoSurface; + +class CMovieManagerBase { +public: + virtual ~CMovieManagerBase() {} + + /** + * Create a new movie and return it + */ + virtual CMovie *createMovie(const CResourceKey &key, CVideoSurface *surface) = 0; +}; + +class CMovieManager : public CMovieManagerBase { +private: + CSoundManager *_soundManager; +public: + CMovieManager() : CMovieManagerBase(), _soundManager(nullptr) {} + virtual ~CMovieManager() {} + + /** + * Create a new movie and return it + */ + virtual CMovie *createMovie(const CResourceKey &key, CVideoSurface *surface); + + /** + * Sets the sound manager that will be attached to all created movies + */ + void setSoundManager(CSoundManager *soundManager) { _soundManager = soundManager; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MOVIE_MANAGER_H */ diff --git a/engines/titanic/support/movie_range_info.cpp b/engines/titanic/support/movie_range_info.cpp new file mode 100644 index 0000000000..d4d9fc0e2a --- /dev/null +++ b/engines/titanic/support/movie_range_info.cpp @@ -0,0 +1,112 @@ +/* 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/support/movie_range_info.h" +#include "titanic/support/movie_clip.h" +#include "titanic/core/game_object.h" + +namespace Titanic { + +CMovieRangeInfo::CMovieRangeInfo() : ListItem(), _startFrame(0), _endFrame(0) { +} + +CMovieRangeInfo::~CMovieRangeInfo() { + _events.destroyContents(); +} + +CMovieRangeInfo::CMovieRangeInfo(const CMovieRangeInfo *src) : ListItem() { + _startFrame = src->_startFrame; + _endFrame = src->_endFrame; + _initialFrame = src->_initialFrame; + _isReversed = src->_isReversed; + _isRepeat = src->_isRepeat; + + // Duplicate the events list + for (CMovieEventList::const_iterator i = _events.begin(); + i != _events.end(); ++i) { + _events.push_back(new CMovieEvent(*i)); + } +} + +void CMovieRangeInfo::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + file->writeNumberLine(_startFrame, indent + 1); + file->writeNumberLine(_endFrame, indent + 1); + file->writeNumberLine(_initialFrame, indent + 1); + file->writeNumberLine(_isRepeat, indent + 1); + file->writeNumberLine(_isReversed, indent + 1); + _events.save(file, indent + 1); +} + +void CMovieRangeInfo::load(SimpleFile *file) { + int val = file->readNumber(); + if (!val) { + _startFrame = file->readNumber(); + _endFrame = file->readNumber(); + _initialFrame = file->readNumber(); + _isRepeat = file->readNumber(); + _isReversed = file->readNumber(); + _events.load(file); + } +} + +void CMovieRangeInfo::getMovieEnd(CMovieEventList &list) { + for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { + CMovieEvent *movieEvent = *i; + if (movieEvent->_type == MET_MOVIE_END) + list.push_back(new CMovieEvent(movieEvent)); + } +} + +void CMovieRangeInfo::getMovieFrame(CMovieEventList &list, int frameNumber) { + for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { + CMovieEvent *movieEvent = *i; + if (movieEvent->_type == MET_FRAME && movieEvent->_initialFrame == frameNumber) + list.push_back(new CMovieEvent(movieEvent)); + } +} + +void CMovieRangeInfo::process(CGameObject *owner) { + int flags = 0; + if (_endFrame) + flags |= MOVIE_REPEAT; + if (_startFrame) + flags |= MOVIE_REVERSE; + + for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { + CMovieEvent *movieEvent = *i; + if (movieEvent->_type == MET_MOVIE_END) { + flags |= CLIPFLAG_PLAY; + break; + } + } + + owner->playMovie(_startFrame, _endFrame, _initialFrame, flags); + + for (CMovieEventList::iterator i = _events.begin(); i != _events.end(); ++i) { + CMovieEvent *movieEvent = *i; + if (movieEvent->_type == MET_PLAY) + owner->movieEvent(movieEvent->_initialFrame); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/movie_range_info.h b/engines/titanic/support/movie_range_info.h new file mode 100644 index 0000000000..6b13fbadb5 --- /dev/null +++ b/engines/titanic/support/movie_range_info.h @@ -0,0 +1,81 @@ +/* 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_MOVIE_RANGE_INFO_H +#define TITANIC_MOVIE_RANGE_INFO_H + +#include "video/video_decoder.h" +#include "titanic/core/list.h" +#include "titanic/core/resource_key.h" +#include "titanic/support/movie_event.h" + +namespace Titanic { + +class CGameObject; + +class CMovieRangeInfo : public ListItem { +public: + int _startFrame; + int _endFrame; + int _initialFrame; + bool _isReversed; + bool _isRepeat; + CMovieEventList _events; +public: + CMovieRangeInfo(); + CMovieRangeInfo(const CMovieRangeInfo *src); + virtual ~CMovieRangeInfo(); + + /** + * 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); + + /** + * Adds an event to the events list + */ + void addEvent(CMovieEvent *movieEvent) { _events.push_back(movieEvent); } + + /** + * Get any movie end events for the range + */ + void getMovieEnd(CMovieEventList &list); + + /** + * Get any movie frame events for a specified frame number + */ + void getMovieFrame(CMovieEventList &list, int frameNumber); + + void process(CGameObject *owner); +}; + +class CMovieRangeInfoList : public List<CMovieRangeInfo> { +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MOVIE_RANGE_INFO_H */ diff --git a/engines/titanic/support/rect.cpp b/engines/titanic/support/rect.cpp new file mode 100644 index 0000000000..5fce4402cb --- /dev/null +++ b/engines/titanic/support/rect.cpp @@ -0,0 +1,44 @@ +/* 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/support/rect.h" + +namespace Titanic { + +void Rect::combine(const Rect &r) { + if (isEmpty() || r.isEmpty()) + return; + + Common::Rect::extend(r); +} + +void Rect::constrain(const Rect &r) { + if (!isEmpty()) { + if (r.isEmpty()) { + clear(); + } else { + Common::Rect::clip(r); + } + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/rect.h b/engines/titanic/support/rect.h new file mode 100644 index 0000000000..1661711870 --- /dev/null +++ b/engines/titanic/support/rect.h @@ -0,0 +1,61 @@ +/* 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_RECT_H +#define TITANIC_RECT_H + +#include "common/rect.h" + +namespace Titanic { + +typedef Common::Point Point; + +class Rect : public Common::Rect { +public: + Rect() : Common::Rect() {} + Rect(int16 w, int16 h) : Common::Rect(w, h) {} + Rect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1, y1, x2, y2) {} + + /** + * Returns the top/left corner of the rect as a point + */ + operator const Point() { return Point(left, top); } + + /** + * Clear the rect + */ + void clear() { left = top = right = bottom = 0; } + + /** + * Combine another rect into this one + */ + void combine(const Rect &r); + + /** + * Constrains/clips to the intersection area of the given rect + */ + void constrain(const Rect &r); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_RECT_H */ diff --git a/engines/titanic/support/screen_manager.cpp b/engines/titanic/support/screen_manager.cpp new file mode 100644 index 0000000000..b0d852104c --- /dev/null +++ b/engines/titanic/support/screen_manager.cpp @@ -0,0 +1,325 @@ +/* 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/support/screen_manager.h" +#include "titanic/support/video_surface.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CScreenManager *CScreenManager::_screenManagerPtr; +CScreenManager *CScreenManager::_currentScreenManagerPtr; + +CScreenManager::CScreenManager(TitanicEngine *vm): _vm(vm) { + _screenManagerPtr = nullptr; + _currentScreenManagerPtr = nullptr; + + _frontRenderSurface = nullptr; + _mouseCursor = nullptr; + _textCursor = nullptr; + _inputHandler = nullptr; + _fontNumber = 0; + + _screenManagerPtr = this; +} + +CScreenManager::~CScreenManager() { + _screenManagerPtr = nullptr; +} + +void CScreenManager::setWindowHandle(int v) { + // Not needed +} + +bool CScreenManager::resetWindowHandle(int v) { + hideCursor(); + return true; +} + +CScreenManager *CScreenManager::setCurrent() { + if (!_currentScreenManagerPtr) + _currentScreenManagerPtr = _screenManagerPtr; + + return _currentScreenManagerPtr; +} + +void CScreenManager::setSurfaceBounds(SurfaceNum surfaceNum, const Rect &r) { + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + _backSurfaces[surfaceNum]._bounds = r; +} + +int CScreenManager::setFontNumber(int fontNumber) { + int oldFontNumber = _fontNumber; + _fontNumber = fontNumber; + return oldFontNumber; +} + +/*------------------------------------------------------------------------*/ + +OSScreenManager::OSScreenManager(TitanicEngine *vm): CScreenManager(vm), + _directDrawManager(vm, false) { + _field48 = 0; + _field4C = 0; + _field50 = 0; + _field54 = 0; +} + +OSScreenManager::~OSScreenManager() { + destroyFrontAndBackBuffers(); + delete _mouseCursor; + delete _textCursor; +} + +void OSScreenManager::setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2) { + assert(bpp == 16); + destroyFrontAndBackBuffers(); + _directDrawManager.initVideo(width, height, bpp, numBackSurfaces); + + _vm->_screen->create(width, height, g_system->getScreenFormat()); + _frontRenderSurface = new OSVideoSurface(this, nullptr); + _frontRenderSurface->setSurface(this, _directDrawManager._mainSurface); + + _backSurfaces.resize(numBackSurfaces); + for (uint idx = 0; idx < numBackSurfaces; ++idx) { + _backSurfaces[idx]._surface = new OSVideoSurface(this, nullptr); + _backSurfaces[idx]._surface->setSurface(this, _directDrawManager._backSurfaces[idx]); + } + + // Load fonts + _fonts[0].load(149); + _fonts[1].load(151); + _fonts[2].load(152); + _fonts[3].load(153); + + // Load the cursors + loadCursors(); +} + +void OSScreenManager::drawCursors() { + // The original did both text and mouse cursor drawing here. + // For ScummVM, we only need to worry about the text cursor + _textCursor->draw(); +} + +DirectDrawSurface *OSScreenManager::getDDSurface(SurfaceNum surfaceNum) { + if (surfaceNum == SURFACE_PRIMARY) + return _directDrawManager._mainSurface; + else if (surfaceNum < (int)_backSurfaces.size()) + return _directDrawManager._backSurfaces[surfaceNum]; + else + return nullptr; +} + +CVideoSurface *OSScreenManager::lockSurface(SurfaceNum surfaceNum) { + CVideoSurface *surface = getSurface(surfaceNum); + surface->lock(); + return surface; +} + +void OSScreenManager::unlockSurface(CVideoSurface *surface) { + surface->unlock(); +} + +CVideoSurface *OSScreenManager::getSurface(SurfaceNum surfaceNum) const { + if (surfaceNum == SURFACE_PRIMARY) + return _frontRenderSurface; + else if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + return _backSurfaces[surfaceNum]._surface; + else + return nullptr; +} + +void OSScreenManager::fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b) { + DirectDrawSurface *surface = getDDSurface(surfaceNum); + if (!surface) + return; + + // If bounds are provided, clip and use them. Otherwise, use entire surface area + Rect surfaceRect(0, 0, surface->getWidth(), surface->getHeight()); + Rect tempRect; + + if (rect) { + tempRect = *rect; + tempRect.clip(surfaceRect); + } else { + tempRect = surfaceRect; + } + + if (tempRect.isValidRect()) + surface->fillRect(&tempRect, r, g, b); +} + +void OSScreenManager::blitFrom(SurfaceNum surfaceNum, CVideoSurface *src, + const Point *destPos, const Rect *srcRect) { + // Get the dest surface + CVideoSurface *destSurface = _frontRenderSurface; + if (surfaceNum < -1) + return; + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + destSurface = _backSurfaces[surfaceNum]._surface; + if (!destSurface->hasSurface()) + return; + + Point destPoint = destPos ? *destPos : Point(0, 0); + Rect srcBounds = srcRect ? *srcRect : Rect(0, 0, src->getWidth(), src->getHeight()); + Rect *bounds = &srcBounds; + Rect rect2; + + if (surfaceNum >= 0 && !_backSurfaces[surfaceNum]._bounds.isEmpty()) { + // Perform clipping to the bounds of the back surface + rect2 = srcBounds; + rect2.translate(-srcBounds.left, -srcBounds.top); + rect2.translate(destPoint.x, destPoint.y); + rect2.constrain(_backSurfaces[surfaceNum]._bounds); + + rect2.translate(-destPoint.x, -destPoint.y); + rect2.translate(srcBounds.left, srcBounds.top); + + if (rect2.isEmpty()) + return; + + destPoint.x += rect2.left - srcBounds.left; + destPoint.y += rect2.top - srcBounds.top; + bounds = &rect2; + } + + if (!bounds->isEmpty()) + destSurface->blitFrom(destPoint, src, bounds); +} + +void OSScreenManager::blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v) { + // Get the dest surface + CVideoSurface *destSurface = _frontRenderSurface; + if (surfaceNum < -1) + return; + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + destSurface = _backSurfaces[surfaceNum]._surface; + if (!destSurface->hasSurface()) + return; + + if (!rect->isEmpty()) + destSurface->blitFrom(Point(rect->left, rect->top), src, rect); +} + +int OSScreenManager::writeString(int surfaceNum, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor) { + CVideoSurface *surface; + Rect bounds; + + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) { + surface = _backSurfaces[surfaceNum]._surface; + bounds = _backSurfaces[surfaceNum]._bounds; + } else if (surfaceNum == -1) { + surface = _frontRenderSurface; + bounds = Rect(0, 0, surface->getWidth(), surface->getHeight()); + } else { + return -1; + } + + return _fonts[_fontNumber].writeString(surface, destRect, bounds, + yOffset, str, textCursor); +} + +int OSScreenManager::writeString(int surfaceNum, const Rect &srcRect, + const Rect &destRect, const CString &str, CTextCursor *textCursor) { + // TODO + return 0; +} + +void OSScreenManager::setFontColor(byte r, byte g, byte b) { + _fonts[_fontNumber].setColor(r, g, b); +} + +int OSScreenManager::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const { + return _fonts[_fontNumber].getTextBounds(str, maxWidth, sizeOut); +} + +int OSScreenManager::getFontHeight() const { + return _fonts[_fontNumber]._fontHeight; +} + +int OSScreenManager::stringWidth(const CString &str) { + return _fonts[_fontNumber].stringWidth(str); +} + +void OSScreenManager::frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b) { + Rect top(rect.left, rect.top, rect.right, rect.top + 1); + fillRect(surfaceNum, &top, r, g, b); + Rect bottom(rect.left, rect.bottom - 1, rect.right, rect.bottom); + fillRect(surfaceNum, &bottom, r, g, b); + Rect left(rect.left, rect.top, rect.left + 1, rect.bottom); + fillRect(surfaceNum, &left, r, g, b); + Rect right(rect.right - 1, rect.top, rect.right, rect.bottom); +} + +void OSScreenManager::clearSurface(SurfaceNum surfaceNum, Rect *bounds) { + if (surfaceNum == SURFACE_PRIMARY) + _directDrawManager._mainSurface->fill(bounds, 0); + else if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + _directDrawManager._backSurfaces[surfaceNum]->fill(bounds, 0); +} + +void OSScreenManager::resizeSurface(CVideoSurface *surface, int width, int height) { + DirectDrawSurface *ddSurface = _directDrawManager.createSurface(width, height, 0); + surface->setSurface(this, ddSurface); +} + +CVideoSurface *OSScreenManager::createSurface(int w, int h) { + DirectDrawSurface *ddSurface = _directDrawManager.createSurface(w, h, 0); + return new OSVideoSurface(this, ddSurface); +} + +CVideoSurface *OSScreenManager::createSurface(const CResourceKey &key) { + return new OSVideoSurface(this, key); +} + +void OSScreenManager::showCursor() { + CScreenManager::_screenManagerPtr->_mouseCursor->show(); +} + +void OSScreenManager::hideCursor() { + CScreenManager::_screenManagerPtr->_mouseCursor->hide(); +} + +void OSScreenManager::destroyFrontAndBackBuffers() { + delete _frontRenderSurface; + _frontRenderSurface = nullptr; + + for (uint idx = 0; idx < _backSurfaces.size(); ++idx) + delete _backSurfaces[idx]._surface; + _backSurfaces.clear(); +} + +void OSScreenManager::loadCursors() { + if (_mouseCursor) { + hideCursor(); + delete _mouseCursor; + } + _mouseCursor = new CMouseCursor(this); + showCursor(); + + if (!_textCursor) { + _textCursor = new CTextCursor(this); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/screen_manager.h b/engines/titanic/support/screen_manager.h new file mode 100644 index 0000000000..0736f1393c --- /dev/null +++ b/engines/titanic/support/screen_manager.h @@ -0,0 +1,395 @@ +/* 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_SCREEN_MANAGER_H +#define TITANIC_SCREEN_MANAGER_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "titanic/support/direct_draw.h" +#include "titanic/support/font.h" +#include "titanic/input_handler.h" +#include "titanic/support/mouse_cursor.h" +#include "titanic/support/text_cursor.h" +#include "titanic/support/video_surface.h" +#include "titanic/core/resource_key.h" + +namespace Titanic { + +/** + * The original used page flipping with one primary and one back buffer. + * Since we don't need that in ScummVM, the back buffer number below is + * remapped to the primary surface + */ +enum SurfaceNum { + SURFACE_PRIMARY = -1, // Surface 0 + SURFACE_BACKBUFFER = -1 // Surface -1 +}; + +class TitanicEngine; + +class CScreenManager { + struct VideoSurfaceEntry { + CVideoSurface *_surface; + Rect _bounds; + }; +protected: + TitanicEngine *_vm; +public: + static CScreenManager *_screenManagerPtr; + static CScreenManager *_currentScreenManagerPtr; + + /** + * Set the current screen manager + */ + static CScreenManager *setCurrent(); +public: + Common::Array<VideoSurfaceEntry> _backSurfaces; + CVideoSurface *_frontRenderSurface; + CMouseCursor *_mouseCursor; + CTextCursor *_textCursor; + CInputHandler *_inputHandler; + int _fontNumber; +public: + CScreenManager(TitanicEngine *vm); + virtual ~CScreenManager(); + + void fn1() {} + void fn2() {} + + virtual void setWindowHandle(int v); + virtual bool resetWindowHandle(int v); + + /** + * Sets the video mode + */ + virtual void setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2) = 0; + + /** + * Handles drawing the cursors + */ + virtual void drawCursors() = 0; + + /** + * Locks a specified surface number for access and returns a pointer to it + */ + virtual CVideoSurface *lockSurface(SurfaceNum surfaceNum) = 0; + + /** + * Unlocks a previously locked surface + */ + virtual void unlockSurface(CVideoSurface *surface) = 0; + + /** + * Gets a specified surface number + */ + virtual CVideoSurface *getSurface(SurfaceNum surfaceNum) const = 0; + + /** + * Return the front render surface + */ + virtual CVideoSurface *getFrontRenderSurface() const = 0; + + /** + * Fill an area with a specific color + */ + virtual void fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b) = 0; + + /** + * Blits a surface onto one of the screen surfaces + */ + virtual void blitFrom(SurfaceNum surfaceNum, CVideoSurface *src, const Point *destPos = nullptr, + const Rect *srcRect = nullptr) = 0; + + /** + * Blits a surface onto one of the screen surfaces + */ + virtual void blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v = 0) = 0; + + /** + * Write a string + * @param surfaceNum Destination surface + * @param destRect Bounds within dest surface + * @param yOffset Y offset for drawing, to allow for parts of + * the text to be scrolled off-screen + * @param str Line or lines to write + * @param textCursor Optional text cursor pointer + */ + virtual int writeString(int surfaceNum, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor) = 0; + + /** + * Write a string + * @param surfaceNum Destination surface + * @param srcRect Drawing area + * @param destRect Bounds of dest surface + * @param str Line or lines to write + * @param textCursor Optional text cursor pointer + */ + virtual int writeString(int surfaceNum, const Rect &srcRect, + const Rect &destRect, const CString &str, CTextCursor *textCursor) = 0; + + /** + * Set the font color + */ + virtual void setFontColor(byte r, byte g, byte b) = 0; + + /** + * Get the text area a string will fit into + * @param str String + * @param maxWidth Maximum width in pixels + * @param sizeOut Optional pointer to output size + * @returns Required height + */ + virtual int getTextBounds(const CString &str, int maxWidth, Point *sizeOut = nullptr) const = 0; + + /** + * Get the current font height + */ + virtual int getFontHeight() const = 0; + + /** + * Returns the width of a given string in pixels + */ + virtual int stringWidth(const CString &str) = 0; + + /** + * Draws a frame enclosing the specified area + */ + virtual void frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b) = 0; + + /** + * Clear a portion of a specified surface + */ + virtual void clearSurface(SurfaceNum surfaceNum, Rect *_bounds) = 0; + + /** + * Resize the passed surface + */ + virtual void resizeSurface(CVideoSurface *surface, int width, int height) = 0; + + /** + * Creates a surface of a given size + */ + virtual CVideoSurface *createSurface(int w, int h) = 0; + + /** + * Creates a surface from a specified resource + */ + virtual CVideoSurface *createSurface(const CResourceKey &key) = 0; + + /** + * Get the top-left corner of the screen in global screen co-ordinates + * For ScummVM, this is always (0, 0), even in Windowed mode + */ + virtual Point getScreenTopLeft() { return Point(0, 0); } + + /** + * Waits for a vertical screen sync + * For ScummVM, this can be safely ignored + */ + virtual void waitForVSync() {} + + /** + * Show the mouse cursor + */ + virtual void showCursor() = 0; + + /** + * Hide the mouse cursor + */ + virtual void hideCursor() = 0; + + /** + * Set drawing bounds for a specified surface + */ + void setSurfaceBounds(SurfaceNum surfaceNum, const Rect &r); + + /** + * Set the current font number + */ + int setFontNumber(int fontNumber); +}; + +class OSScreenManager: CScreenManager { +private: + DirectDrawManager _directDrawManager; + + /** + * Frees any surface buffers + */ + void destroyFrontAndBackBuffers(); + + /** + * Load game cursors + */ + void loadCursors(); + + /** + * Gets an underlying surface + */ + DirectDrawSurface *getDDSurface(SurfaceNum surfaceNum); +public: + int _field48; + int _field4C; + int _field50; + int _field54; + STFont _fonts[4]; +public: + OSScreenManager(TitanicEngine *vm); + virtual ~OSScreenManager(); + + /** + * Sets the video mode + */ + virtual void setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2); + + /** + * Handles drawing the cursors + */ + virtual void drawCursors(); + + /** + * Locks a specified surface number for access and returns a pointer to it + */ + virtual CVideoSurface *lockSurface(SurfaceNum surfaceNum); + + /** + * Unlocks a previously locked surface + */ + virtual void unlockSurface(CVideoSurface *surface); + + /** + * Gets a specified surface number + */ + virtual CVideoSurface *getSurface(SurfaceNum surfaceNum) const; + + /** + * Return the front render surface + */ + virtual CVideoSurface *getFrontRenderSurface() const { + return _frontRenderSurface; + } + + + /** + * Fill an area with a specific color + */ + virtual void fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b); + + /** + * Blits a surface onto one of the screen surfaces + */ + virtual void blitFrom(SurfaceNum surfaceNum, CVideoSurface *src, const Point *destPos, + const Rect *srcRect = nullptr); + + /** + * Blits a surface onto one of the screen surfaces + */ + virtual void blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v = 0); + + /** + * Write a string + * @param surfaceNum Destination surface + * @param destRect Bounds within dest surface + * @param yOffset Y offset for drawing, to allow for parts of + * the text to be scrolled off-screen + * @param str Line or lines to write + * @param textCursor Optional text cursor pointer + */ + virtual int writeString(int surfaceNum, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor); + + /** + * Write a string + * @param surfaceNum Destination surface + * @param srcRect Drawing area + * @param destRect Bounds of dest surface + * @param str Line or lines to write + * @param textCursor Optional text cursor pointer + */ + virtual int writeString(int surfaceNum, const Rect &srcRect, + const Rect &destRect, const CString &str, CTextCursor *textCursor); + + /** + * Set the font color + */ + virtual void setFontColor(byte r, byte g, byte b); + + /** + * Get the text area a string will fit into + * @param str String + * @param maxWidth Maximum width in pixels + * @param sizeOut Optional pointer to output size + * @returns Required height + */ + virtual int getTextBounds(const CString &str, int maxWidth, Point *sizeOut = nullptr) const; + + /** + * Get the current font height + */ + virtual int getFontHeight() const; + + /** + * Returns the width of a given string in pixels + */ + virtual int stringWidth(const CString &str); + + /** + * Draws a frame enclosing the specified area + */ + virtual void frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b); + + /** + * Clear a portion of the screen surface + */ + virtual void clearSurface(SurfaceNum surfaceNum, Rect *bounds); + + /** + * Resize the passed surface + */ + virtual void resizeSurface(CVideoSurface *surface, int width, int height); + + /** + * Creates a surface of a given size + */ + virtual CVideoSurface *createSurface(int w, int h); + + /** + * Creates a surface from a specified resource + */ + virtual CVideoSurface *createSurface(const CResourceKey &key); + + /** + * Show the mouse cursor + */ + virtual void showCursor(); + + /** + * Hide the mouse cursor + */ + virtual void hideCursor(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SCREEN_MANAGER_H */ diff --git a/engines/titanic/support/simple_file.cpp b/engines/titanic/support/simple_file.cpp new file mode 100644 index 0000000000..35b2e28e4a --- /dev/null +++ b/engines/titanic/support/simple_file.cpp @@ -0,0 +1,512 @@ +/* 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/util.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +CString readStringFromStream(Common::SeekableReadStream *s) { + CString result; + char c; + while ((c = s->readByte()) != '\0') + result += c; + + return result; +} + +/*------------------------------------------------------------------------*/ + +bool File::open(const Common::String &filename) { + if (!Common::File::open(filename)) + error("Could not open file - %s", filename.c_str()); + return true; +} + +/*------------------------------------------------------------------------*/ + +SimpleFile::SimpleFile(): _inStream(nullptr), _outStream(nullptr), _lineCount(1) { +} + +SimpleFile::~SimpleFile() { + close(); +} + +void SimpleFile::open(Common::SeekableReadStream *stream) { + close(); + _inStream = stream; +} + +void SimpleFile::open(Common::OutSaveFile *stream) { + close(); + _outStream = stream; +} + +void SimpleFile::close() { + if (_outStream) { + _outStream->finalize(); + delete _outStream; + _outStream = nullptr; + } + + if (_inStream) { + delete _inStream; + _inStream = nullptr; + } +} + +void SimpleFile::safeRead(void *dst, size_t count) { + if (unsafeRead(dst, count) != count) + error("Could not read %d bytes", (int)count); +} + +size_t SimpleFile::unsafeRead(void *dst, size_t count) { + assert(_inStream); + return _inStream->read(dst, count); +} + +size_t SimpleFile::write(const void *src, size_t count) const { + assert(_outStream); + return _outStream->write(src, count); +} + +void SimpleFile::seek(int offset, int origin) { + assert(_inStream); + _inStream->seek(offset, origin); +} + +byte SimpleFile::readByte() { + byte b; + safeRead(&b, 1); + return b; +} + +uint SimpleFile::readUint16LE() { + uint val; + safeRead(&val, 2); + return READ_LE_UINT16(&val); +} + +uint SimpleFile::readUint32LE() { + uint val; + safeRead(&val, 4); + return READ_LE_UINT32(&val); +} + +CString SimpleFile::readString() { + char c; + CString result; + bool backslashFlag = false; + + // First skip any spaces + do { + safeRead(&c, 1); + } while (Common::isSpace(c)); + + // Ensure we've found a starting quote for the string + if (c != '"') + error("Could not find starting quote"); + + bool endFlag = false; + while (!endFlag) { + // Read the next character + safeRead(&c, 1); + + if (backslashFlag) { + backslashFlag = false; + switch (c) { + case 'n': + result += '\n'; + break; + case 'r': + result += '\r'; + break; + case '\t': + result += '\t'; + break; + default: + result += c; + break; + } + } else { + switch (c) { + case '"': + endFlag = true; + break; + case '\\': + backslashFlag = true; + break; + default: + result += c; + break; + } + } + } + + // Return the string + return result; +} + +int SimpleFile::readNumber() { + char c; + int result = 0; + bool minusFlag = false; + + // First skip any spaces + do { + safeRead(&c, 1); + } while (Common::isSpace(c)); + + // Check for prefix sign + if (c == '+' || c == '-') { + minusFlag = c == '-'; + safeRead(&c, 1); + } + + // Read in the number + if (!Common::isDigit(c)) + error("Invalid number"); + + while (Common::isDigit(c)) { + result = result * 10 + (c - '0'); + safeRead(&c, 1); + } + + // Finally, if it's a minus value, then negate it + if (minusFlag) + result = -result; + + return result; +} + +double SimpleFile::readFloat() { + char c; + Common::String result; + + // First skip any spaces + do { + safeRead(&c, 1); + } while (Common::isSpace(c)); + + // Check for prefix sign + if (c == '+' || c == '-') { + result += c; + safeRead(&c, 1); + } + + // Read in the number + if (!Common::isDigit(c)) + error("Invalid number"); + + while (Common::isDigit(c) || c == '.') { + result += c; + safeRead(&c, 1); + } + + // Convert to a float and return it + float floatValue; + sscanf(result.c_str(), "%f", &floatValue); + + return floatValue; +} + +Point SimpleFile::readPoint() { + Point pt; + pt.x = readNumber(); + pt.y = readNumber(); + + return pt; +} + +Rect SimpleFile::readRect() { + Rect r; + r.left = readNumber(); + r.top = readNumber(); + r.right = readNumber(); + r.bottom = readNumber(); + + return r; +} + +Rect SimpleFile::readBounds() { + Rect r; + r.left = readNumber(); + r.top = readNumber(); + r.setWidth(readNumber()); + r.setHeight(readNumber()); + + return r; +} + +void SimpleFile::readBuffer(char *buffer, size_t count) { + CString tempString = readString(); + if (buffer) { + strncpy(buffer, tempString.c_str(), count); + buffer[count - 1] = '\0'; + } +} + +void SimpleFile::writeUint16LE(uint val) { + byte lo = val & 0xff; + byte hi = (val >> 8) & 0xff; + write(&lo, 1); + write(&hi, 1); +} + +void SimpleFile::writeUint32LE(uint val) { + uint16 lo = val & 0xffff; + uint16 hi = (val >> 16) & 0xff; + writeUint16LE(lo); + writeUint16LE(hi); +} + +void SimpleFile::writeLine(const CString &str) const { + write(str.c_str(), str.size()); + write("\r\n", 2); +} + +void SimpleFile::writeString(const CString &str) const { + if (str.empty()) + return; + + const char *msgP = str.c_str(); + char c; + + while ((c = *msgP++) != '\0') { + switch (c) { + case '\r': + write("\\r", 2); + break; + case '\n': + write("\\n", 2); + break; + case '\t': + write("\\t", 2); + break; + case '\"': + write("\\\"", 2); + break; + case '\\': + write("\\\\", 2); + break; + case '{': + write("\\{", 2); + break; + case '}': + write("\\}", 2); + break; + default: + write(&c, 1); + break; + } + } +} + +void SimpleFile::writeQuotedString(const CString &str) const { + write("\"", 1); + writeString(str); + write("\" ", 2); +} + +void SimpleFile::writeQuotedLine(const CString &str, int indent) const { + writeIndent(indent); + writeQuotedString(str); + write("\n", 1); +} + +void SimpleFile::writeNumber(int val) const { + CString str = CString::format("%d ", val); + write(str.c_str(), str.size()); +} + +void SimpleFile::writeNumberLine(int val, int indent) const { + writeIndent(indent); + writeNumber(val); + write("\n", 1); +} + +void SimpleFile::writeFloat(double val) const { + Common::String valStr = Common::String::format("%f ", val); + write(valStr.c_str(), valStr.size()); +} + +void SimpleFile::writeFloatLine(double val, int indent) const { + writeIndent(indent); + writeFloat(val); + write("\n", 1); +} + +void SimpleFile::writePoint(const Point &pt, int indent) const { + writeIndent(indent); + writeNumber(pt.x); + writeNumber(pt.y); + write("\n", 1); +} + +void SimpleFile::writeRect(const Rect &r, int indent) const { + writePoint(Point(r.left, r.top), indent); + writePoint(Point(r.right, r.bottom), indent); +} + +void SimpleFile::writeBounds(const Rect &r, int indent) const { + writePoint(Point(r.left, r.top), indent); + writePoint(Point(r.width(), r.height()), indent); +} + +void SimpleFile::writeFormat(const char *format, ...) const { + // Convert the format specifier and params to a string + va_list va; + va_start(va, format); + CString line = CString::vformat(format, va); + va_end(va); + + // Write out the string + write(format, strlen(format)); +} + +void SimpleFile::writeIndent(uint indent) const { + for (uint idx = 0; idx < indent; ++idx) + write("\t", 1); +} + +bool SimpleFile::IsClassStart() { + char c; + + do { + safeRead(&c, 1); + } while (Common::isSpace(c)); + + assert(c == '{' || c == '}'); + return c == '{'; +} + +void SimpleFile::writeClassStart(const CString &classStr, int indent) { + write("\n", 1); + writeIndent(indent); + write("{\n", 2); + writeIndent(indent + 1); + writeQuotedString(classStr); + write("\n", 1); +} + +void SimpleFile::writeClassEnd(int indent) { + writeIndent(indent); + write("}\n", 2); +} + +bool SimpleFile::scanf(const char *format, ...) { + va_list va; + va_start(va, format); + char c; + + CString formatStr(format); + while (!formatStr.empty()) { + if (formatStr.hasPrefix(" ")) { + formatStr.deleteChar(0); + + safeRead(&c, 1); + if (!Common::isSpace(c)) + return false; + + // Skip over whitespaces + skipSpaces(); + } else if (formatStr.hasPrefix("%d")) { + // Read in a number + formatStr = CString(formatStr.c_str() + 2); + int *param = (int *)va_arg(va, int *); + *param = readNumber(); + + if (!eos()) + _inStream->seek(-1, SEEK_CUR); + } else if (formatStr.hasPrefix("%s")) { + // Read in text until the next space + formatStr = CString(formatStr.c_str() + 2); + CString *str = (CString *)va_arg(va, CString *); + str->clear(); + while (!eos() && !Common::isSpace(c = readByte())) + *str += c; + + if (!eos()) + _inStream->seek(-1, SEEK_CUR); + } + } + + skipSpaces(); + va_end(va); + return true; +} + +void SimpleFile::skipSpaces() { + char c = ' '; + while (!eos() && Common::isSpace(c)) + safeRead(&c, 1); + + if (!eos()) + _inStream->seek(-1, SEEK_CUR); +} + +/*------------------------------------------------------------------------*/ + +bool StdCWadFile::open(const Common::String &filename) { + File f; + CString name = filename; + + // Check for whether it is indeed a file/resource pair + int idx = name.indexOf('#'); + + if (idx < 0) { + // Nope, so open up file for standard reading + assert(!name.empty()); + f.open(name); + + SimpleFile::open(f.readStream(f.size())); + return true; + } + + // Split up the name and resource, and get the resource index + CString fname = name.left(idx) + ".st"; + int extPos = name.lastIndexOf('.'); + CString resStr = name.mid(idx + 1, extPos - idx - 1); + int resIndex = resStr.readInt(); + + // Open up the index for access + f.open(fname); + int indexSize = f.readUint32LE() / 4; + assert(resIndex < indexSize); + + // Get the specific resource's offset, and size by also + // getting the offset of the following resource + f.seek(resIndex * 4); + uint resOffset = f.readUint32LE(); + uint nextOffset = (resIndex == (indexSize - 1)) ? f.size() : + f.readUint32LE(); + + // Read in the resource + f.seek(resOffset); + Common::SeekableReadStream *stream = f.readStream(nextOffset - resOffset); + SimpleFile::open(stream); + + f.close(); + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/simple_file.h b/engines/titanic/support/simple_file.h new file mode 100644 index 0000000000..f5d0bc7c1b --- /dev/null +++ b/engines/titanic/support/simple_file.h @@ -0,0 +1,321 @@ +/* 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_SIMPLE_FILE_H +#define TITANIC_SIMPLE_FILE_H + +#include "common/file.h" +#include "titanic/support/rect.h" +#include "common/savefile.h" +#include "common/stream.h" +#include "common/zlib.h" +#include "titanic/support/string.h" + +namespace Titanic { + +class Decompressor; +class DecompressorData; + +/** + * Simple ScummVM File descendent that throws a wobbly if + * the file it tries to open isn't present + */ +class File : public Common::File { +public: + virtual bool open(const Common::String &filename); +}; + +/** + * This class implements basic reading and writing to files + */ +class SimpleFile { +private: + /** + * Skip over any pending spaces + */ + void skipSpaces(); +protected: + Common::SeekableReadStream *_inStream; + Common::OutSaveFile *_outStream; + int _lineCount; +public: + SimpleFile(); + virtual ~SimpleFile(); + + operator Common::SeekableReadStream &() { return *_inStream; } + operator Common::WriteStream &() { return *_outStream; } + + /** + * Set up a stream for read access + */ + virtual void open(Common::SeekableReadStream *stream); + + /** + * Set up a stream for write access + */ + virtual void open(Common::OutSaveFile *stream); + + /** + * Close the file + */ + virtual void close(); + + /** + * Read from the file with validation + */ + virtual void safeRead(void *dst, size_t count); + + /** + * Read from the file + */ + virtual size_t unsafeRead(void *dst, size_t count); + + /** + * Write out data + */ + virtual size_t write(const void *src, size_t count) const; + + /** + * Seek + */ + virtual void seek(int offset, int origin); + /** + * Read a byte + */ + byte readByte(); + + /** + * Read a 16-bit LE number + */ + uint readUint16LE(); + + /** + * Read a 32-bit LE number + */ + uint readUint32LE(); + + /** + * Read a string from the file + */ + CString readString(); + + /** + * Read a number from the file + */ + int readNumber(); + + /** + * Read a floating point number from the file + */ + double readFloat(); + + /** + * Read in a point + */ + Point readPoint(); + + /** + * Read in a rect + */ + Rect readRect(); + + /** + * Rect in a bounds + */ + Rect readBounds(); + + /** + * Read a string and copy it into an optionally passed buffer + */ + void readBuffer(char *buffer = nullptr, size_t count = 0); + + /** + * Scan in values from the file + */ + bool scanf(const char *format, ...); + + /** + * Write out a byte + */ + void writeByte(byte b) { write(&b, 1); } + + /** + * Write out a raw 16-bit LE number + */ + void writeUint16LE(uint val); + + /** + * Write out a raw 32-bit LE number + */ + void writeUint32LE(uint val); + + /** + * Write a string line + */ + void writeLine(const CString &str) const; + + /** + * Write a string + */ + void writeString(const CString &str) const; + + /** + * Write a quoted string + */ + void writeQuotedString(const CString &str) const; + + /** + * Write a quoted string line + */ + void writeQuotedLine(const CString &str, int indent) const; + + /** + * Write a number to file + */ + void writeNumber(int val) const; + + /** + * Write a number line to file + */ + void writeNumberLine(int val, int indent) const; + + /** + * Write a floating point number + */ + void writeFloat(double val) const; + + /** + * Write a floating point number as a line + */ + void writeFloatLine(double val, int indent) const; + + /** + * Write out a point line + */ + void writePoint(const Point &pt, int indent)const; + + /** + * Write out a rect line + */ + void writeRect(const Rect &r, int indent) const; + + /** + * Write out a bounds line + */ + void writeBounds(const Rect &r, int indent) const; + + /** + * Write out a string using a format specifier, just like fprintf + */ + void writeFormat(const char *format, ...) const; + + /** + * Write out a number of tabs to form an indent in the output + */ + void writeIndent(uint indent) const; + + /** + * Validates that the following non-space character is either + * an opening or closing squiggly bracket denoting a class + * definition start or end. Returns true if it's a class start + */ + bool IsClassStart(); + + /** + * Write the starting header for a class definition + */ + void writeClassStart(const CString &classStr, int indent); + + /** + * Write out the ending footer for a class definition + */ + void writeClassEnd(int indent); + + /** + * Return true if the stream has finished being read + */ + bool eos() const { + assert(_inStream); + return _inStream->pos() >= _inStream->size(); + } +}; + +/** + * Derived file that handles compressed files + */ +class CompressedFile : public SimpleFile { +public: + CompressedFile() : SimpleFile() {} + virtual ~CompressedFile() {} + + /** + * Set up a stream for read access + */ + virtual void open(Common::SeekableReadStream *stream) { + SimpleFile::open(Common::wrapCompressedReadStream(stream)); + } + + /** + * Set up a stream for write access + */ + virtual void open(Common::OutSaveFile *stream) { + SimpleFile::open(Common::wrapCompressedWriteStream(stream)); + } +}; + +/** + * Derived file that handles WAD archives containing multiple files + */ +class StdCWadFile : public SimpleFile { +public: + StdCWadFile() : SimpleFile() {} + virtual ~StdCWadFile() {} + + /** + * Open up the specified file + */ + virtual bool open(const Common::String &filename); + + /** + * Unsupported open method from parent class + */ + virtual void open(Common::SeekableReadStream *stream) {} + + /** + * Unsupported open method from parent class + */ + virtual void open(Common::OutSaveFile *stream) {} + + /** + * Return a reference to the read stream + */ + Common::SeekableReadStream *readStream() const { return _inStream; } +}; + +/** + * General purpose support method for reading an ASCIIZ string from a stream + */ +CString readStringFromStream(Common::SeekableReadStream *s); + +} // End of namespace Titanic + +#endif /* TITANIC_SIMPLE_FILE_H */ diff --git a/engines/titanic/support/string.cpp b/engines/titanic/support/string.cpp new file mode 100644 index 0000000000..9961cfce59 --- /dev/null +++ b/engines/titanic/support/string.cpp @@ -0,0 +1,145 @@ +/* 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/algorithm.h" +#include "titanic/support/string.h" + +namespace Titanic { + +CString::CString(char c, uint32 len) : Common::String() { + ensureCapacity(len, false); + for (uint idx = 0; idx < len; ++idx) + (*this) += c; +} + +CString::CString(int val) : Common::String() { + *this = CString::format("%d", val); +} + +CString CString::left(uint count) const { + return (count > size()) ? CString() : CString(c_str(), c_str() + count); +} + +CString CString::right(uint count) const { + uint strSize = size(); + return (count > strSize) ? CString() : + CString(c_str() + strSize - count, c_str() + strSize); +} + +CString CString::mid(uint start, uint count) const { + if (start >= size()) + return CString(); + else + return CString(c_str() + start, MIN(count, size() - start)); +} + +CString CString::mid(uint start) const { + uint strSize = size(); + assert(start <= strSize); + return mid(start, strSize - start); +} + +CString CString::deleteRight(uint count) const { + return (count >= size()) ? CString() : left(size() - count); +} + +int CString::indexOf(char c) const { + const char *charP = strchr(c_str(), c); + return charP ? charP - c_str() : -1; +} + +int CString::indexOf(const char *s) const { + const char *strP = strstr(c_str(), s); + return strP ? strP - c_str() : -1; +} + +int CString::lastIndexOf(char c) const { + const char *charP = strrchr(c_str(), c); + return charP ? charP - c_str() : -1; +} + +FileType CString::fileTypeSuffix() const { + CString ext = right(1); + if (ext == "0" || ext == "4") + return FILETYPE_IMAGE; + else if (ext == "1") + return FILETYPE_WAV; + else if (ext == "2" || ext == "3") + return FILETYPE_MOVIE; + + ext = right(3); + if (ext == "tga" || ext == "jpg") + return FILETYPE_IMAGE; + else if (ext == "wav") + return FILETYPE_WAV; + else if (ext == "avi" || ext == "mov") + return FILETYPE_MOVIE; + else if (ext == "dlg") + return FILETYPE_DLG; + else + return FILETYPE_UNKNOWN; +} + +ImageType CString::imageTypeSuffix() const { + CString ext = right(1); + if (ext == "0") + return IMAGETYPE_TARGA; + else if (ext == "4") + return IMAGETYPE_JPEG; + + ext = right(3); + if (ext == "tga") + return IMAGETYPE_TARGA; + else if (ext == "jpg") + return IMAGETYPE_JPEG; + else + return IMAGETYPE_UNKNOWN; +} + +CString CString::format(const char *fmt, ...) { + String output; + + va_list va; + va_start(va, fmt); + output = String::vformat(fmt, va); + va_end(va); + + return output; +} + +bool CString::operator==(const CString &x) const { + return compareToIgnoreCase(x) == 0; +} + +bool CString::operator==(const char *x) const { + return compareToIgnoreCase(x) == 0; +} + +bool CString::operator!=(const CString &x) const { + return compareToIgnoreCase(x) != 0; +} + +bool CString::operator!=(const char *x) const { + return compareToIgnoreCase(x) != 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/string.h b/engines/titanic/support/string.h new file mode 100644 index 0000000000..71242c01c9 --- /dev/null +++ b/engines/titanic/support/string.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_STRING_H +#define TITANIC_STRING_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/str.h" + +namespace Titanic { + +enum FileType { + FILETYPE_UNKNOWN = 0, FILETYPE_IMAGE = 1, FILETYPE_MOVIE = 2, + FILETYPE_WAV = 3, FILETYPE_DLG = 4 +}; + +enum ImageType { + IMAGETYPE_UNKNOWN = 0, IMAGETYPE_TARGA = 1, IMAGETYPE_JPEG = 2 +}; + +class CString : public Common::String { +public: + CString() : Common::String() {} + CString(const char *str) : Common::String(str) {} + CString(const char *str, uint32 len) : Common::String(str, len) {} + CString(const char *beginP, const char *endP) : Common::String(beginP, endP) {} + CString(const String &str) : Common::String(str) {} + CString(char c, uint32 len); + explicit CString(char c) : Common::String(c) {} + explicit CString(int val); + + bool operator==(const CString &x) const; + bool operator==(const char *x) const; + bool operator!=(const CString &x) const; + bool operator!=(const char *x) const; + + /** + * Returns the left n characters of the string + */ + CString left(uint count) const; + + /** + * Returns the right n characters of the string + */ + CString right(uint count) const; + + /** + * Returns a substring from within the string + */ + CString mid(uint start, uint count) const; + + /** + * Returns a substring from within the string + */ + CString mid(uint start) const; + + /** + * Returns a substring consisting of the entire string + * except for a specified number of characters at the end + */ + CString deleteRight(uint count) const; + + /** + * Returns the index of the first occurance of a given character + */ + int indexOf(char c) const; + + /** + * Returns the index of the first occurance of a given string + */ + int indexOf(const char *s) const; + + /** + * Returns the index of the last occurance of a given character + */ + int lastIndexOf(char c) const; + + /** + * Returns the type of a filename based on it's extension + */ + FileType fileTypeSuffix() const; + + /** + * Returns the type of an image filename based on it's extension + */ + ImageType imageTypeSuffix() const; + + /** + * Parses the string as an integer and returns the value + */ + int readInt() const { + return atoi(c_str()); + } + + /** + * Format a string + */ + static CString format(const char *fmt, ...); +}; + +typedef Common::Array<CString> StringArray; + +} // End of namespace Titanic + +#endif /* TITANIC_STRING_H */ diff --git a/engines/titanic/support/string_parser.cpp b/engines/titanic/support/string_parser.cpp new file mode 100644 index 0000000000..496440a973 --- /dev/null +++ b/engines/titanic/support/string_parser.cpp @@ -0,0 +1,97 @@ +/* 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/support/string_parser.h" +#include "common/util.h" + +namespace Titanic { + +void CStringParser::skipSeperators(const CString &seperatorChars) { + for (; _index < size(); ++_index) { + char c = (*this)[_index]; + if (seperatorChars.indexOf(c) == -1) + break; + } +} + +bool CStringParser::parse(CString &resultStr, const CString &seperatorChars, bool allowQuotes) { + if (_index >= size()) + return false; + + resultStr.clear(); + bool quoteFlag = false; + while (_index < size()) { + char c = (*this)[_index]; + if (!quoteFlag && seperatorChars.indexOf(c) >= 0) + break; + + if (allowQuotes) { + if (quoteFlag) { + if (c == '"') { + // End of quoted string + ++_index; + break; + } + } else { + if (c == '"') { + // Start of quoted string + ++_index; + quoteFlag = true; + continue; + } + } + } + + resultStr += c; + ++_index; + } + + return true; +} + +uint CStringParser::readInt() { + // Get digits from the string + CString numStr; + while (Common::isDigit(currentChar())) + numStr += getNextChar(); + + // Throw a wobbly if there wasn't a number + if (numStr.empty()) + error("ReadInt(): No number to read"); + + return atoi(numStr.c_str()); +} + +char CStringParser::currentChar() const { + return (_index >= size()) ? '\0' : (*this)[_index]; +} + +char CStringParser::getNextChar() { + return (_index >= size()) ? '\0' : (*this)[_index++]; +} + +void CStringParser::skipSpaces() { + while (_index < size() && Common::isSpace(currentChar())) + ++_index; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/string_parser.h b/engines/titanic/support/string_parser.h new file mode 100644 index 0000000000..f89caacfb5 --- /dev/null +++ b/engines/titanic/support/string_parser.h @@ -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. + * + */ + +#ifndef TITANIC_STRING_PARSER_H +#define TITANIC_STRING_PARSER_H + +#include "titanic/support/string.h" + +namespace Titanic { + +class CStringParser : public CString { +private: + uint _index; +private: + /** + * Gets the character at the current index + */ + char currentChar() const; + + /** + * Gets the next character, and increments the parsing index + */ + char getNextChar(); + + /** + * Skips over any spaces + */ + void skipSpaces(); +public: + CStringParser() : CString(), _index(0) {} + CStringParser(const CString &str) : CString(str), _index(0) {} + + /** + * Skips over any specified seperator characters in our string + * at the current index + */ + void skipSeperators(const CString &seperatorChars); + + /** + * Parses out a string from a source string at the current index + * @param resultStr String to hold the resulting sring + * @param seperatorChras List of characters that seperate string values + * @param allowQuotes If true, handles double-quoted substrings + * @returns True if a string entry was extracted + */ + bool parse(CString &resultStr, const CString &seperatorChars, bool allowQuotes = false); + + /** + * Reads an integer from the string + */ + uint readInt(); + +}; + +} // End of namespace Titanic + +#endif /* TITANIC_STRING_PARSER_H */ diff --git a/engines/titanic/support/text_cursor.cpp b/engines/titanic/support/text_cursor.cpp new file mode 100644 index 0000000000..ad3fe4ed26 --- /dev/null +++ b/engines/titanic/support/text_cursor.cpp @@ -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. + * + */ + +#include "common/textconsole.h" +#include "titanic/support/text_cursor.h" +#include "titanic/support/screen_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CTextCursor::CTextCursor(CScreenManager *screenManager) : + _screenManager(screenManager), _active(false), _blinkVisible(false), + _backRenderSurface(nullptr), _frontRenderSurface(nullptr), + _blinkDelay(300), _size(2, 10), _priorBlinkTime(0), + _cursorR(0), _cursorG(0), _cursorB(0), _mode(-1) { + _surface = screenManager->createSurface(10, 10); +} + +CTextCursor::~CTextCursor() { + delete _surface; +} + +void CTextCursor::setColor(byte r, byte g, byte b) { + _cursorR = r; + _cursorG = g; + _cursorB = b; +} + +void CTextCursor::show() { + _backRenderSurface = _screenManager->getSurface(SURFACE_BACKBUFFER); + _frontRenderSurface = _screenManager->getFrontRenderSurface(); + _active = true; + _priorBlinkTime = g_vm->_events->getTicksCount(); +} + +void CTextCursor::hide() { + _active = false; +} + +void CTextCursor::draw() { + if (!_active) + return; + + // Handle updating whether the blinking cursor is visible or not + uint newTicks = g_vm->_events->getTicksCount(); + while (newTicks > (_priorBlinkTime + _blinkDelay)) { + _priorBlinkTime += _blinkDelay; + _blinkVisible = !_blinkVisible; + } + + if (_blinkVisible) { + Rect cursorRect = getCursorBounds(); + _surface->blitFrom(Common::Point(0, 0), _backRenderSurface, &cursorRect); + + if (!_screenBounds.isEmpty()) + // Limit the cursor rect to only within designated screen area + cursorRect.constrain(_screenBounds); + + if (!cursorRect.isEmpty()) { + // Draw cursor onto the screen + _backRenderSurface->_ddSurface->fillRect(&cursorRect, + _cursorR, _cursorG, _cursorB); + } + + //_screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &_pos); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/text_cursor.h b/engines/titanic/support/text_cursor.h new file mode 100644 index 0000000000..d8c6ac0653 --- /dev/null +++ b/engines/titanic/support/text_cursor.h @@ -0,0 +1,121 @@ +/* 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_TEXT_CURSOR_H +#define TITANIC_TEXT_CURSOR_H + +#include "common/scummsys.h" +#include "titanic/support/rect.h" + +namespace Titanic { + +class CScreenManager; +class CVideoSurface; + +class CTextCursor { +private: + CScreenManager *_screenManager; + CVideoSurface *_backRenderSurface; + CVideoSurface *_frontRenderSurface; + Point _pos; + Rect _screenBounds; + uint _blinkDelay; + bool _blinkVisible; + Point _size; + Point _screenTopLeft; + uint _priorBlinkTime; + byte _cursorR; + byte _cursorG; + byte _cursorB; + CVideoSurface *_surface; + int _mode; +public: + bool _active; +public: + CTextCursor(CScreenManager *screenManager); + ~CTextCursor(); + + /** + * Sets the position of the cursor + */ + void setPos(const Point &pt) { _pos = pt; } + + /** + * Sets the size of the cursor + */ + void setSize(const Point &size) { _size = size; } + + /** + * Returns the bounds for the cursor + */ + Rect getCursorBounds() const { + return Rect(_pos.x, _pos.y, _pos.x + _size.x, _pos.y + _size.y); + } + + /** + * Set bounds + */ + void setBounds(const Rect &r) { _screenBounds = r; } + + /** + * Clear the bounds + */ + void clearBounds() { _screenBounds.clear(); } + + /** + * Set the blinking rate + */ + void setBlinkRate(uint ticks) { _blinkDelay = ticks; } + + /** + * Set the cursor color + */ + void setColor(byte r, byte g, byte b); + + /** + * Returns whether the text cursor is active + */ + bool isActive() const { return _active; } + + int getMode() const { return _mode; } + + void setMode(int mode) { _mode = mode; } + + /** + * Show the text cursor + */ + void show(); + + /** + * Hide the text cursor + */ + void hide(); + + /** + * Update and draw the cursor if necessary + */ + void draw(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TEXT_CURSOR_H */ diff --git a/engines/titanic/support/time_event_info.cpp b/engines/titanic/support/time_event_info.cpp new file mode 100644 index 0000000000..0226223f1a --- /dev/null +++ b/engines/titanic/support/time_event_info.cpp @@ -0,0 +1,206 @@ +/* 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/support/time_event_info.h" +#include "titanic/core/game_object.h" +#include "titanic/core/project_item.h" +#include "titanic/messages/messages.h" + +namespace Titanic { + +void CTimeEventInfoList::postLoad(uint ticks, CProjectItem *project) { + for (iterator i = begin(); i != end(); ++i) + (*i)->postLoad(ticks, project); +} + +void CTimeEventInfoList::preSave(uint ticks) { + for (iterator i = begin(); i != end(); ++i) + (*i)->preSave(ticks); +} + +void CTimeEventInfoList::postSave() { + for (iterator i = begin(); i != end(); ++i) + (*i)->postSave(); +} + +void CTimeEventInfoList::update(uint ticks) { + // Remove any items that are done + for (iterator i = begin(); i != end(); ) { + CTimeEventInfo *item = *i; + if (item->_done) { + i = erase(i); + delete item; + } else { + ++i; + } + } + + // Handle updating the items + for (iterator i = begin(); i != end(); ) { + CTimeEventInfo *item = *i; + if (!item->update(ticks)) { + ++i; + } else { + i = erase(i); + delete item; + } + } +} + +void CTimeEventInfoList::stop(uint id) { + for (iterator i = begin(); i != end(); ++i) { + CTimeEventInfo *item = *i; + if (item->_id == id) { + item->_done = true; + return; + } + } +} + +void CTimeEventInfoList::setPersisent(uint id, bool flag) { + for (iterator i = begin(); i != end(); ++i) { + CTimeEventInfo *item = *i; + if (item->_id == id) { + item->setPersisent(flag); + return; + } + } +} + +/*------------------------------------------------------------------------*/ + +uint CTimeEventInfo::_nextId; + +CTimeEventInfo::CTimeEventInfo() : ListItem(), _lockCounter(0), + _repeated(false), _firstDuration(0), _repeatDuration(0), + _target(nullptr), _actionVal(0), _timerCtr(0), _done(false), + _lastTimerTicks(0), _relativeTicks(0), _persisent(true) { + _id = _nextId++; +} + +CTimeEventInfo::CTimeEventInfo(uint ticks, bool repeated, uint firstDuration, + uint repeatDuration, CTreeItem *target, int endVal, const CString &action) : + ListItem(), _lockCounter(0), _repeated(repeated), _firstDuration(firstDuration), + _repeatDuration(repeatDuration), _target(target), _actionVal(endVal), _done(false), + _timerCtr(0), _lastTimerTicks(ticks), _relativeTicks(0), _persisent(true) { + _id = _nextId++; +} + +void CTimeEventInfo::save(SimpleFile *file, int indent) { + file->writeNumberLine(0, indent); + + CString targetName; + if (_target) + targetName = _target->getName(); + file->writeQuotedLine(targetName, indent); + file->writeNumberLine(_id, indent); + file->writeNumberLine(_repeated, indent); + file->writeNumberLine(_firstDuration, indent); + file->writeNumberLine(_repeatDuration, indent); + file->writeNumberLine(_actionVal, indent); + file->writeQuotedLine(_action, indent); + file->writeNumberLine(_timerCtr, indent); + file->writeNumberLine(_relativeTicks, indent); + file->writeNumberLine(_done, indent); + file->writeNumberLine(_persisent, indent); +} + +void CTimeEventInfo::load(SimpleFile *file) { + lock(); + int val = file->readNumber(); + + if (!val) { + _targetName = file->readString(); + _id = file->readNumber(); + _repeated = file->readNumber(); + _firstDuration = file->readNumber(); + _repeatDuration = file->readNumber(); + _actionVal = file->readNumber(); + _action = file->readString(); + _timerCtr = file->readNumber(); + _relativeTicks = file->readNumber(); + _done = file->readNumber() != 0; + _persisent = file->readNumber() != 0; + _target = nullptr; + } +} + +void CTimeEventInfo::postLoad(uint ticks, CProjectItem *project) { + if (!_persisent || _targetName.empty()) + _done = true; + + // Get the timer's target + if (project) + _target = project->findByName(_targetName); + if (!_target) + _done = true; + + _lastTimerTicks = ticks + _relativeTicks; + if (_id >= _nextId) + _nextId = _id + 1; + + unlock(); +} + +void CTimeEventInfo::preSave(uint ticks) { + _relativeTicks = _lastTimerTicks - ticks; + lock(); +} + +void CTimeEventInfo::postSave() { + unlock(); +} + +bool CTimeEventInfo::update(uint ticks) { + if (_lockCounter) + return false; + + if (_timerCtr) { + if (ticks > (_lastTimerTicks + _repeatDuration)) { + ++_timerCtr; + _lastTimerTicks = ticks; + + if (_target) { + CTimerMsg timerMsg(ticks, _timerCtr, _actionVal, _action); + timerMsg.execute(_target); + } + } + } else { + if (ticks > (_lastTimerTicks + _firstDuration)) { + _timerCtr = 1; + _lastTimerTicks = ticks; + + if (_target) { + CTimerMsg timerMsg(ticks, _timerCtr, _actionVal, _action); + timerMsg.execute(_target); + } + + if (!_repeated) + // Event is done, and can be removed + return true; + } + } + + return false; +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/time_event_info.h b/engines/titanic/support/time_event_info.h new file mode 100644 index 0000000000..ebf5b54458 --- /dev/null +++ b/engines/titanic/support/time_event_info.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_TIMER_H +#define TITANIC_TIMER_H + +#include "common/algorithm.h" +#include "titanic/core/list.h" + +namespace Titanic { + +class CTreeItem; +class CProjectItem; + +class CTimeEventInfo : public ListItem { +private: + /** + * Increments the counter + */ + void lock() { ++_lockCounter; } + + /** + * Called at the end of both post load and post save actions + */ + void unlock() { + _lockCounter = MAX(_lockCounter - 1, 0); + } +public: + static uint _nextId; +public: + int _lockCounter; + uint _id; + bool _repeated; + uint _firstDuration; + uint _repeatDuration; + CTreeItem *_target; + uint _actionVal; + CString _action; + uint _timerCtr; + uint _lastTimerTicks; + uint _relativeTicks; + bool _done; + bool _persisent; + CString _targetName; +public: + CLASSDEF; + CTimeEventInfo(); + CTimeEventInfo(uint ticks, bool repeated, uint firstDuration, uint repeatDuration, + CTreeItem *target, int endVal, const CString &action); + + /** + * 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); + + /** + * Called after loading a game has finished + */ + void postLoad(uint ticks, CProjectItem *project); + + /** + * Called when a game is about to be saved + */ + void preSave(uint ticks); + + /** + * Called when a game has finished being saved + */ + void postSave(); + + bool update(uint ticks); + + /** + * Flags whether the timer will be persisent across save & loads + */ + void setPersisent(bool val) { _persisent = val; } +}; + +class CTimeEventInfoList : public List<CTimeEventInfo> { +public: + /** + * Called after loading a game has finished + */ + void postLoad(uint ticks, CProjectItem *project); + + /** + * Called when a game is about to be saved + */ + void preSave(uint ticks); + + /** + * Called when a game has finished being saved + */ + void postSave(); + + /** + * Handles an update + */ + void update(uint ticks); + + /** + * Remove an item with the given Id + */ + void stop(uint id); + + /** + * Sets whether a timer with a given Id will be persisent across saves + */ + void setPersisent(uint id, bool flag); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TIMER_H */ diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp new file mode 100644 index 0000000000..594f660937 --- /dev/null +++ b/engines/titanic/support/video_surface.cpp @@ -0,0 +1,583 @@ +/* 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/support/video_surface.h" +#include "titanic/support/image_decoders.h" +#include "titanic/support/screen_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +int CVideoSurface::_videoSurfaceCounter = 0; + +CVideoSurface::CVideoSurface(CScreenManager *screenManager) : + _screenManager(screenManager), _rawSurface(nullptr), _movie(nullptr), + _pendingLoad(false), _transBlitFlag(false), _fastBlitFlag(false), + _movieFrameSurface(nullptr), _transparencyMode(TRANS_DEFAULT), + _freeMovieSurface(DisposeAfterUse::NO), _hasFrame(true), _lockCount(0) { + _videoSurfaceNum = _videoSurfaceCounter++; +} + +CVideoSurface::~CVideoSurface() { + if (_ddSurface) + _videoSurfaceCounter -= freeSurface(); + --_videoSurfaceCounter; + + if (_freeMovieSurface == DisposeAfterUse::YES) + delete _movieFrameSurface; +} + +void CVideoSurface::setSurface(CScreenManager *screenManager, DirectDrawSurface *surface) { + _screenManager = screenManager; + _ddSurface = surface; +} + +void CVideoSurface::blitFrom(const Point &destPos, CVideoSurface *src, const Rect *srcRect) { + if (loadIfReady() && src->loadIfReady() && _ddSurface && src->_ddSurface) { + Rect srcBounds, destBounds; + clipBounds(srcBounds, destBounds, src, srcRect, &destPos); + + if (src->_transBlitFlag) + blitRect2(srcBounds, destBounds, src); + else + blitRect1(srcBounds, destBounds, src); + } +} + +void CVideoSurface::blitFrom(const Point &destPos, const Graphics::Surface *src) { + lock(); + _rawSurface->blitFrom(*src, destPos); + unlock(); +} + +void CVideoSurface::clipBounds(Rect &srcRect, Rect &destRect, + CVideoSurface *srcSurface, const Rect *subRect, const Point *destPos) { + // Figure out initial source rect and dest rect, based on whether + // specific subRect and/or destPos have been passed + if (destPos) { + destRect.left = destPos->x; + destRect.top = destPos->y; + } else { + destRect.left = destRect.top = 0; + } + + if (subRect) { + destRect.right = destRect.left + subRect->width(); + destRect.bottom = destRect.top + subRect->height(); + srcRect = *subRect; + } else { + srcRect.right = srcRect.left + srcSurface->getWidth(); + srcRect.bottom = srcRect.top + srcSurface->getHeight(); + srcRect = Rect(0, 0, srcSurface->getWidth(), srcSurface->getHeight()); + } + + // Clip destination rect to be on-screen + if (destRect.left < 0) { + srcRect.left -= destRect.left; + destRect.left = 0; + } + if (destRect.top < 0) { + srcRect.top -= destRect.top; + destRect.top = 0; + } + if (destRect.right > getWidth()) { + srcRect.right += getWidth() - destRect.right; + destRect.right = getWidth(); + } + if (destRect.bottom > getHeight()) { + srcRect.bottom += getHeight() - destRect.bottom; + destRect.bottom = getHeight(); + } + + // Clip source rect to be within the source surface + if (srcRect.left < 0) { + destRect.left -= srcRect.left; + srcRect.left = 0; + } + if (srcRect.top < 0) { + destRect.top -= srcRect.top; + srcRect.top = 0; + } + if (srcRect.right > srcSurface->getWidth()) { + destRect.right += srcSurface->getWidth() - srcRect.right; + srcRect.right = srcSurface->getWidth(); + } + if (srcRect.bottom > srcSurface->getHeight()) { + destRect.bottom += srcSurface->getHeight() - srcRect.bottom; + srcRect.bottom = srcSurface->getHeight(); + } + + // Validate that the resulting rects are valid + if (destRect.left >= destRect.right || destRect.top >= destRect.bottom + || srcRect.left >= srcRect.right || srcRect.top >= srcRect.bottom) + error("Invalid rect"); +} + +void CVideoSurface::blitRect1(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { + src->lock(); + lock(); + + if (src->_fastBlitFlag) { + _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top)); + } else if (getMovieFrameSurface()) { + movieBlitRect(srcRect, destRect, src); + } else { + _rawSurface->transBlitFrom(*src->_rawSurface, srcRect, destRect, src->getTransparencyColor()); + } + + src->unlock(); + unlock(); +} + +void CVideoSurface::blitRect2(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { + if (getMovieFrameSurface()) { + movieBlitRect(srcRect, destRect, src); + } else { + src->lock(); + lock(); + + _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top)); + + src->unlock(); + unlock(); + } +} + +void CVideoSurface::movieBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { + // TODO +} + +uint CVideoSurface::getTransparencyColor() { + uint32 val = -(getPixelDepth() - 2); + val &= 0xFFFF8400; + val += 0xF81F; + return val; +} + +bool CVideoSurface::hasFrame() { + if (_hasFrame) { + _hasFrame = false; + return true; + } else if (_movie) { + return _movie->hasVideoFrame(); + } else { + return false; + } +} + +/*------------------------------------------------------------------------*/ + +byte OSVideoSurface::_palette1[32][32]; +byte OSVideoSurface::_palette2[32][32]; + +OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, DirectDrawSurface *surface) : + CVideoSurface(screenManager) { + _ddSurface = surface; +} + +OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey &key, bool pendingLoad) : + CVideoSurface(screenManager) { + _ddSurface = nullptr; + _pendingLoad = pendingLoad; + + if (_pendingLoad) { + loadResource(key); + } else { + _resourceKey = key; + load(); + } +} + +void OSVideoSurface::setupPalette(byte palette[32][32], byte val) { + for (uint idx1 = 0; idx1 < 32; ++idx1) { + for (uint idx2 = 0, base = 0; idx2 < 32; ++idx2, base += idx1) { + int64 v = 0x84210843; + v *= base; + uint v2 = (v >> 36); + v = ((v2 >> 31) + v2) & 0xff; + palette[idx1][idx2] = v << 3; + + if (val != 0xff && v != idx2) { + v = 0x80808081 * v * val; + v2 = v >> 39; + palette[idx1][idx2] = ((v2 >> 31) + v2) << 3; + } + } + } +} + +void OSVideoSurface::loadResource(const CResourceKey &key) { + _resourceKey = key; + _pendingLoad = true; + + if (hasSurface()) + load(); +} + +void OSVideoSurface::loadTarga(const CResourceKey &key) { + // Decode the image + CTargaDecode decoder; + decoder.decode(*this, key.getString()); + + if (getPixelDepth() == 2) + shiftColors(); + + _resourceKey = key; + +} + +void OSVideoSurface::loadJPEG(const CResourceKey &key) { + // Decode the image + CJPEGDecode decoder; + decoder.decode(*this, key.getString()); + + if (getPixelDepth() == 2) + shiftColors(); + + _resourceKey = key; +} + +void OSVideoSurface::loadTarga(const CString &name) { + CResourceKey key(name); + loadTarga(key); +} + +void OSVideoSurface::loadMovie(const CResourceKey &key, bool destroyFlag) { + // Delete any prior movie + if (_movie) { + delete _movie; + _movie = nullptr; + } + + // Create the new movie and load the first frame to the video surface + _movie = g_vm->_movieManager.createMovie(key, this); + _movie->setFrame(0); + + // If flagged to destroy, then immediately destroy movie instance + if (destroyFlag) { + delete _movie; + _movie = nullptr; + } + + _resourceKey = key; +} + +bool OSVideoSurface::lock() { + if (!loadIfReady()) + return false; + + ++_lockCount; + _rawSurface = _ddSurface->lock(nullptr, 0); + return true; +} + +void OSVideoSurface::unlock() { + if (!--_lockCount) { + if (_rawSurface) + _ddSurface->unlock(); + _rawSurface = nullptr; + } +} + +bool OSVideoSurface::hasSurface() { + return _ddSurface != nullptr; +} + +int OSVideoSurface::getWidth() { + if (!loadIfReady()) + error("Could not load resource"); + + return _ddSurface->getWidth(); +} + +int OSVideoSurface::getHeight() { + if (!loadIfReady()) + error("Could not load resource"); + + return _ddSurface->getHeight(); +} + +int OSVideoSurface::getPitch() { + if (!loadIfReady()) + error("Could not load resource"); + + return _ddSurface->getPitch(); +} + +int OSVideoSurface::getBpp() { + if (!loadIfReady()) + error("Could not load resource"); + + return getPixelDepth(); +} + +void OSVideoSurface::recreate(int width, int height) { + freeSurface(); + + _screenManager->resizeSurface(this, width, height); + if (_ddSurface) + _videoSurfaceCounter += _ddSurface->getSize(); +} + +void OSVideoSurface::resize(int width, int height) { + if (!_ddSurface || _ddSurface->getWidth() != width || + _ddSurface->getHeight() != height) + recreate(width, height); +} + +void OSVideoSurface::detachSurface() { + _ddSurface = nullptr; +} + +int OSVideoSurface::getPixelDepth() { + if (!loadIfReady()) + error("Could not load resource"); + + lock(); + + int result = _rawSurface->format.bytesPerPixel; + if (result == 1) + // Paletted 8-bit images don't store the color directly in the pixels + result = 0; + + unlock(); + return result; +} + +bool OSVideoSurface::load() { + if (!_resourceKey.scanForFile()) + return false; + + switch (_resourceKey.fileTypeSuffix()) { + case FILETYPE_IMAGE: + switch (_resourceKey.imageTypeSuffix()) { + case IMAGETYPE_TARGA: + loadTarga(_resourceKey); + break; + case IMAGETYPE_JPEG: + loadJPEG(_resourceKey); + break; + default: + break; + } + return true; + + case FILETYPE_MOVIE: + loadMovie(_resourceKey); + return true; + + default: + return false; + } +} + +uint16 OSVideoSurface::getPixel(const Common::Point &pt) { + if (!loadIfReady()) + return 0; + + if (pt.x >= 0 && pt.y >= 0 && pt.x < getWidth() && pt.y < getHeight()) { + lock(); + uint16 pixel = *(uint16 *)_rawSurface->getBasePtr(pt.x, pt.y); + unlock(); + return pixel; + } else { + return getTransparencyColor(); + } +} + +void OSVideoSurface::setPixel(const Point &pt, uint pixel) { + assert(getPixelDepth() == 2); + + uint16 *pixelP = (uint16 *)_rawSurface->getBasePtr(pt.x, pt.y); + *pixelP = pixel; +} + +void OSVideoSurface::changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag) { + assert(getPixelDepth() == 2); + const Graphics::PixelFormat &destFormat = _ddSurface->getFormat(); + const Graphics::PixelFormat srcFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); + + // Get the color + byte r, g, b; + srcFormat.colorToRGB(*color, r, g, b); + if (remapFlag) { + r = _palette1[31 - srcVal][r >> 3]; + g = _palette1[31 - srcVal][g >> 3]; + b = _palette1[31 - srcVal][b >> 3]; + } + + byte r2, g2, b2; + destFormat.colorToRGB(*pixelP, r2, g2, b2); + r2 = _palette1[srcVal][r2 >> 3]; + g2 = _palette1[srcVal][g2 >> 3]; + b2 = _palette1[srcVal][b2 >> 3]; + + *pixelP = destFormat.RGBToColor(r + r2, g + g2, b + b2); +} + +void OSVideoSurface::shiftColors() { + if (!loadIfReady()) + return; + + // Currently no further processing is needed, since for ScummVM, + // we already convert 16-bit surfaces as soon as they're loaded +} + +void OSVideoSurface::clear() { + if (!loadIfReady()) + error("Could not load resource"); + +} + +void OSVideoSurface::playMovie(uint flags, CGameObject *obj) { + if (loadIfReady() && _movie) + _movie->play(flags, obj); + + _ddSurface->fill(nullptr, 0); +} + +void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) { + if (loadIfReady() && _movie) { + _movie->play(startFrame, endFrame, flags, obj); + } +} + +void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) { + if (loadIfReady() && _movie) { + _movie->play(startFrame, endFrame, initialFrame, flags, obj); + } +} + +void OSVideoSurface::stopMovie() { + if (_movie) + _movie->stop(); +} + +void OSVideoSurface::setMovieFrame(uint frameNumber) { + if (loadIfReady() && _movie) + _movie->setFrame(frameNumber); +} + +void OSVideoSurface::addMovieEvent(int frameNumber, CGameObject *obj) { + if (_movie) + _movie->addEvent(frameNumber, obj); +} + +void OSVideoSurface::setMovieFrameRate(double rate) { + if (_movie) + _movie->setFrameRate(rate); +} + +const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const { + return _movie ? _movie->getMovieRangeInfo() : nullptr; +} + +void OSVideoSurface::flipVertically(bool needsLock) { + if (!loadIfReady() || !_transBlitFlag) + return; + + if (needsLock) + lock(); + + byte lineBuffer[SCREEN_WIDTH * 2]; + int pitch = getBpp() * getWidth(); + assert(pitch < (SCREEN_WIDTH * 2)); + + for (int yp = 0; yp < (_rawSurface->h / 2); ++yp) { + byte *line1P = (byte *)_rawSurface->getBasePtr(0, yp); + byte *line2P = (byte *)_rawSurface->getBasePtr(0, _rawSurface->h - yp - 1); + + Common::copy(line1P, line1P + pitch, lineBuffer); + Common::copy(line2P, line2P + pitch, line1P); + Common::copy(lineBuffer, lineBuffer + pitch, line1P); + } + + _transBlitFlag = false; + if (needsLock) + unlock(); +} + +bool OSVideoSurface::loadIfReady() { + _videoSurfaceNum = _videoSurfaceCounter; + + if (hasSurface()) { + return true; + } else if (_pendingLoad) { + _hasFrame = true; + load(); + return true; + } else { + return false; + } +} + +void OSVideoSurface::transPixelate() { + if (!loadIfReady()) + return; + + lock(); + Graphics::ManagedSurface *surface = _rawSurface; + uint transColor = getTransparencyColor(); + // TODO: Check whether color is correct + uint pixelColor = surface->format.RGBToColor(0x50, 0, 0); + + for (int yp = 0; yp < surface->h; ++yp) { + uint16 *pixelsP = (uint16 *)surface->getBasePtr(0, yp); + bool bitFlag = (yp % 2) == 0; + int replaceCtr = yp & 3; + + for (int xp = 0; xp < surface->w; ++xp, ++pixelsP) { + if (bitFlag && *pixelsP == transColor && replaceCtr == 0) + *pixelsP = pixelColor; + + bitFlag = !bitFlag; + replaceCtr = (replaceCtr + 1) & 3; + } + } + + surface->markAllDirty(); + unlock(); +} + +Graphics::ManagedSurface *OSVideoSurface::dupMovieFrame() const { + return _movie ? _movie->duplicateFrame() : nullptr; +} + +int OSVideoSurface::freeSurface() { + if (!_ddSurface) + return 0; + int surfaceSize = _ddSurface->getSize(); + + delete _movie; + _movie = nullptr; + delete _ddSurface; + _ddSurface = nullptr; + + return surfaceSize; +} + +uint16 *OSVideoSurface::getBasePtr(int x, int y) { + assert(_rawSurface); + return (uint16 *)_rawSurface->getBasePtr(x, y); +} + +} // End of namespace Titanic diff --git a/engines/titanic/support/video_surface.h b/engines/titanic/support/video_surface.h new file mode 100644 index 0000000000..053eabb0f9 --- /dev/null +++ b/engines/titanic/support/video_surface.h @@ -0,0 +1,537 @@ +/* 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_VIDEO_SURFACE_H +#define TITANIC_VIDEO_SURFACE_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "graphics/managed_surface.h" +#include "titanic/support/font.h" +#include "titanic/support/direct_draw.h" +#include "titanic/support/movie.h" +#include "titanic/support/movie_range_info.h" +#include "titanic/support/rect.h" +#include "titanic/core/list.h" +#include "titanic/core/resource_key.h" + +namespace Titanic { + +enum TransparencyMode { + TRANS_MASK0 = 0, TRANS_MASK255 = 1, TRANS_ALPHA0 = 2, + TRANS_ALPHA255 = 3, TRANS_DEFAULT = 4 +}; + +class CScreenManager; +class CJPEGDecode; +class CTargaDecode; + +class CVideoSurface : public ListItem { + friend class CJPEGDecode; + friend class CTargaDecode; +private: + /** + * Calculates blitting bounds + */ + void clipBounds(Rect &srcRect, Rect &destRect, CVideoSurface *srcSurface, + const Rect *subRect = nullptr, const Point *destPos = nullptr); + + void blitRect1(const Rect &srcRect, const Rect &destRect, CVideoSurface *src); + void blitRect2(const Rect &srcRect, const Rect &destRect, CVideoSurface *src); + void movieBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src); +protected: + static int _videoSurfaceCounter; +protected: + CScreenManager *_screenManager; + Graphics::ManagedSurface *_rawSurface; + bool _pendingLoad; + Graphics::ManagedSurface *_movieFrameSurface; + DisposeAfterUse::Flag _freeMovieSurface; + int _videoSurfaceNum; + bool _hasFrame; + int _lockCount; +public: + CMovie *_movie; + DirectDrawSurface *_ddSurface; + bool _fastBlitFlag; + bool _transBlitFlag; + CResourceKey _resourceKey; + TransparencyMode _transparencyMode; +public: + CVideoSurface(CScreenManager *screenManager); + virtual ~CVideoSurface(); + + /** + * Set the underlying surface for this video surface + */ + void setSurface(CScreenManager *screenManager, DirectDrawSurface *surface); + + /** + * Load the data for the class from file + */ + virtual void load(SimpleFile *file) { + ListItem::load(file); + } + + /** + * Load the surface with the passed resource + */ + virtual void loadResource(const CResourceKey &key) = 0; + + /** + * Loads a Targa image file specified by the resource key + */ + virtual void loadTarga(const CResourceKey &key) = 0; + + /** + * Loads a JPEG image file specified by the resource key + */ + virtual void loadJPEG(const CResourceKey &key) = 0; + + /** + * Loads a Targa image file specified by the given name + */ + virtual void loadTarga(const CString &name) = 0; + + /** + * Loads a movie file specified by the resource key. + * @param key Resource key for movie to load + * @param destroyFlag Immediately destroy movie after decoding first frame + */ + virtual void loadMovie(const CResourceKey &key, bool destroyFlag = false) = 0; + + /** + * Lock the surface for direct access to the pixels + */ + virtual bool lock() = 0; + + /** + * Unlocks the surface after prior calls to lock() + */ + virtual void unlock() = 0; + + /** + * Returns true if an underlying raw surface has been set + */ + virtual bool hasSurface() = 0; + + /** + * Returns the width of the surface + */ + virtual int getWidth() = 0; + + /** + * Returns the height of the surface + */ + virtual int getHeight() = 0; + + /** + * Returns the pitch of the surface in bytes + */ + virtual int getPitch() = 0; + + /** + * Returns the bytes per pixel of the surface + */ + virtual int getBpp() = 0; + + /** + * Recreates the surface + */ + virtual void recreate(int width, int height) = 0; + + /** + * Resizes the surface + */ + virtual void resize(int width, int height) = 0; + + /** + * Detachs the underlying raw surface + */ + virtual void detachSurface() = 0; + + /** + * Returns the number of bytes per pixel in the surface + */ + virtual int getPixelDepth() = 0; + + /** + * Gets the pixel at the specified position within the surface + */ + virtual uint16 getPixel(const Common::Point &pt) = 0; + + + /** + * Sets a pixel at a specified position within the surface + */ + virtual void setPixel(const Point &pt, uint pixel) = 0; + + /** + * Change a pixel + */ + virtual void changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag = true) = 0; + + /** + * Shifts the colors of the surface.. maybe greys it out? + */ + virtual void shiftColors() = 0; + + /** + * Clears the entire surface to black + */ + virtual void clear() = 0; + + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint flags, CGameObject *obj) = 0; + + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) = 0; + + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) = 0; + + /** + * Stops any movie currently attached to the surface + */ + virtual void stopMovie() = 0; + + /** + * Set the current movie frame number + */ + virtual void setMovieFrame(uint frameNumber) = 0; + + /** + * Adds a movie playback event + */ + virtual void addMovieEvent(int eventId, CGameObject *obj) = 0; + + /** + * Set the movie frame rate + */ + virtual void setMovieFrameRate(double rate) = 0; + + /** + * Return any movie range info associated with the surface's movie + */ + virtual const CMovieRangeInfoList *getMovieRangeInfo() const = 0; + + /** + * + */ + virtual void flipVertically(bool needsLock = true) = 0; + + /** + * Loads the surface's resource if there's one pending + */ + virtual bool loadIfReady() = 0; + + /** + * Loads the surface data based on the currently set resource key + */ + virtual bool load() = 0; + + /** + * Does a replacement of transparent pixels on certain lines at regular + * intervals. This is totally weird + */ + virtual void transPixelate() = 0; + + /** + * Returns true if there's a frame to display on the video surface + */ + virtual bool hasFrame(); + + /** + * Duplicates movie frame surface + */ + virtual Graphics::ManagedSurface *dupMovieFrame() const = 0; + + /** + * Frees the underlying surface + */ + virtual int freeSurface() { return 0; } + + /** + * Get a pointer into the underlying surface + */ + virtual uint16 *getBasePtr(int x, int y) = 0; + + /** + * Blit from another surface + */ + void blitFrom(const Point &destPos, CVideoSurface *src, const Rect *srcRect = nullptr); + + /** + * Blit from another surface + */ + void blitFrom(const Point &destPos, const Graphics::Surface *src); + + /** + * Sets the movie frame surface containing frame data from an active movie + */ + void setMovieFrameSurface(Graphics::ManagedSurface *frameSurface) { _movieFrameSurface = frameSurface; } + + /** + * Get the previously set movie frame surface + */ + Graphics::ManagedSurface *getMovieFrameSurface() const { return _movieFrameSurface; } + + /** + * Get the pixels associated with the surface. Only valid when the + * surface has been locked for access + */ + uint16 *getPixels() { return (uint16 *)_rawSurface->getPixels(); } + + /** + * Get a reference to the underlying surface. Only valid when the surface + * has been locked for access + */ + Graphics::ManagedSurface *getRawSurface() { return _rawSurface; } + + /** + * Returns the transparent color + */ + uint getTransparencyColor(); +}; + +class OSVideoSurface : public CVideoSurface { + friend class OSMovie; +private: + static byte _palette1[32][32]; + static byte _palette2[32][32]; + + /** + * Setup the shading palettes + */ + static void setupPalette(byte palette[32][32], byte val); +public: + /** + * Setup statics + */ + static void setup() { + setupPalette(_palette1, 0xff); + setupPalette(_palette2, 0xe0); + } +public: + OSVideoSurface(CScreenManager *screenManager, DirectDrawSurface *surface); + OSVideoSurface(CScreenManager *screenManager, const CResourceKey &key, bool flag = false); + + /** + * Load the surface with the passed resource + */ + virtual void loadResource(const CResourceKey &key); + + /** + * Loads a Targa image file specified by the resource key + */ + virtual void loadTarga(const CResourceKey &key); + + /** + * Loads a JPEG image file specified by the resource key + */ + virtual void loadJPEG(const CResourceKey &key); + + /** + * Loads a Targa image file specified by the given name + */ + virtual void loadTarga(const CString &name); + + /** + * Loads a movie file specified by the resource key. + * @param key Resource key for movie to load + * @param destroyFlag Immediately destroy movie after decoding first frame + */ + virtual void loadMovie(const CResourceKey &key, bool destroyFlag = false); + + /** + * Lock the surface for direct access to the pixels + */ + virtual bool lock(); + + /** + * Unlocks the surface after prior calls to lock() + */ + virtual void unlock(); + + /** + * Returns true if an underlying raw surface has been set + */ + virtual bool hasSurface(); + + /** + * Returns the width of the surface + */ + virtual int getWidth(); + + /** + * Returns the height of the surface + */ + virtual int getHeight(); + + /** + * Returns the pitch of the surface in bytes + */ + virtual int getPitch(); + + /** + * Returns the bytes per pixel of the surface + */ + virtual int getBpp(); + + /** + * Recreates the surface with the designated size + */ + virtual void recreate(int width, int height); + + /** + * Resizes the surface + */ + virtual void resize(int width, int height); + + /** + * Detachs the underlying raw surface + */ + virtual void detachSurface(); + + /** + * Returns the number of bytes per pixel in the surface + */ + virtual int getPixelDepth(); + + /** + * Gets the pixel at the specified position within the surface + */ + virtual uint16 getPixel(const Point &pt); + + /** + * Sets a pixel at a specified position within the surface + */ + virtual void setPixel(const Point &pt, uint pixel); + + /** + * Change a pixel + */ + virtual void changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag = true); + + /** + * Shifts the colors of the surface.. maybe greys it out? + */ + virtual void shiftColors(); + + /** + * Clears the entire surface to black + */ + virtual void clear(); + + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint flags, CGameObject *obj); + + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj); + + /** + * Plays a movie, loading it from the specified _resource + * if not already loaded + */ + virtual void playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj); + + /** + * Stops any movie currently attached to the surface + */ + virtual void stopMovie(); + + /** + * Sets the movie to the specified frame number + */ + virtual void setMovieFrame(uint frameNumber); + + /** + * Adds a movie playback event + */ + virtual void addMovieEvent(int frameNumber, CGameObject *obj); + + /** + * Set the movie frame rate + */ + virtual void setMovieFrameRate(double rate); + + /** + * Return any movie range info associated with the surface's movie + */ + virtual const CMovieRangeInfoList *getMovieRangeInfo() const; + + /** + * + */ + virtual void flipVertically(bool needsLock = true); + + /** + * Loads the surface's resource if there's one pending + */ + virtual bool loadIfReady(); + + /** + * Loads the surface data based on the currently set resource key + */ + virtual bool load(); + + /** + * Does a replacement of transparent pixels on certain lines at regular + * intervals. This is totally weird + */ + virtual void transPixelate(); + + /** + * Duplicates movie frame surface + */ + virtual Graphics::ManagedSurface *dupMovieFrame() const; + + + /** + * Frees the underlying surface + */ + virtual int freeSurface(); + + /** + * Get a pointer into the underlying surface + */ + virtual uint16 *getBasePtr(int x, int y); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_VIDEO_SURFACE_H */ diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp new file mode 100644 index 0000000000..3a721b6095 --- /dev/null +++ b/engines/titanic/titanic.cpp @@ -0,0 +1,218 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/scummsys.h" +#include "common/archive.h" +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/events.h" +#include "engines/util.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" +#include "titanic/titanic.h" +#include "titanic/debugger.h" +#include "titanic/carry/hose.h" +#include "titanic/core/saveable_object.h" +#include "titanic/game/get_lift_eye2.h" +#include "titanic/game/lemon_dispensor.h" +#include "titanic/game/television.h" +#include "titanic/game/parrot/parrot_lobby_object.h" +#include "titanic/game/sgt/sgt_navigation.h" +#include "titanic/game/sgt/sgt_state_room.h" +#include "titanic/moves/enter_exit_first_class_state.h" +#include "titanic/moves/enter_exit_sec_class_mini_lift.h" +#include "titanic/moves/exit_pellerator.h" +#include "titanic/support/simple_file.h" +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +TitanicEngine *g_vm; + +TitanicEngine::TitanicEngine(OSystem *syst, const TitanicGameDescription *gameDesc) + : _gameDescription(gameDesc), Engine(syst), _randomSource("Titanic") { + g_vm = this; + _debugger = nullptr; + _events = nullptr; + _filesManager = nullptr; + _window = nullptr; + _screen = nullptr; + _screenManager = nullptr; + _scriptHandler = nullptr; + _script = nullptr; + CMusicRoom::_musicHandler = nullptr; +} + +TitanicEngine::~TitanicEngine() { + delete _debugger; + delete _events; + delete _screen; + delete _window; + delete _screenManager; + delete _filesManager; + CSaveableObject::freeClassList(); +} + +void TitanicEngine::initializePath(const Common::FSNode &gamePath) { + Engine::initializePath(gamePath); + SearchMan.addSubDirectoryMatching(gamePath, "assets"); +} + +void TitanicEngine::initialize() { + // Set up debug channels + DebugMan.addDebugChannel(kDebugCore, "core", "Core engine debug level"); + DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); + DebugMan.addDebugChannel(kDebugSound, "sound", "Sound and Music handling"); + + _debugger = new Debugger(this); + _filesManager = new CFilesManager(); + + CSaveableObject::initClassList(); + CEnterExitFirstClassState::init(); + CGameObject::init(); + CGetLiftEye2::init(); + CHose::init(); + CLemonDispensor::init(); + CMovie::init(); + CParrotLobbyObject::init(); + CSGTNavigation::init(); + CSGTStateRoom::init(); + CExitPellerator::init(); + CEnterExitSecClassMiniLift::init(); + CTelevision::init(); + TTnpcScript::init(); + OSVideoSurface::setup(); + + _events = new Events(this); + _screen = new Graphics::Screen(0, 0); + _screenManager = new OSScreenManager(this); + _window = new CMainGameWindow(this); + + setItemNames(); + setRoomNames(); + + _window->applicationStarting(); +} + +void TitanicEngine::deinitialize() { + CEnterExitFirstClassState::deinit(); + CGetLiftEye2::deinit(); + CHose::deinit(); + CMovie::deinit(); + CSGTNavigation::deinit(); + CSGTStateRoom::deinit(); + CExitPellerator::deinit(); + CEnterExitSecClassMiniLift::deinit(); + CGameObject::deinit(); + CTelevision::deinit(); + TTnpcScript::deinit(); +} + +Common::Error TitanicEngine::run() { + initialize(); + + // Main event loop + while (!shouldQuit()) { + _events->pollEventsAndWait(); + } + + deinitialize(); + return Common::kNoError; +} + +void TitanicEngine::setItemNames() { + Common::SeekableReadStream *r; + r = g_vm->_filesManager->getResource("TEXT/ITEM_NAMES"); + while (r->pos() < r->size()) + _itemNames.push_back(readStringFromStream(r)); + delete r; + + r = g_vm->_filesManager->getResource("TEXT/ITEM_DESCRIPTIONS"); + while (r->pos() < r->size()) + _itemNames.push_back(readStringFromStream(r)); + delete r; + + r = g_vm->_filesManager->getResource("TEXT/ITEM_IDS"); + while (r->pos() < r->size()) + _itemIds.push_back(readStringFromStream(r)); + delete r; +} + +void TitanicEngine::setRoomNames() { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource("TEXT/ROOM_NAMES"); + while (r->pos() < r->size()) + _roomNames.push_back(readStringFromStream(r)); + delete r; +} + + +bool TitanicEngine::canLoadGameStateCurrently() { + return _window->_inputAllowed; +} + +bool TitanicEngine::canSaveGameStateCurrently() { + return _window->_inputAllowed; +} + +Common::Error TitanicEngine::loadGameState(int slot) { + _window->_project->loadGame(slot); + return Common::kNoError; +} + +Common::Error TitanicEngine::saveGameState(int slot, const Common::String &desc) { + _window->_project->saveGame(slot, desc); + return Common::kNoError; +} + +CString TitanicEngine::generateSaveName(int slot) { + return CString::format("%s.%03d", _targetName.c_str(), slot); +} + +CString TitanicEngine::getSavegameName(int slot) { + // Try and open up the savegame for access + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading( + generateSaveName(slot)); + + if (in) { + // Read in the savegame header data + CompressedFile file; + file.open(in); + + TitanicSavegameHeader header; + bool isValid = CProjectItem::readSavegameHeader(&file, header); + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + file.close(); + + if (isValid) + // Set the name text + return header._saveName; + } + + return CString(); +} + +} // End of namespace Titanic diff --git a/engines/titanic/titanic.h b/engines/titanic/titanic.h new file mode 100644 index 0000000000..ec015551b8 --- /dev/null +++ b/engines/titanic/titanic.h @@ -0,0 +1,176 @@ +/* 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_TITANIC_H +#define TITANIC_TITANIC_H + +#include "common/scummsys.h" +#include "common/random.h" +#include "common/str-array.h" +#include "common/system.h" +#include "common/serializer.h" +#include "engines/advancedDetector.h" +#include "engines/engine.h" +#include "graphics/screen.h" +#include "titanic/debugger.h" +#include "titanic/events.h" +#include "titanic/support/files_manager.h" +#include "titanic/main_game_window.h" +#include "titanic/support/exe_resources.h" +#include "titanic/support/movie_manager.h" +#include "titanic/support/screen_manager.h" +#include "titanic/support/string.h" +#include "titanic/true_talk/tt_script_base.h" + +/** + * This is the namespace of the Titanic engine. + * + * Status of this engine: In Development + * + * Games using this engine: + * - Starship Titanic + */ +namespace Titanic { + +enum TitanicDebugChannels { + kDebugCore = 1 << 0, + kDebugScripts = 1 << 1, + kDebugGraphics = 1 << 2, + kDebugSound = 1 << 3 +}; + +#define TITANIC_SAVEGAME_VERSION 1 + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define ERROR_BASIC 1 +#define ERROR_INTERMEDIATE 2 +#define ERROR_DETAILED 3 + +#define TOTAL_ITEMS 46 +#define TOTAL_ROOMS 34 + +#define MAX_SAVES 99 + +struct TitanicGameDescription; +class TitanicEngine; + +class TitanicEngine : public Engine { +private: + /** + * Handles basic initialization + */ + void initialize(); + + /** + * Handles game deinitialization + */ + void deinitialize(); + + /** + * Sets up the item names, short, and long descriptions + */ + void setItemNames(); + + /** + * Sets up the list of room names + */ + void setRoomNames(); +protected: + const TitanicGameDescription *_gameDescription; + int _loadSaveSlot; + + // Engine APIs + virtual void initializePath(const Common::FSNode &gamePath); + virtual Common::Error run(); + virtual bool hasFeature(EngineFeature f) const; +public: + Debugger *_debugger; + Events *_events; + CFilesManager *_filesManager; + CMovieManager _movieManager; + Graphics::Screen *_screen; + OSScreenManager *_screenManager; + CMainGameWindow *_window; + Common::RandomSource _randomSource; + CScriptHandler *_scriptHandler; + TTscriptBase *_script; + CTrueTalkManager *_trueTalkManager; + CExeResources _exeResources; + StringArray _itemNames; + StringArray _itemDescriptions; + CString _itemObjects[TOTAL_ITEMS]; + StringArray _itemIds; + StringArray _roomNames; +public: + TitanicEngine(OSystem *syst, const TitanicGameDescription *gameDesc); + virtual ~TitanicEngine(); + + + /** + * Returns true if a savegame can be loaded + */ + virtual bool canLoadGameStateCurrently(); + + /** + * Returns true if the game can be saved + */ + virtual bool canSaveGameStateCurrently(); + + /** + * Called by the GMM to load a savegame + */ + virtual Common::Error loadGameState(int slot); + + /** + * Called by the GMM to save the game + */ + virtual Common::Error saveGameState(int slot, const Common::String &desc); + + uint32 getFeatures() const; + bool isDemo() const; + Common::Language getLanguage() const; + + /** + * Gets a random number + */ + uint getRandomNumber(uint max) { return _randomSource.getRandomNumber(max); } + + /** + * Support method that generates a savegame name + * @param slot Slot number + */ + CString generateSaveName(int slot); + + /** + * Checks whether a savegame exists for the given slot, + * and if it exists, returns it's description + */ + CString getSavegameName(int slot); +}; + +extern TitanicEngine *g_vm; + +} // End of namespace Titanic + +#endif /* TITANIC_TITANIC_H */ diff --git a/engines/titanic/true_talk/barbot_script.cpp b/engines/titanic/true_talk/barbot_script.cpp new file mode 100644 index 0000000000..b327c3647e --- /dev/null +++ b/engines/titanic/true_talk/barbot_script.cpp @@ -0,0 +1,1200 @@ +/* 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/true_talk/barbot_script.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +static const int STATE_ARRAY[7] = { + 0xCAB0, 0xCAB2, 0xCAB3, 0xCAB4, 0xCAB5, 0xCAB6, 0xCAB7 +}; + +static const uint ARRAY1[] = { + 0, 50033, 50044, 50045, 50046, 50047, 50048, 50049, + 50050, 50051, 50034, 50035, 50036, 50037, 50038, 50039, + 50040, 50041, 50042, 50043, 50411, 0 +}; + +static const uint ARRAY2[] = { + 51899, 51900, 51901, 51902, 51903, 51904, 51905, 51906, 51907, 0 +}; + +BarbotScript::BarbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, v4, v5, v6, v7) { + _state = 0; + _arrIndex = 0; + + loadRanges("Ranges/Barbot"); + loadResponses("Responses/Barbot"); + setupSentences(); + _tagMappings.load("TagMap/Barbot"); + _quotes.load("Quotes/Barbot"); + _states.load("States/Barbot"); + _preResponses.load("PreResponses/Barbot"); +} + +void BarbotScript::setupSentences() { + for (int idx = 28; idx < 35; ++idx) + CTrueTalkManager::setFlags(idx, 0); + setupDials(100, 100, 100); + + if (!_currentDialNum) + _currentDialNum = 2; + + _mappings.load("Mappings/Barbot", 8); + _entries.load("Sentences/Barbot"); + _entries2.load("Sentences/Barbot2"); + _words.load("Words/Barbot"); +} + +int BarbotScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + if (tag == MKTAG('D', 'N', 'A', '1') || tag == MKTAG('H', 'H', 'G', 'Q') || + tag == MKTAG('A', 'N', 'S', 'W') || tag == MKTAG('S', 'U', 'M', 'S')) { + if (_state < 7) { + addResponse(STATE_ARRAY[_state++]); + } else { + selectResponse(51896); + setState(1); + _state = 0; + } + + applyResponse(); + return 2; + + } else if (tag == MKTAG('S', 'W', 'E', 'R')) { + adjustDial(0, -18); + adjustDial(1, -5); + + if (getRandomNumber(100) > 50) { + addResponse(getDialogueId(getDialRegion(0) == 0 ? 250200 : 250062)); + applyResponse(); + return 2; + } + + } else if (tag == MKTAG('B', 'A', 'R', 'K') && getRandomNumber(100) > 50) { + selectResponse(250025); + switch (getDialsBitset()) { + case 4: + case 6: + addResponse(getDialogueId(250125)); + break; + default: + break; + } + + applyResponse(); + return 2; + + } else if (tag == MKTAG('B', 'A', 'R', 'U') && getRandomNumber(100) > 50) { + selectResponse(250025); + switch (getDialsBitset()) { + case 4: + case 6: + addResponse(getDialogueId(250112)); + break; + default: + break; + } + + applyResponse(); + return 2; + } + + if (tag == MKTAG('T', 'H', 'R', 'T') || tag == MKTAG('S', 'L', 'O', 'W') || + tag == MKTAG('S', 'E', 'X', '1') || tag == MKTAG('P', 'K', 'U', 'P')) { + adjustDial(0, -7); + adjustDial(1, -3); + } + + return TTnpcScript::chooseResponse(roomScript, sentence, tag); +} + +int BarbotScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + int dialogueId = 0; + + if (roomScript->_scriptId != 112) + return 2; + + checkItems(roomScript, sentence); + if (isState9()) { + if (sentence->localWord("visioncenter") || sentence->localWord("brain") || + sentence->contains("vision") || sentence->contains("visual") || + sentence->contains("brain") || sentence->contains("crystal")) { + if (CTrueTalkManager::getStateValue(2)) { + addResponse(getDialogueId(251003)); + applyResponse(); + CTrueTalkManager::triggerAction(6, 0); + return 2; + } + } + + if (sentence->contains("goldfish")) { + addResponse(getDialogueId(250184)); + applyResponse(); + return 2; + } + + dialogueId = ARRAY1[getRandomNumber(20)]; + if (!ARRAY2[_arrIndex]) + _arrIndex = 0; + + if (_arrIndex) { + dialogueId = ARRAY2[_arrIndex++]; + } else if (getRandomNumber(100) > 35) { + dialogueId = ARRAY2[0]; + _arrIndex = 1; + } else if (getRandomNumber(100) > 60) { + switch (sentence->_field2C) { + case 2: + dialogueId = 51914; + break; + case 3: + dialogueId = 51911; + break; + case 4: + dialogueId = 51913; + break; + case 5: + dialogueId = 51912; + break; + case 6: + dialogueId = 51915; + break; + case 7: + dialogueId = 51909; + break; + default: + break; + } + } + + addResponse(dialogueId); + if (getRandomNumber(100) > 65) + addResponse(getDialogueId(251250)); + applyResponse(); + return 2; + } + + CTrueTalkManager::setFlags(29, getValue(29) - 1); + CTrueTalkManager::setFlags(30, getValue(30) - 1); + CTrueTalkManager::setFlags(31, getValue(31) - 1); + CTrueTalkManager::setFlags(32, getValue(32) - 1); + CTrueTalkManager::setFlags(33, getValue(33) - 1); + CTrueTalkManager::setFlags(34, getValue(34) - 1); + + TTtreeResult treeResult; + int val34 = getState(); + setState(0); + + int val2C = sentence->_field2C; + bool flag = val2C == 11 || val2C == 13; + bool flag2 = val2C == 12; + + if (!val34) { + goto done; + } else if (val34 > 50357) { + goto done; + } else if (val34 == 50357) { + return applySentenceIds(50358, -1); + } + + switch (val34) { + case 1: + if (flag) + return applySentenceIds(51898, 2); + if (flag2) + return applySentenceIds(51897); + break; + case 2: + if (flag) + return applySentenceIds(51897); + break; + case 3: + if (sentence->localWord("useless") || sentence->contains("useless")) + return applySentenceIds(50824); + break; + case 4: + if (flag) + return applySentenceIds(getRandomBit() ? 50512 : 51642); + else if (flag2) + return applySentenceIds(getRandomBit() ? 50511 : 51643); + break; + case 5: + if (flag) + return applySentenceIds(50829, 6); + if (flag2) + return applySentenceIds(50828); + break; + case 6: + if (flag) + return applySentenceIds(50831); + if (flag2) + return applySentenceIds(50830); + break; + case 7: + if (flag2 || sentence->contains("never")) + return applySentenceIds(51553); + if (flag || sentence->contains("nicest")) + return applySentenceIds(51554); + break; + case 8: + if (flag) + return applySentenceIds(50961); + if (flag2) + return applySentenceIds(50960); + break; + case 9: + if (flag) + return applySentenceIds(getDialogueId(251858)); + break; + case 10: + if (flag) + return applySentenceIds(getDialogueId(251014)); + else if (flag2) + return applySentenceIds(getDialogueId(251013)); + break; + case 11: + if (flag) + return applySentenceIds(getDialogueId(251008)); + else if (flag2) + return applySentenceIds(getDialogueId(251007)); + break; + case 12: + if (flag) + return applySentenceIds(getDialogueId(250656)); + else if (flag2) + return applySentenceIds(getDialogueId(250655)); + break; + case 13: + if (flag) + return applySentenceIds(getDialogueId(250614)); + else if (flag2) + return applySentenceIds(getDialogueId(250613)); + break; + case 14: + if (val2C == 6) + return applySentenceIds(getDialogueId(250946)); + break; + case 15: + if (flag || sentence->contains("or")) { + return applySentenceIds(getDialogueId(250526), 16); + } else { + if (g_vm->_trueTalkManager->_quotesTree.search( + sentence->_normalizedLine.c_str(), TREE_3, &treeResult, 0, nullptr) != -1) { + uint newId = getDialogueId(250526); + return applySentenceIds(newId, 16); + } + } + break; + case 17: + if (flag) { + return applySentenceIds(50382); + } else if (flag2) { + return applySentenceIds(51423); + } + // Deliberate fall-through + + case 16: + if (val2C == 7 || val2C == 10) + return applySentenceIds(getDialogueId(250525)); + break; + case 18: + return applySentenceIds(getDialogueId(250589)); + case 19: + return applySentenceIds(getDialogueId(250565), 20); + case 20: + if (flag) + return applySentenceIds(50307); + if (flag2) + return applySentenceIds(50306); + break; + case 21: + if (flag) + return applySentenceIds(50359); + if (flag2) + return applySentenceIds(50357); + break; + case 23: + if (val2C == 6 || val2C == 10) + return applySentenceIds(getDialogueId(250551)); + break; + case 24: + if (sentence->contains("do not know") + || sentence->contains("no idea") + || sentence->contains("a clue")) { + return applySentenceIds(getDialogueId(250553)); + } else { + return applySentenceIds(getDialogueId(250552)); + } + break; + case 25: + if (flag || val2C == 10) + applySentenceIds(getDialogueId(251899), 26); + else if (flag2) + return applySentenceIds(50215); + break; + case 26: + if (g_vm->_trueTalkManager->_quotesTree.search( + sentence->_normalizedLine.c_str(), TREE_3, &treeResult, 0, nullptr) != -1) + return applySentenceIds(getDialogueId(251899), 26); + break; + + case 27: + if (flag) + return applySentenceIds(getDialogueId(250766)); + else if (flag2) + return applySentenceIds(getDialogueId(250764)); + break; + case 28: + return applySentenceIds(getDialogueId(250765)); + case 29: + return applySentenceIds(getDialogueId(250652)); + case 30: + return applySentenceIds(getDialogueId(250653)); + case 31: + if (flag) + return applySentenceIds(getDialogueId(250664)); + else if (flag2) + return applySentenceIds(getDialogueId(250663)); + break; + case 32: + if (flag) + return applySentenceIds(getDialogueId(250643)); + else if (flag2) + return applySentenceIds(getDialogueId(250642)); + break; + case 33: + return applySentenceIds(50763); + case 34: + if (flag) + return applySentenceIds(getDialogueId(251622)); + else if (flag2) + return applySentenceIds(getDialogueId(251624)); + break; + case 35: + if (val2C == 6 || val2C == 10) + return applySentenceIds(getDialogueId(251623)); + break; + case 36: + if (flag) + return applySentenceIds(50335); + if (flag2) + return applySentenceIds(50334); + break; + case 37: + if (flag) + return applySentenceIds(50217); + if (flag2) + return applySentenceIds(50153); + break; + case 38: + return applySentenceIds(getDialogueId(250637)); + case 39: + return applySentenceIds(getDialogueId(250638)); + case 40: + return applySentenceIds(getDialogueId(250639)); + case 41: + return applySentenceIds(getDialogueId(250640)); + case 42: + if (flag) + return applySentenceIds(getDialogueId(250676)); + else if (flag2) + return applySentenceIds(getDialogueId(250673)); + break; + case 43: + if (flag) + return applySentenceIds(50416, -1); + if (flag2) + return applySentenceIds(50415, -1); + break; + case 44: + if (flag) + return applySentenceIds(getDialogueId(250468)); + else if (flag2) + return applySentenceIds(getDialogueId(250413)); + + if (val2C == 6 || val2C == 10) + return applySentenceIds(getDialogueId(251649)); + break; + case 45: + if (sentence->localWord("summer") + || sentence->contains("summer") + || sentence->localWord("autumn") + || sentence->contains("autumn")) { + return applySentenceIds(50743); + } else if (sentence->localWord("winter") || sentence->contains("winter")) { + return applySentenceIds(50696); + } else { + return applySentenceIds(50225); + } + break; + case 46: + if (val2C == 7 || val2C == 10) + return applySentenceIds(50698); + break; + case 47: + if (flag || flag2 || val2C == 6) + return applySentenceIds(50717); + break; + case 48: + if (flag) + return applySentenceIds(50710); + if (flag2) + return applySentenceIds(50225); + break; + case 49: + if (sentence->localWord("scraliontis") || sentence->contains("scraliontis")) + return applySentenceIds(50711); + if (sentence->localWord("brobostigon") || sentence->contains("brobostigon")) + return applySentenceIds(50712); + break; + case 50: + return applySentenceIds(50713); + case 51: + if (flag) + return applySentenceIds(50715); + if (flag2) + return applySentenceIds(50714); + break; + case 52: + if (sentence->localWord("note") || sentence->contains("note")) + return applySentenceIds(50716); + return applySentenceIds(50210); + case 53: + return applySentenceIds(50210); + case 54: + if (getDialRegion(0) != 0) { + if (val2C == 12) + return applySentenceIds(50174); + else + return applySentenceIds(50300); + } else if (val2C == 7 || val2C == 10) { + return applySentenceIds(50871); + } + break; + case 55: + if (flag) + return applySentenceIds(50302); + if (flag2) + return applySentenceIds(50301); + break; + case 56: + if (flag) + return applySentenceIds(50304); + if (flag2) + return applySentenceIds(50303); + break; + case 57: + if (sentence->localWord("mustard") + || sentence->contains("mustard") + || sentence->localWord("tomato") + || sentence->contains("tomato")) + return applySentenceIds(50320); + if (sentence->localWord("sauce") + || sentence->localWord("puree") + || sentence->contains("sauce") + || sentence->contains("puree") + || sentence->contains("bird") + || sentence->contains("starling")) { + applySentenceIds(50321); + CTrueTalkManager::triggerAction(30, 0); + return 2; + } + + return applySentenceIds(50320); + case 58: + if (val2C == 6 || val2C == 10) + return applySentenceIds(50880); + break; + case 59: + if (flag) { + if (addRandomResponse(true)) { + setState(59); + return 2; + } + } else if (flag2) { + return applySentenceIds(getDialogueId(251754)); + } + break; + case 60: + if (flag && addRandomResponse(true)) { + setState(59); + return 2; + } else if (flag2 || val2C == 7 || val2C == 10) { + return applySentenceIds(getDialogueId(251712)); + } + break; + case 61: + if (val2C == 3) { + if (sentence->localWord("loop")) + return applySentenceIds(getDialogueId(250269)); + else if (sentence->localWord("do")) + return applySentenceIds(getDialogueId(250270)); + } else if (val2C == 7) { + return applySentenceIds(getDialogueId(250270)); + } else if (flag) { + return applySentenceIds(getDialogueId(250270)); + } + + return applySentenceIds(getDialogueId(250272)); + case 62: + if (flag + || (val2C == 3 && sentence->localWord("do")) + || val2C == 7 + || sentence->localWord("help")) + return applySentenceIds(getDialogueId(250270)); + + return applySentenceIds(getDialogueId(2570272)); + case 63: + if (flag + || (val2C == 3 || sentence->localWord("do")) + || val2C == 7 + || sentence->localWord("help")) + return applySentenceIds(getDialogueId(250271)); + + return applySentenceIds(getDialogueId(250272)); + case 64: + if (flag || val2C == 3 || val2C == 8) + return applySentenceIds(getDialogueId(250631)); + break; + case 65: + if (sentence->localWord("now") || sentence->localWord("soonh")) + return applySentenceIds(getDialogueId(250424)); + return applySentenceIds(getDialogueId(250506)); + case 66: + if (flag || sentence->localWord("good") || sentence->localWord("well")) + return applySentenceIds(getDialogueId(251027)); + return applySentenceIds(getDialogueId(251021)); + case 67: + if (flag || val2C == 6 || val2C == 10) { + setDial(0, getDialLevel(0, false) - 8); + return applySentenceIds(getDialogueId(251589)); + } + break; + case 68: + if (flag || val2C == 6 || val2C == 10) { + setDial(0, getDialLevel(0, false) - 12); + return applySentenceIds(getDialogueId(251590)); + } + break; + case 69: + if (flag || val2C == 6 || val2C == 10) { + setDial(0, getDialLevel(0, false) - 25); + return applySentenceIds(getDialogueId(251591)); + } + break; + default: + break; + } + +done: + // Adjust primary dial + setState(0); + if (sentence->get58() != 5) { + adjustDial(0, sentence->get58() * 4 - 20); + } else if (getDialLevel(0, false) > 65) { + adjustDial(0, -2 - getRandomNumber(7)); + } else if (getDialLevel(0, false) < 35) { + adjustDial(0, 2 + getRandomNumber(7)); + } + + updateCurrentDial(true); + + if (sentence->contains("goldfish")) { + addResponse(250184); + } else if ((sentence->localWord("puree") || sentence->localWord("pureed")) + && sentence->localWord("parrot")) { + addResponse(250021); + } else if (sentence->localWord("starling")) { + addResponse(250024); + } else { + if (getRandomNumber(100) > 95 && getDialRegion(2) == 0) { + addResponse(getDialogueId(250210)); + } + + if (processEntries(&_entries, _entryCount, roomScript, sentence) == 2) + return 2; + if (processEntries(_defaultEntries, 0, roomScript, sentence) != 2 + && !defaultProcess(roomScript, sentence)) { + int dval = 0; + flag = getRandomNumber(100) > 50; + int val; + + switch (_field2C) { + case 2: + val = getValue(29); + if (val < 16) + val += 4; + if (val < 9) { + val = val / 2; + dval = 250081 + (flag ? 0 : 267); + } + CTrueTalkManager::setFlags(29, val); + break; + + case 3: + val = getValue(30); + if (val < 16) + val += 4; + if (val < 9) { + val = val / 2; + dval = 250081 + (flag ? 0 : 243); + } + CTrueTalkManager::setFlags(30, val); + break; + + case 4: + val = getValue(31); + if (val < 16) + val += 4; + if (val < 9) { + val = val / 2; + dval = 250081 + (flag ? 0 : 256); + } + CTrueTalkManager::setFlags(31, val); + break; + + case 5: + val = getValue(32); + if (val < 16) + val += 4; + if (val < 9) { + val = val / 2; + dval = 250081 + (flag ? 0 : 251); + } + CTrueTalkManager::setFlags(32, val); + break; + + case 6: + val = getValue(33); + if (val < 16) + val += 4; + if (val < 9) { + val = val / 2; + dval = 250081 + (flag ? 0 : 273); + } + CTrueTalkManager::setFlags(33, val); + break; + + case 7: + val = getValue(34); + if (val < 16) + val += 4; + if (val < 9) { + val = val / 2; + dval = 250081 + (flag ? 0 : 236); + } + CTrueTalkManager::setFlags(34, val); + break; + + + case 11: + addResponse(getDialogueId(250463)); + applyResponse(); + return 2; + + case 12: + addResponse(getDialogueId(250455)); + applyResponse(); + return 2; + + case 13: + addResponse(getDialogueId(250447)); + applyResponse(); + return 2; + + case 19: + return applySentenceIds(getDialogueId(getDialRegion(0) ? 250062 : 250200)); + + default: + break; + } + + if (dval) { + adjustDial(0, -9); + adjustDial(1, -2); + + if (dval != 250081) { + selectResponse(250286); + selectResponse(250296); + selectResponse(250307); + applyResponse(); + return 2; + } + } else if (processEntries(&_entries2, 0, roomScript, sentence) == 2) { + return 2; + } + + addResponse(getDialogueId(250082 + getRandomNumber(100) <= 89 ? 128 : 0)); + } + } + + applyResponse(); + return 2; +} + +ScriptChangedResult BarbotScript::scriptChanged(const TTroomScript *roomScript, uint id) { + switch (id) { + case 1: + case 100: + if (!isState9()) { + selectResponse(250210); + applyResponse(); + } + + adjustDial(0, getRandomBit() ? getRandomNumber(5) * 4 : + -(int)getRandomNumber(5) * 4); + break; + + case 3: + if (isState9()) { + selectResponse(250244); + applyResponse(); + resetFlags(); + } else { + if (!getValue(28) || !fn10(true)) { + addResponse(getDialogueId(251627 + getValue(28) ? -1034 : 0)); + applyResponse(); + } + + CTrueTalkManager::setFlags(28, 1); + resetFlags(); + } + break; + + case 4: + selectResponse(isState9() ? 250141 : 250140); + applyResponse(); + adjustDial(2, getDialLevel(2, false) < 50 ? -15 - getRandomNumber(30) : + 15 + getRandomNumber(30)); + + if (getDialRegion(1) != 0 && getRandomNumber(100) > 75) + adjustDial(1, -35); + break; + + case 143: + addResponse(getDialogueId(isState9() ? 250577 : 250576)); + break; + + case 144: + addResponse(getDialogueId(isState9() ? 250577 : 250584)); + break; + + case 145: + if (isState9()) { + addResponse(getDialogueId(250577)); + applyResponse(); + } else { + setState(57); + } + break; + + case 146: + addResponse(getDialogueId(isState9() ? 250577 : 250574)); + break; + + case 147: + addResponse(getDialogueId(250579)); + break; + + } + + if (id >= 250000 && id <= 251900) { + if (id > 250571) { + if (id != 250575 && (id == 250586 || id == 251858 || !isState9())) { + addResponse(getDialogueId(id)); + applyResponse(); + } + } else if (id == 250571 || (id != 250244 && !isState9()) || isState9()) { + addResponse(getDialogueId(id)); + applyResponse(); + } else { + addResponse(getDialogueId(251018)); + applyResponse(); + } + } + + return SCR_2; +} + +int BarbotScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + switch (tagId) { + case MKTAG('A', 'D', 'V', 'T'): + case MKTAG('A', 'R', 'T', 'I'): + case MKTAG('A', 'R', 'T', 'Y'): + case MKTAG('B', 'R', 'N', 'D'): + case MKTAG('C', 'O', 'M', 'D'): + case MKTAG('D', 'N', 'C', 'E'): + case MKTAG('H', 'B', 'B', 'Y'): + case MKTAG('M', 'A', 'G', 'S'): + case MKTAG('L', 'I', 'T', 'R'): + case MKTAG('M', 'C', 'P', 'Y'): + case MKTAG('M', 'I', 'N', 'S'): + case MKTAG('M', 'U', 'S', 'I'): + case MKTAG('N', 'I', 'K', 'E'): + case MKTAG('S', 'F', 'S', 'F'): + case MKTAG('S', 'O', 'A', 'P'): + case MKTAG('S', 'O', 'N', 'G'): + case MKTAG('S', 'P', 'R', 'T'): + case MKTAG('T', 'E', 'A', 'M'): + case MKTAG('T', 'U', 'S', 'H'): + case MKTAG('W', 'W', 'E', 'B'): + tagId = MKTAG('E', 'N', 'T', 'N'); + break; + case MKTAG('A', 'U', 'T', 'H'): + case MKTAG('B', 'A', 'R', 'K'): + case MKTAG('B', 'L', 'R', '1'): + case MKTAG('B', 'L', 'P', '1'): + case MKTAG('B', 'L', 'P', '2'): + case MKTAG('B', 'L', 'P', '3'): + case MKTAG('B', 'L', 'P', '4'): + case MKTAG('B', 'L', 'T', '1'): + case MKTAG('B', 'L', 'T', '2'): + case MKTAG('B', 'L', 'T', '3'): + case MKTAG('B', 'L', 'T', '4'): + case MKTAG('B', 'L', 'T', '5'): + case MKTAG('B', 'O', 'Y', 'S'): + case MKTAG('C', 'O', 'P', 'S'): + case MKTAG('D', 'C', 'T', 'R'): + case MKTAG('F', 'A', 'M', 'E'): + case MKTAG('F', 'A', 'S', 'H'): + case MKTAG('G', 'I', 'R', 'L'): + case MKTAG('H', 'E', 'R', 'O'): + case MKTAG('H', 'O', 'S', 'T'): + case MKTAG('K', 'N', 'O', 'B'): + case MKTAG('N', 'H', 'R', 'O'): + case MKTAG('R', 'A', 'C', 'E'): + case MKTAG('S', 'C', 'I', 'T'): + case MKTAG('T', 'D', 'V', 'P'): + case MKTAG('T', 'W', 'A', 'T'): + case MKTAG('W', 'E', 'A', 'T'): + tagId = MKTAG('P', 'R', 'S', 'N'); + break; + case MKTAG('C', 'H', 'S', 'E'): + case MKTAG('C', 'M', 'N', 'T'): + case MKTAG('F', 'I', 'L', 'M'): + case MKTAG('J', 'F', 'O', 'D'): + case MKTAG('L', 'I', 'Q', 'D'): + tagId = MKTAG('F', 'O', 'O', 'D'); + break; + case MKTAG('C', 'R', 'M', 'N'): + case MKTAG('C', 'S', 'P', 'Y'): + case MKTAG('U', 'B', 'A', 'D'): + tagId = MKTAG('V', 'B', 'A', 'D'); + break; + case MKTAG('E', 'A', 'R', 'T'): + case MKTAG('H', 'O', 'M', 'E'): + case MKTAG('N', 'P', 'L', 'C'): + case MKTAG('P', 'L', 'A', 'C'): + case MKTAG('P', 'L', 'A', 'N'): + tagId = MKTAG('P', 'L', 'A', 'C'); + break; + case MKTAG('F', 'A', 'U', 'N'): + case MKTAG('F', 'I', 'S', 'H'): + case MKTAG('F', 'L', 'O', 'R'): + tagId = MKTAG('N', 'A', 'T', 'R'); + break; + case MKTAG('H', 'H', 'L', 'D'): + case MKTAG('T', 'O', 'Y', 'S'): + case MKTAG('W', 'E', 'A', 'P'): + tagId = MKTAG('M', 'A', 'C', 'H'); + break; + case MKTAG('M', 'L', 'T', 'Y'): + case MKTAG('P', 'G', 'R', 'P'): + case MKTAG('P', 'T', 'I', 'C'): + tagId = MKTAG('G', 'R', 'U', 'P'); + break; + case MKTAG('P', 'K', 'U', 'P'): + case MKTAG('S', 'E', 'X', '1'): + case MKTAG('S', 'W', 'E', 'R'): + tagId = MKTAG('R', 'U', 'D', 'E'); + break; + case MKTAG('P', 'H', 'I', 'L'): + case MKTAG('R', 'C', 'K', 'T'): + case MKTAG('S', 'C', 'I', 'E'): + tagId = MKTAG('S', 'C', 'I', 'E'); + break; + case MKTAG('T', 'R', 'A', '2'): + case MKTAG('T', 'R', 'A', '3'): + tagId = MKTAG('T', 'R', 'A', 'V'); + break; + default: + break; + } + + if (val == 36) { + switch (getValue(1)) { + case 1: + return setResponse(getDialogueId(220837), -1); + break; + case 2: + return setResponse(getDialogueId(220849), -1); + default: + return setResponse(getDialogueId(220858), -1); + } + } else if (val == 61 && getValue(1) > 2) { + return setResponse(getDialogueId(222301), -1); + } + + return TTnpcScript::handleQuote(roomScript, sentence, val, tagId, remainder); +} + +int BarbotScript::updateState(uint oldId, uint newId, int index) { + if (newId == 250538) { + CTrueTalkManager::triggerAction(28, 0); + return 250538; + } + if (newId == 251704) { + return 251701 + (_field7C ? 3 : 0); + } + + for (uint idx = 0; idx < _states.size(); ++idx) { + const TTupdateState &us = _states[idx]; + if (us._newId == newId) { + if ((us._dialBits & 1) && !getDialRegion(0)) + continue; + if ((us._dialBits & 2) && getDialRegion(0)) + continue; + if ((us._dialBits & 4) && !getDialRegion(1)) + continue; + if ((us._dialBits & 8) && getDialRegion(1)) + continue; + if ((us._dialBits & 0x10) && !getDialRegion(2)) + continue; + if ((us._dialBits & 0x20) && getDialRegion(2)) + continue; + + setState(us._newValue); + break; + } + } + + return newId; +} + +int BarbotScript::preResponse(uint id) { + if (getDialRegion(0) == 0 && getRandomNumber(100) > 80) + return 251250; + + return _preResponses.find(id); +} + +uint BarbotScript::getDialsBitset() const { + uint bits = 0; + if (!getDialRegion(0)) + bits = 1; + if (!getDialRegion(1)) + bits |= 2; + if (!getDialRegion(2)) + bits |= 4; + + return bits; +} + +int BarbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + int v34 = getState(); + uint id = 0; + + if (v34 > 0x200) { + switch (v34 - 0x201) { + case 0: + if (getValue(4) != 2) + id = 250738; + break; + case 1: + if (getValue(4) != 3) + id = 250738; + case 2: + if (getValue(4) != 0) + id = 250738; + break; + default: + break; + } + } else if (v34 == 0x200) { + if (getValue(4) != 1) + id = 250738; + } else { + switch (v34) { + case 2: + if (getValue(1) != 1) + return 1; + break; + case 3: + if (getValue(1) != 2) + return 1; + break; + case 4: + if (getValue(1) != 3) + return 1; + break; + case 5: + if (getValue(1) == 3) + return 1; + break; + case 6: + if (sentence->contains("do not") || sentence->contains("have no") || + sentence->contains("got no")) + return 1; + break; + case 7: + if (!sentence->contains("do not") && !sentence->contains("have no") && + !sentence->contains("got no")) + return 1; + break; + case 8: + if (sentence->_field38 == 2) + return 1; + break; + case 9: { + uint val = CTrueTalkManager::getStateValue(3); + bool bit0 = (val & 1) != 0; + bool bit2 = (val & 4) != 0; + bool bit3 = (val & 8) != 0; + + if (bit2) { + if (!bit0) { + id = 250085 - (bit3 ? 0 : 199715); + break; + } else if (!bit3) { + id = 250627; + } + } else { + if (!bit0) { + id = 50365 + (bit3 ? 0 : 2); + } else if (!bit3) { + id = 50370; + } + } + + if (id) { + addResponse(getDialogueId(id)); + applyResponse(); + return 2; + } + break; + } + + case 10: { + uint val = CTrueTalkManager::getStateValue(3); + bool bit0 = (val & 1) != 0; + bool bit2 = (val & 4) != 0; + bool bit3 = (val & 8) != 0; + + if (bit0 && bit2 && bit3) { + addResponse(getDialogueId(251027)); + applyResponse(); + CTrueTalkManager::triggerAction(7, 0); + return 2; + } else { + if (getDialRegion(1) == 1) { + if (*srcIdP != 251650) + id = 251651; + } else { + addResponse(getDialRegion(0) != 0 ? 51444 : 51530); + applyResponse(); + return 2; + } + } + break; + } + + case 11: + if (CTrueTalkManager::getStateValue(2) != 0) { + CTrueTalkManager::triggerAction(6, 0); + id = 251003; + } + break; + + case 12: + if (getDialRegion(1) == 0) { + addResponse(getDialogueId(251871)); + applyResponse(); + return 2; + } else if (getRandomNumber(100) > 25 && addRandomResponse(false)) { + return 2; + } + + default: + break; + } + } + + if (id) { + addResponse(getDialogueId(id)); + applyResponse(); + } + + return 2; +} + +void BarbotScript::setDialRegion(int dialNum, int region) { + TTnpcScript::setDialRegion(dialNum, region); + selectResponse(250365); + applyResponse(); +} + +void BarbotScript::adjustDial(int dialNum, int amount) { + int level = CLIP(getDialLevel(dialNum) + amount, 0, 100); + setDial(dialNum, level); +} + +bool BarbotScript::isState9() const { + return CTrueTalkManager::getStateValue(9) != 0; +} + +int BarbotScript::applySentenceIds(int dialogueId, int v34) { + addResponse(dialogueId); + applyResponse(); + + if (v34 != -1) { + setState(v34); + } else { + for (uint idx = 0; idx < _mappings.size(); ++idx) { + const TTscriptMapping &m = _mappings[idx]; + for (int vidx = 0; vidx < _mappings._valuesPerMapping; ++idx) { + if (m._values[vidx] == (uint)dialogueId) { + updateState(m._id, m._id, vidx); + break; + } + } + } + } + + return -2; +} + +int BarbotScript::setResponse(int dialogueId, int state) { + addResponse(dialogueId); + applyResponse(); + + if (state != -1) + setState(state); + return 2; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/barbot_script.h b/engines/titanic/true_talk/barbot_script.h new file mode 100644 index 0000000000..1820d77216 --- /dev/null +++ b/engines/titanic/true_talk/barbot_script.h @@ -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. + * + */ + +#ifndef TITANIC_BARBOT_SCRIPT_H +#define TITANIC_BARBOT_SCRIPT_H + +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class BarbotScript : public TTnpcScript { +private: + int _state; + int _arrIndex; + TTsentenceEntries _entries2; + TTupdateStateArray _states; + TTmapEntryArray _preResponses; +private: + /** + * Adjust a given dial number by a given delta amount + */ + void adjustDial(int dialNum, int amount); + + /** + * Setup sentence data + */ + void setupSentences(); + + bool isState9() const; + + int applySentenceIds(int dialogueId, int v34 = -1); + + /** + * Add a response and optionally set the state + */ + int setResponse(int dialogueId, int state = -1); +public: + BarbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); + + /** + * Returns a bitset of the first three dialgs being on or not + */ + virtual uint getDialsBitset() const; + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Sets a given dial to be pointing in a specified region (0 to 2) + */ + virtual void setDialRegion(int dialNum, int region); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_BARBOT_SCRIPT_H */ diff --git a/engines/titanic/true_talk/bellbot_script.cpp b/engines/titanic/true_talk/bellbot_script.cpp new file mode 100644 index 0000000000..7da2ab6201 --- /dev/null +++ b/engines/titanic/true_talk/bellbot_script.cpp @@ -0,0 +1,1905 @@ +/* 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/true_talk/bellbot_script.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/core/node_item.h" +#include "titanic/titanic.h" + +namespace Titanic { + +uint BellbotScript::_oldId; + +static const RoomDialogueId ROOM_DIALOGUE_IDS[] = { + { 100, 201442 },{ 101, 201417 },{ 107, 201491 },{ 108, 201421 }, + { 109, 201437 },{ 110, 201431 },{ 111, 201457 },{ 112, 201411 }, + { 113, 201424 },{ 114, 201464 },{ 115, 201407 },{ 116, 201468 }, + { 117, 201447 },{ 122, 201491 },{ 123, 201299 },{ 124, 201479 }, + { 125, 201480 },{ 126, 201476 },{ 127, 201483 },{ 128, 201399 }, + { 129, 201400 },{ 130, 201387 },{ 131, 201395 },{ 132, 201388 }, + { 0, 0 } +}; + +BellbotScript::BellbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, -1, -1, -1, 0), + _field2D0(0), _field2D4(0), _field2D8(0), _field2DC(0), + _room107First(false) { + CTrueTalkManager::setFlags(25, 0); + CTrueTalkManager::setFlags(24, 0); + CTrueTalkManager::setFlags(40, 0); + CTrueTalkManager::setFlags(26, 0); + + setupDials(0, 0, 0); + _array[0] = 100; + _array[1] = 0; + + loadRanges("Ranges/Bellbot"); + loadResponses("Responses/Bellbot", 4); + setupSentences(); + _tagMappings.load("TagMap/Bellbot"); + _words.load("Words/Bellbot"); + _quotes.load("Quotes/Bellbot"); + _states.load("States/Bellbot"); + _preResponses.load("PreResponses/Bellbot"); + _phrases.load("Phrases/Bellbot"); +} + +void BellbotScript::setupSentences() { + _mappings.load("Mappings/Bellbot", 1); + _entries.load("Sentences/Bellbot"); + for (int idx = 1; idx < 20; ++idx) + _sentences[idx].load(CString::format("Sentences/Bellbot/%d", idx)); + + _field2DC = 0; + _field68 = 0; + _entryCount = 0; +} + +int BellbotScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + int val24 = getValue(24); + CTrueTalkManager::setFlags(24, 0); + + int result = preprocess(roomScript, sentence); + if (result != 1) + return 1; + + CTrueTalkManager::setFlags(23, 0); + setState(0); + if (getValue(1) <= 2) + updateCurrentDial(1); + + // Handle room specific sentences + switch (roomScript->_scriptId) { + case 101: + if (getValue(2) == 1) { + result = processEntries(&_sentences[11], 0, roomScript, sentence); + } + break; + + case 107: + result = processEntries(&_sentences[5], 0, roomScript, sentence); + break; + + case 108: + result = processEntries(&_sentences[7], 0, roomScript, sentence); + break; + + case 109: + result = processEntries(&_sentences[13], 0, roomScript, sentence); + break; + + case 110: + result = processEntries(&_sentences[16], 0, roomScript, sentence); + break; + + case 111: + result = processEntries(&_sentences[10], 0, roomScript, sentence); + break; + + case 112: + result = processEntries(&_sentences[15], 0, roomScript, sentence); + break; + + case 113: + result = processEntries(&_sentences[9], 0, roomScript, sentence); + break; + + case 114: + result = processEntries(&_sentences[18], 0, roomScript, sentence); + break; + + case 115: + result = processEntries(&_sentences[12], 0, roomScript, sentence); + break; + + case 116: + result = processEntries(&_sentences[8], 0, roomScript, sentence); + break; + + case 117: + result = processEntries(&_sentences[6], 0, roomScript, sentence); + break; + + case 123: + result = processEntries(&_sentences[17], 0, roomScript, sentence); + break; + + case 125: + result = processEntries(&_sentences[14], 0, roomScript, sentence); + break; + + case 131: + if (getValue(26) == 0) { + result = processEntries(&_sentences[getValue(6) ? 5 : 4], 0, roomScript, sentence); + } + break; + } + + if (result == 2) + return 2; + if (sentence->contains("pretend you summoned yourself") || + sentence->contains("pretend you just summoned yourself")) { + if (scriptChanged(roomScript, 157) == 2) + return 2; + } + + if (sentence->localWord("television") || roomScript->_scriptId == 111) { + if (sentence->localWord("drop") || sentence->localWord("throw") + || sentence->localWord("smash") || sentence->localWord("destroy") + || sentence->localWord("toss") || sentence->localWord("put") + || sentence->localWord("pitch") || sentence->localWord("heft")) { + if (getValue(40) == 1) { + addResponse(getDialogueId(201687)); + applyResponse(); + return 2; + } + else if (roomScript->_scriptId == 111) { + addResponse(getDialogueId(201687)); + applyResponse(); + CTrueTalkManager::triggerAction(17, 0); + CTrueTalkManager::setFlags(40, 1); + return 2; + } + else { + addResponse(getDialogueId(200710)); + addResponse(getDialogueId(201334)); + applyResponse(); + return 2; + } + } + } + + if (sentence->contains("what should i do here") + || sentence->contains("what do i do here") + || sentence->contains("what shall i do in here") + || sentence->contains("what shall i do in this room") + || sentence->contains("what should i do in this room") + || sentence->contains("what am i supposed to do in here") + || sentence->contains("what should i do in here") + || sentence->contains("what do i do in this room")) { + if (addRoomDescription(roomScript)) { + applyResponse(); + return 2; + } + } + + if (sentence->contains("help") + || sentence->contains("what now") + || sentence->contains("what next") + || sentence->contains("give me a hint") + || sentence->contains("i need a hint") + || sentence->contains("what should i be doing") + || sentence->contains("what do you reckon i should do now") + || sentence->contains("what shall i do") + || sentence->contains("what would you do") + || sentence->contains("what should i do") + || sentence->contains("what do i do")) { + if (getDialRegion(0) == 1) { + randomResponse4(roomScript, getValue(1)); + applyResponse(); + return 2; + } else { + randomResponse3(roomScript, getValue(1)); + } + } + + if (sentence->get58() > 6 && sentence->contains("please")) { + addResponse(getDialogueId(200432)); + applyResponse(); + return 2; + } + + if (checkCommonSentences(roomScript, sentence) == 2) + return 2; + + // WORKAROUND: Skip processEntries call on unassigned sentence array + + // Standard sentence list + if (processEntries(&_entries, _entryCount, roomScript, sentence) == 2) + return 2; + + if ((sentence->_field2C == 4 && sentence->localWord("am") && sentence->localWord("i")) + || (sentence->localWord("are") && sentence->localWord("we")) + || (sentence->_field2C == 3 && sentence->localWord("room") + && sentence->localWord("we") && sentence->localWord("in")) + || (sentence->_field2C == 3 && sentence->localWord("rom") + && sentence->localWord("is") && sentence->localWord("this")) + ) { + uint id = getRangeValue(getRoomDialogueId(roomScript)); + addResponse(getDialogueId(id ? id : 201384)); + applyResponse(); + return 2; + } + + if (getValue(1) >= 3) { + result = processEntries(&_sentences[1], 0, roomScript, sentence); + } else if (getValue(1) == 2) { + result = processEntries(&_sentences[2], 0, roomScript, sentence); + } else if (getValue(1) == 1) { + result = processEntries(&_sentences[3], 0, roomScript, sentence); + + if (sentence->contains("shrinkbot")) { + addResponse(getDialogueId(200583)); + applyResponse(); + return 2; + } + } + + if (sentence->localWord("television") || sentence->localWord("tv") + || sentence->localWord("crush") || sentence->localWord("crushed")) { + if (roomScript->_scriptId == 111 || getRandomBit()) { + addResponse(getDialogueId(getRandomBit() ? 200912 : 200913)); + } else { + addResponse(getDialogueId(200710)); + addResponse(getDialogueId(201334)); + } + + applyResponse(); + return 2; + } + + if (checkCommonWords(roomScript, sentence)) { + applyResponse(); + setState(0); + return 2; + } + + if (sentence->contains("my") && (sentence->contains("where can i find") + || sentence->contains("where is") + || sentence->contains("wheres") + || sentence->contains("help me find") + || sentence->contains("what have you done with") + || sentence->contains("have you got") + || sentence->contains("id like") + || sentence->contains("i would like") + || sentence->contains("have you seen") + )) { + addResponse(getDialogueId(200799)); + applyResponse(); + return 2; + } + + setupSentences(); + uint tagId = g_vm->_trueTalkManager->_quotes.find(sentence->_normalizedLine); + if (tagId && chooseResponse(roomScript, sentence, tagId) == 2) + return 2; + if (defaultProcess(roomScript, sentence)) + return 2; + if (!processEntries(&_sentences[19], 0, roomScript, sentence)) + return 2; + if (!processEntries(_defaultEntries, 0, roomScript, sentence)) + return 2; + + if (sentence->contains("42")) { + addResponse(getDialogueId(200515)); + applyResponse(); + return 2; + } + + CTrueTalkManager::setFlags(24, val24 + 1); + if (getValue(24) > 3) { + addResponse(getDialogueId(200200)); + applyResponse(); + return 2; + } + + if (sentence->localWord("get")) { + addResponse(getDialogueId(200475)); + applyResponse(); + return 2; + } + + if (getRandomNumber(100) <= 75) { + addResponse(getDialogueId(200060)); + applyResponse(); + return 2; + } + + addResponse(getDialogueId(200140)); + addResponse(getDialogueId(getRandomBit() ? 200192 : 200157)); + addResponse(getDialogueId(200176)); + applyResponse(); + return 2; +} + +ScriptChangedResult BellbotScript::scriptChanged(const TTroomScript *roomScript, uint id) { + if (!roomScript) + return SCR_2; + + switch (id) { + case 104: + addResponse(getDialogueId(200617)); + applyResponse(); + break; + + case 105: + addResponse(getDialogueId(200732)); + applyResponse(); + break; + + case 106: + addResponse(getDialogueId(200733)); + applyResponse(); + break; + + case 107: + addResponse(getDialogueId(200731)); + applyResponse(); + break; + + case 157: + _field2DC = 1; + break; + + case 158: + CTrueTalkManager::setFlags(26, 1); + break; + + case 3: + if (_field2DC) { + if (randomResponse0(roomScript, id)) + return SCR_2; + } else { + addResponse(getDialogueId(201693)); + applyResponse(); + } + + _field2DC = 0; + CTrueTalkManager::_v9 = 0; + // Deliberate fall-through + default: + if (roomScript->_scriptId == 115 && id == 103) { + switch (getValue(4)) { + case 0: + addResponse(getDialogueId(200014)); + applyResponse(); + break; + case 1: + case 2: + addResponse(getDialogueId(200011)); + applyResponse(); + break; + case 3: + addResponse(getDialogueId(200007)); + applyResponse(); + break; + default: + break; + } + } + break; + } + + return SCR_2; +} + +int BellbotScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + switch (tagId) { + case MKTAG('A', 'D', 'V', 'T'): + case MKTAG('A', 'R', 'T', 'I'): + case MKTAG('A', 'R', 'T', 'Y'): + case MKTAG('B', 'R', 'N', 'D'): + case MKTAG('C', 'O', 'M', 'D'): + case MKTAG('D', 'N', 'C', 'E'): + case MKTAG('H', 'B', 'B', 'Y'): + case MKTAG('L', 'I', 'T', 'R'): + case MKTAG('M', 'A', 'G', 'S'): + case MKTAG('M', 'C', 'P', 'Y'): + case MKTAG('M', 'I', 'N', 'S'): + case MKTAG('M', 'U', 'S', 'I'): + case MKTAG('N', 'I', 'K', 'E'): + case MKTAG('S', 'F', 'S', 'F'): + case MKTAG('S', 'O', 'A', 'P'): + case MKTAG('S', 'O', 'N', 'G'): + case MKTAG('S', 'P', 'R', 'T'): + case MKTAG('T', 'E', 'A', 'M'): + case MKTAG('T', 'V', 'S', 'H'): + case MKTAG('W', 'W', 'E', 'B'): + tagId = MKTAG('E', 'N', 'T', 'N'); + break; + case MKTAG('A', 'C', 'T', 'R'): + case MKTAG('A', 'C', 'T', 'S'): + case MKTAG('A', 'U', 'T', 'H'): + case MKTAG('B', 'A', 'R', 'K'): + case MKTAG('B', 'A', 'R', 'U'): + case MKTAG('B', 'L', 'F', '1'): + case MKTAG('B', 'L', 'F', '2'): + case MKTAG('B', 'L', 'P', '1'): + case MKTAG('B', 'L', 'P', '2'): + case MKTAG('B', 'L', 'P', '3'): + case MKTAG('B', 'L', 'P', '4'): + case MKTAG('B', 'L', 'R', '1'): + case MKTAG('B', 'L', 'R', '2'): + case MKTAG('B', 'L', 'T', '1'): + case MKTAG('B', 'L', 'T', '2'): + case MKTAG('B', 'L', 'T', '3'): + case MKTAG('B', 'L', 'T', '4'): + case MKTAG('B', 'L', 'T', '5'): + case MKTAG('C', 'O', 'P', 'S'): + case MKTAG('D', 'C', 'T', 'R'): + case MKTAG('F', 'A', 'S', 'H'): + case MKTAG('F', 'A', 'M', 'E'): + case MKTAG('H', 'E', 'R', 'D'): + case MKTAG('H', 'O', 'S', 'T'): + case MKTAG('K', 'N', 'O', 'B'): + case MKTAG('N', 'H', 'R', 'O'): + case MKTAG('R', 'A', 'C', 'E'): + case MKTAG('S', 'C', 'I', 'T'): + case MKTAG('T', 'O', 'U', 'P'): + case MKTAG('T', 'W', 'A', 'T'): + case MKTAG('W', 'E', 'A', 'T'): + tagId = MKTAG('P', 'R', 'S', 'N'); + break; + case MKTAG('C', 'H', 'S', 'E'): + case MKTAG('C', 'M', 'N', 't'): + case MKTAG('F', 'I', 'L', 'M'): + case MKTAG('J', 'F', 'O', 'D'): + case MKTAG('L', 'I', 'Q', 'D'): + tagId = MKTAG('F', 'O', 'O', 'D'); + break; + case MKTAG('C', 'R', 'I', 'M'): + case MKTAG('C', 'S', 'P', 'Y'): + case MKTAG('D', 'R', 'U', 'G'): + tagId = MKTAG('V', 'B', 'A', 'D'); + break; + case MKTAG('E', 'A', 'R', 'T'): + case MKTAG('H', 'O', 'M', 'E'): + case MKTAG('N', 'P', 'L', 'C'): + case MKTAG('P', 'L', 'A', 'N'): + tagId = MKTAG('P', 'L', 'A', 'C'); + break; + case MKTAG('F', 'A', 'U', 'N'): + case MKTAG('F', 'I', 'S', 'H'): + case MKTAG('F', 'L', 'O', 'R'): + tagId = MKTAG('N', 'A', 'T', 'R'); + break; + case MKTAG('H', 'H', 'L', 'D'): + case MKTAG('T', 'O', 'Y', 'S'): + case MKTAG('W', 'E', 'A', 'P'): + tagId = MKTAG('M', 'A', 'C', 'H'); + break; + case MKTAG('M', 'L', 'T', 'Y'): + case MKTAG('P', 'G', 'R', 'P'): + case MKTAG('P', 'T', 'I', 'C'): + tagId = MKTAG('G', 'R', 'U', 'P'); + break; + case MKTAG('P', 'K', 'U', 'P'): + case MKTAG('S', 'E', 'X', '1'): + case MKTAG('S', 'W', 'E', 'R'): + tagId = MKTAG('R', 'U', 'D', 'E'); + break; + case MKTAG('P', 'H', 'I', 'L'): + case MKTAG('R', 'C', 'K', 'T'): + tagId = MKTAG('S', 'C', 'I', 'E'); + break; + case MKTAG('T', 'R', 'A', '2'): + case MKTAG('T', 'R', 'A', '3'): + tagId = MKTAG('T', 'R', 'A', 'V'); + break; + default: + break; + } + + return TTnpcScript::handleQuote(roomScript, sentence, val, tagId, remainder); +} + +int BellbotScript::updateState(uint oldId, uint newId, int index) { + if (!getValue(25)) { + newId = 202043 - getValue(1) <= 2 ? 994 : 0; + CTrueTalkManager::setFlags(25, 1); + } + + if (oldId == _oldId && _rangeResetCtr >= 3) { + TTscriptRange *range = findRange(oldId); + if (range) + range->_priorIndex = 0; + + _rangeResetCtr = 0; + return getRangeValue(200370); + } + + if (oldId != _oldId) { + _oldId = oldId; + _rangeResetCtr = 0; + } + + if (oldId >= 201709 && oldId <= 201754) { + addResponse(getDialogueId(201705)); + addResponse(getDialogueId(201706)); + newId = getRangeValue(201707); + } + + if (newId == 202276) + newId = addLocation(); + if (newId == 202275) + newId = getStateDialogueId(); + + if (getValue(1) >= 2) { + if (newId == 200840 || newId == 200845 || newId == 200846 || newId == 200851) { + if (getValue(1) == 2) { + newId = 202047; + } else { + newId = getRangeValue(202848); + } + } + } + + if (getValue(1) >= 3) { + if (newId == 200841 || newId == 200842 || newId == 200843 || + newId == 200847 || newId == 200848 || newId == 200854) { + newId = getRangeValue(202038); + } + } + + if (newId == 200264 && getValue(1) == 1) + newId = 200267; + if (newId == 202231 && getValue(1) == 1) + newId = 200848; + + int v4 = getValue(4); + if (newId == 200187 && v4) { + return 200188; + } else if (newId == 200188 && !v4) { + return 200187; + } else if (newId == 200014 && (v4 == 1 || v4 == 2)) { + return 200011; + } else if (newId == 200011 && !v4) { + return 200014; + } + + if (oldId == 200612) { + CTrueTalkManager::setFlags(25, 2); + CTrueTalkManager::setFlags(5, 1); + } + + if (newId == 200423 || newId == 200424 || newId == 200425) { + if (getValue(5)) { + CTrueTalkManager::triggerAction(16, 0); + } else { + newId = 200611; + } + } + + if (oldId == 200261 && getRandomNumber(10) == 1) { + if (getValue(1) >= 3) + newId = getRangeValue(200283); + else if (getValue(1) == 2) + newId = getRangeValue(200279); + } + + if (oldId == 200962) { + if (getValue(1) == 2) + return 200963; + if (getValue(1) == 1) + return 200964; + } + if (oldId == 200989 && getValue(1) <= 2) + return 200990; + + if (oldId == 201760) { + CGameManager *gameManager = g_vm->_trueTalkManager->getGameManager(); + CPetControl *pet = getPetControl(gameManager); + + if (pet) { + bool canSummon = pet->canSummonBot("DoorBot"); + if (canSummon) { + CTrueTalkManager::_v9 = 101; + CTrueTalkManager::triggerAction(5, 0); + } else { + newId = 201857; + } + } + } + + setValue23(newId); + return newId; +} + +int BellbotScript::preResponse(uint id) { + int newId = _preResponses.find(id); + + if (newId == 202277) { + applyResponse(); + CTrueTalkManager::triggerAction(1, 0); + } + if (newId == 200769) { + applyResponse(); + CTrueTalkManager::triggerAction(18, 0); + } + + if (id == 21790) + CTrueTalkManager::triggerAction(13, 0); + + return newId; +} + +int BellbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + switch (val1) { + case 1: + addResponse(getDialogueId(*srcIdP)); + applyResponse(); + return 2; + + case 2: + addResponse(getDialogueId(*srcIdP)); + addResponse(getDialogueId(getRandomNumber(2) == 1 ? 200192 : 200157)); + addResponse(getDialogueId(200176)); + applyResponse(); + return 2; + + case 21: + if (CTrueTalkManager::getStateValue(7) == 0) { + selectResponse(21372); + applyResponse(); + return 2; + } + + if (!sentence->localWord("broken") && !sentence->contains("broken") && + CTrueTalkManager::_currentNPC) { + CNodeItem *node = CTrueTalkManager::_currentNPC->getNode(); + if (node) { + CString nodeName = node->getName(); + if (nodeName == "5" || nodeName == "6" || nodeName == "7") { + CTrueTalkManager::triggerAction(29, 2); + selectResponse(201571); + applyResponse(); + return 2; + } + } + } + + CTrueTalkManager::triggerAction(29, 1); + selectResponse(201771); + applyResponse(); + return 2; + + case 22: + if (CTrueTalkManager::getStateValue(7) == 0) { + selectResponse(21372); + applyResponse(); + return 2; + } + + if (!sentence->localWord("broken") && !sentence->contains("broken") && + CTrueTalkManager::_currentNPC) { + CNodeItem *node = CTrueTalkManager::_currentNPC->getNode(); + if (node) { + CString nodeName = node->getName(); + if (nodeName == "5" || nodeName == "6" || nodeName != "7") { + CTrueTalkManager::triggerAction(29, 2); + selectResponse(201571); + applyResponse(); + return 2; + } + } + } + + CTrueTalkManager::triggerAction(29, 1); + selectResponse(201771); + applyResponse(); + return 2; + + case 23: + case 24: + if (CTrueTalkManager::getStateValue(7) == 0) { + selectResponse(21372); + applyResponse(); + return 2; + } + + CTrueTalkManager::triggerAction(29, val1 == 23 ? 3 : 4); + break; + + default: + break; + } + + return 0; +} + +bool BellbotScript::randomResponse(uint index) { + if (getRandomNumber(100) > 10 || getRandomNumber(10) <= index) + return 0; + + if (getRandomNumber(100) > 95) { + deleteResponses(); + addResponse(getDialogueId(201695)); + applyResponse(); + } else { + setResponseFromArray(index, 201696); + } + + return true; +} + +int BellbotScript::addLocation() { + addResponse(getDialogueId(202228)); + int roomNum, floorNum, elevatorNum; + getAssignedRoom(&roomNum, &floorNum, &elevatorNum); + + addResponse(getDialogueId(202071 + roomNum)); + addResponse(getDialogueId(201933 + floorNum)); + addResponse(getDialogueId(201916 + elevatorNum)); + + return 200858; +} + +int BellbotScript::getStateDialogueId() const { + switch (getValue(1)) { + case 1: + return 201253; + case 2: + return 200282; + default: + return 201246; + } +} + +void BellbotScript::setValue23(uint id) { + uint val = 0; + for (uint idx = 0; idx < _states.size() && !val; ++idx) { + TTmapEntry &us = _states[idx]; + if (us._src == id) + val = us._dest; + } + + CTrueTalkManager::setFlags(23, val); +} + +int BellbotScript::preprocess(const TTroomScript *roomScript, const TTsentence *sentence) { + if (!roomScript || !sentence) + return true; + + bool applyFlag = false, stateFlag = true; + switch (getValue(23)) { + case 1: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200818)); + applyFlag = true; + } + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200817)); + applyFlag = true; + } + break; + + case 2: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200835)); + addResponse(getDialogueId(200830)); + applyFlag = true; + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(200834)); + addResponse(getDialogueId(200830)); + applyFlag = true; + } + break; + + case 3: + if (sentence->_field2C >= 11 && sentence->_field2C <= 13) { + addResponse(getDialogueId(200831)); + addResponse(getDialogueId(200833)); + applyFlag = true; + } + break; + + case 4: + if (sentence->_field2C == 11) { + addResponse(getDialogueId(200872)); + applyFlag = true; + } + if (sentence->_field2C == 12 || sentence->_field2C == 13) { + addResponse(getDialogueId(200873)); + applyFlag = true; + } + break; + + case 5: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200492)); + applyFlag = true; + } + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200491)); + applyFlag = true; + } + break; + + case 6: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200496)); + applyResponse(); + setState(0); + CTrueTalkManager::setFlags(23, 7); + return 2; + } + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200127)); + applyFlag = true; + } + break; + + case 7: + addResponse(getDialogueId(200504)); + addResponse(getDialogueId(200496)); + applyFlag = true; + stateFlag = false; + break; + + case 8: + addResponse(getDialogueId(200494)); + applyFlag = true; + stateFlag = false; + break; + + case 9: + addResponse(getDialogueId(sentence->localWord("guess") ? 200495 : 200493)); + applyFlag = true; + break; + + case 10: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200317)); + applyResponse(); + setState(0); + CTrueTalkManager::setFlags(23, 11); + return 2; + } + + addResponse(getDialogueId(sentence->_field2C == 12 ? 200316 : 200315)); + applyFlag = true; + break; + + case 11: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200055)); + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(200318)); + } else { + addResponse(getDialogueId(200315)); + } + + applyFlag = true; + break; + + case 12: + if (sentence->_field2C == 6) { + addResponse(getDialogueId(200259)); + applyFlag = true; + } + break; + + case 13: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200207)); + applyFlag = true; + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(200206)); + applyFlag = true; + } + break; + + case 14: + if (sentence->_field2C == 6) { + addResponse(getDialogueId(200349)); + applyFlag = true; + } + + case 15: + if (sentence->_field2C == 6) { + addResponse(getDialogueId(200130)); + applyResponse(); + setState(0); + CTrueTalkManager::setFlags(23, 16); + return 2; + } + break; + + case 16: + if (sentence->localWord("invented")) { + addResponse(getDialogueId(200131)); + applyFlag = true; + } + break; + + case 17: + if ((sentence->_field2C == 3 && sentence->localWord("code")) + || (sentence->localWord("which") && sentence->localWord("is")) + || sentence->localWord("remember") + || sentence->localWord("know") + ) { + addResponse(getDialogueId(200044)); + applyFlag = true; + stateFlag = false; + } + break; + + case 19: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200223)); + applyFlag = true; + } + break; + + case 20: + addResponse(getDialogueId(200254)); + applyFlag = true; + break; + + case 21: + if (sentence->contains("hiker") || sentence->contains("hug")) { + addResponse(getDialogueId(200379)); + applyFlag = true; + } + break; + + case 22: + if (sentence->localWord("get") || sentence->localWord("it")) { + addResponse(getDialogueId(200474)); + applyFlag = true; + } + break; + + case 23: + addResponse(getDialogueId(sentence->localWord("long") ? 200870 : 200871)); + applyFlag = true; + break; + + case 24: + addResponse(getDialogueId(200793)); + applyFlag = true; + stateFlag = false; + break; + + case 25: + if (sentence->localWord("parrot")) { + addResponse(getDialogueId(200255)); + applyFlag = true; + stateFlag = false; + } + break; + + case 26: + if (sentence->localWord("cage")) { + addResponse(getDialogueId(200380)); + applyFlag = true; + stateFlag = false; + } + break; + + case 27: + addResponse(getDialogueId(200347)); + applyFlag = true; + stateFlag = false; + break; + + case 28: + if (sentence->localWord("perch")) { + addResponse(getDialogueId(200242)); + applyFlag = true; + stateFlag = false; + } + break; + + case 29: + if (sentence->localWord("brain") || sentence->localWord("titania")) { + addResponse(getDialogueId(200392)); + applyFlag = true; + stateFlag = false; + } + break; + + case 30: + if ((sentence->localWord("did") || sentence->localWord("not")) + || (sentence->localWord("would") || sentence->localWord("not")) + || (sentence->localWord("could") || sentence->localWord("not")) + || sentence->localWord("tried")) { + addResponse(getDialogueId(200416)); + applyFlag = true; + } + break; + + case 31: + addResponse(getDialogueId(sentence->_field2C == 11 ? 200810 : 200811)); + applyFlag = true; + break; + + case 32: + addResponse(getDialogueId(sentence->_field2C == 11 ? 200810 : 200812)); + applyFlag = true; + break; + + case 33: + addResponse(getDialogueId(200822)); + applyFlag = true; + break; + + case 34: + addResponse(getDialogueId(200824)); + applyFlag = true; + break; + + case 35: + if (sentence->_field2C == 3 && sentence->localWord("it") + && (sentence->localWord("for") || sentence->localWord("do"))) { + addResponse(getDialogueId(200768)); + applyFlag = true; + } + break; + + case 36: + if (sentence->_field2C == 11) { + CTrueTalkManager::triggerAction(14, 0); + addResponse(getDialogueId(200761)); + applyFlag = true; + } + break; + + case 37: + addResponse(getDialogueId(200630)); + applyFlag = true; + break; + + case 38: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200631)); + applyFlag = true; + } + break; + + case 39: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200632)); + stateFlag = false; + } else { + addResponse(getDialogueId(200633)); + } + applyFlag = true; + break; + + case 40: + addResponse(getDialogueId(200633)); + applyFlag = true; + break; + + case 41: + addResponse(getDialogueId(sentence->contains("42") ? 200139 : 200627)); + applyFlag = true; + break; + + case 42: + if ((sentence->localWord("carry") && sentence->localWord("on")) + || (sentence->localWord("go") && sentence->localWord("on")) + || sentence->localWord("more") + || sentence->localWord("going") + || sentence->localWord("elaborate") + || sentence->localWord("suspicious") + || sentence->localWord("they")) { + addResponse(getDialogueId(200642)); + applyFlag = true; + stateFlag = false; + } + break; + + case 43: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200643)); + applyFlag = true; + } + break; + + case 44: +case44: + if (better(sentence, 200615, 200613)) { + applyFlag = true; + stateFlag = false; + } + break; + + case 45: + if (sentence->contains("surprise")) { + addResponse(getDialogueId(200614)); + applyFlag = true; + stateFlag = false; + break; + } + goto case44; + + case 46: + if (sentence->contains("good")) { + addResponse(getDialogueId(200616)); + applyFlag = true; + stateFlag = false; + break; + } + goto case44; + + case 47: + if (sentence->_field2C == 12) + addResponse(getDialogueId(200368)); + addResponse(getDialogueId(200366)); + applyFlag = true; + stateFlag = false; + break; + + case 48: + if ((sentence->localWord("carry") && sentence->localWord("on")) + || sentence->localWord("more") + || (sentence->localWord("go") && sentence->localWord("on")) + || sentence->localWord("going") + || sentence->localWord("yes") + || sentence->localWord("really")) { + addResponse(getDialogueId(200367)); + applyFlag = true; + } + break; + + case 49: + if (sentence->_field2C >= 11 && sentence->_field2C <= 13) { + addResponse(getDialogueId(200407)); + applyFlag = true; + stateFlag = false; + } + break; + + case 50: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200408)); + stateFlag = false; + } else { + addResponse(getDialogueId(200409)); + } + applyFlag = true; + break; + + case 51: + if (sentence->localWord("no") || sentence->localWord("it") + || sentence->localWord("is") || sentence->localWord("not") + || sentence->contains("yeah right")) { + addResponse(getDialogueId(200636)); + applyFlag = true; + } + break; + + case 52: + if (sentence->_field2C >= 11 && sentence->_field2C <= 13) { + addResponse(getDialogueId(200872)); + applyFlag = true; + } + break; + + case 53: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200525)); + applyFlag = true; + } else if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200526)); + applyFlag = true; + } + break; + + case 54: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200095)); + applyFlag = true; + stateFlag = false; + } + break; + + case 55: + if (sentence->_field2C == 6) { + addResponse(getDialogueId(200112)); + applyFlag = true; + } + break; + + case 56: + if (sentence->localWord("sure") + || (sentence->localWord("nothing") && sentence->localWord("else"))) { + addResponse(getDialogueId(200649)); + applyFlag = true; + stateFlag = false; + } + break; + + case 57: + if (sentence->localWord("bad") + || (sentence->localWord("not") && sentence->localWord("good"))) { + addResponse(getDialogueId(200654)); + } else { + addResponse(getDialogueId(200655)); + stateFlag = false; + } + applyFlag = true; + break; + + case 58: + if (sentence->localWord("more") + || (sentence->localWord("go") && sentence->localWord("on")) + || (sentence->_field2C == 11 && sentence->localWord("really"))) { + addResponse(getDialogueId(200650)); + applyFlag = true; + stateFlag = false; + } + break; + + case 59: + if (!sentence->localWord("shutup")) { + addResponse(getDialogueId(200651)); + applyFlag = true; + stateFlag = false; + } + break; + + case 60: + if (sentence->_field2C == 3 && sentence->localWord("they") && sentence->localWord("do")) { + addResponse(getDialogueId(200652)); + applyFlag = true; +stateFlag = false; + } + break; + + case 61: + if ((sentence->localWord("that") && sentence->localWord("all")) + || (sentence->localWord("anything") && sentence->localWord("else"))) { + addResponse(getDialogueId(200653)); + applyFlag = true; + } + break; + + case 62: + if (sentence->localWord("meant") || sentence->localWord("woman")) { + addResponse(getDialogueId(200743)); + applyFlag = true; + } + break; + + case 63: + addResponse(getDialogueId(200208)); + applyFlag = true; + break; + + case 64: + if (sentence->localWord("rowboat")) { + addResponse(getDialogueId(200052)); + applyFlag = true; + } + break; + + case 65: + if (sentence->localWord("sorry")) { + addResponse(getDialogueId(200056)); + applyFlag = true; + stateFlag = false; + } + break; + + case 66: + if (sentence->localWord("sorry")) { + addResponse(getDialogueId(200057)); + applyFlag = true; + stateFlag = false; + } + break; + + case 67: + if (sentence->localWord("sorry")) { + addResponse(getDialogueId(200055)); + applyFlag = true; + stateFlag = false; + } + break; + + case 68: + if ((sentence->localWord("i") && sentence->localWord("care")) + || sentence->localWord("do") + || sentence->localWord("me")) { + addResponse(getDialogueId(201006)); + applyFlag = true; + } + break; + + case 69: + if ((sentence->localWord("what") && sentence->localWord("happen")) + || sentence->localWord("filigon")) { + addResponse(getDialogueId(201011)); + applyFlag = true; + stateFlag = false; + } + break; + + case 70: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(201012)); + applyFlag = true; + stateFlag = false; + } + break; + + case 71: + if (sentence->localWord("why")) { + addResponse(getDialogueId(201013)); + applyFlag = true; + } + break; + + case 72: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(200921)); + applyFlag = true; + } else if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(200920)); + applyFlag = true; + } + break; + + case 73: + if (sentence->localWord("mood") && (charId() == 7 || charId() == 5)) { + addResponse(getDialogueId(201021)); + applyFlag = true; + stateFlag = false; + } + break; + + case 74: + if (sentence->_field2C == 6) { + addResponse(getDialogueId(201022)); + applyFlag = true; + stateFlag = false; + } + break; + + case 75: + if (sentence->_field2C == 3) { + if (sentence->localWord("that") || sentence->localWord("worb")) { + addResponse(getDialogueId(201802)); + applyFlag = true; + } + } + break; + + case 76: + if (sentence->_field2C == 2 && (sentence->localWord("that") || sentence->localWord("gat"))) { + addResponse(getDialogueId(201034)); + applyFlag = true; + stateFlag = false; + } + break; + + case 77: + if (sentence->_field2C == 4 || sentence->_field2C == 3) { + if (sentence->localWord("that") || sentence->localWord("blerontis")) { + addResponse(getDialogueId(201035)); + applyFlag = true; + } + } + break; + + case 78: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(201034)); + applyFlag = true; + stateFlag = false; + } else if (sentence->_field2C == 11) { + addResponse(getDialogueId(201040)); + applyFlag = true; + } else if ((sentence->localWord("not") && sentence->localWord("remember")) + || sentence->localWord("forgot")) { + addResponse(getDialogueId(201041)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why")) { + addResponse(getDialogueId(201042)); + applyFlag = true; + stateFlag = false; + } + break; + + case 79: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(201052)); + CTrueTalkManager::triggerAction(14, 0); + applyFlag = true; + stateFlag = false; + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(202119)); + addResponse(getDialogueId(200256)); + applyFlag = true; + } + break; + + case 80: + if ((!sentence->localWord("what") && sentence->localWord("how")) + || sentence->localWord("about") + || sentence->localWord("you")) { + if (sentence->_field2C != 3 && sentence->_field2C != 4 && sentence->_field2C != 7) { + addResponse(getDialogueId(201694)); + applyFlag = true; + stateFlag = false; + } + } else { + addResponse(getDialogueId(201135)); + applyFlag = true; + } + break; + + case 81: + if ((!sentence->localWord("what") && !sentence->localWord("how")) + || !sentence->localWord("about") + || !sentence->localWord("you")) { + if (!sentence->localWord("and") || !sentence->localWord("yourself")) + break; + } + addResponse(getDialogueId(201135)); + applyFlag = true; + break; + + case 82: + if ((sentence->_field2C == 3 && sentence->localWord("mean")) + || sentence->localWord("surf") + || (sentence->localWord("what") && sentence->localWord("talk") + && sentence->localWord("about"))) { + addResponse(getDialogueId(201694)); + applyFlag = true; + stateFlag = false; + } + break; + + case 83: + if (sentence->_field2C != 3 && sentence->_field2C != 4 && sentence->_field2C != 7) { + addResponse(getDialogueId(201083)); + applyFlag = true; + } + break; + + case 84: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(202119)); + + switch (getValue(1)) { + case 1: + addResponse(getDialogueId(202024)); + applyFlag = true; + break; + case 2: + addResponse(getDialogueId(201812)); + applyFlag = true; + stateFlag = false; + break; + default: + break; + } + } else if (sentence->_field2C == 11) { + addResponse(getDialogueId(201060)); + addResponse(getDialogueId(201079)); + applyFlag = true; + stateFlag = false; + } + break; + + case 85: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(201814)); + applyFlag = true; + } + if (sentence->_field2C == 12) { + addResponse(getDialogueId(201813)); + applyFlag = true; + } + break; + + case 86: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(202109)); + applyFlag = true; + } + if (sentence->_field2C == 12) { + addResponse(getDialogueId(202108)); + applyFlag = true; + } + break; + + case 87: + if (better(sentence, 201993, 200720)) { + applyFlag = true; + } + break; + + case 88: + if (sentence->_field2C == 6 || sentence->contains("upside down")) { + addResponse(getDialogueId(202142)); + applyFlag = true; + } + break; + + case 89: + if (sentence->_field2C == 2) { + addResponse(getDialogueId(200739)); + applyFlag = true; + stateFlag = false; + } + break; + + case 90: + if (sentence->contains("like") && (sentence->contains("slug") || sentence->contains("snail"))) { + addResponse(getDialogueId(201029)); + applyFlag = true; + stateFlag = false; + } else if (sentence->contains("slime") || sentence->localWord("what")) { + addResponse(getDialogueId(201220)); + applyFlag = true; + stateFlag = false; + } + + default: + break; + } + + if (applyFlag) + applyResponse(); + if (stateFlag) { + setState(0); + CTrueTalkManager::setFlags(23, 0); + } + + return applyFlag ? 2 : 1; +} + +bool BellbotScript::better(const TTsentence *sentence, uint id1, uint id2) { + if (sentence->contains("good") || sentence->localWord("better")) { + addResponse(getDialogueId(id1)); + } else if (sentence->localWord("bad")) { + addResponse(getDialogueId(id2)); + } else { + return false; + } + + return true; +} + +bool BellbotScript::randomResponse0(const TTroomScript *roomScript, uint id) { + bool dr0 = getDialRegion(0) == 1; + uint newId = getValue(1); + + if (getValue(25) == 0) { + CTrueTalkManager::setFlags(25, 1); + if (getValue(1) > 2) { + addResponse(getDialogueId(202043)); + applyResponse(); + return true; + } + } + + bool result = dr0 ? randomResponse1(roomScript, newId) : + randomResponse2(roomScript, newId); + if (result) + CTrueTalkManager::triggerAction(1, 0); + + return true; +} + +bool BellbotScript::randomResponse1(const TTroomScript *roomScript, uint id) { + if (getRandomNumber(100) < 10) { + addResponse(getDialogueId(201978)); + applyResponse(); + } else { + if (getRandomNumber(100) < 50) + addResponse(getDialogueId(202259)); + + randomResponse3(roomScript, id); + applyResponse(); + } + + return false; +} + +bool BellbotScript::randomResponse2(const TTroomScript *roomScript, uint id) { + if (getRandomNumber(100) < 5) { + addResponse(getDialogueId(202262)); + applyResponse(); + } else { + if (getRandomNumber(100) < 40) + addResponse(getDialogueId(202258)); + + randomResponse4(roomScript, id); + applyResponse(); + } + + return false; +} + +void BellbotScript::randomResponse3(const TTroomScript *roomScript, uint id) { + bool result = false; + if (roomScript && getRandomNumber(100) < 50) + result = addRoomDescription(roomScript); + + if (result) + return; + if (getRandomNumber(100) >= 50) { + addResponse(getDialogueId(202262)); + return; + } + + if (id <= 2) { + if (getRandomNumber(100) < 50) { + addResponse(getDialogueId(202266)); + return; + } else if (id == 2) { + addResponse(getDialogueId(202264)); + return; + } + } + + addResponse(getDialogueId(id == 1 ? 202265 : 202263)); +} + +void BellbotScript::randomResponse4(const TTroomScript *roomScript, uint id) { + if (getRandomNumber(100) < 4 && id <= 2) { + addResponse(getDialogueId(202268)); + } else { + addResponse(getDialogueId(202267)); + } +} + +int BellbotScript::checkCommonSentences(const TTroomScript *roomScript, const TTsentence *sentence) { + if (!roomScript || !sentence) + return 1; + + uint val1 = getValue(1); + for (uint idx = 0; idx < _phrases.size(); ++idx) { + TTcommonPhrase &cp = _phrases[idx]; + + if (cp._roomNum != 0 && cp._roomNum != roomScript->_scriptId) + continue; + if (cp._val1 != 0 && cp._val1 != val1 && (cp._val1 == 3 || val1 != 4)) + continue; + if (!sentence->contains(cp._str.c_str())) + continue; + + addResponse(getDialogueId(cp._dialogueId)); + applyResponse(); + return 2; + } + + return 0; +} + +bool BellbotScript::checkCommonWords(const TTroomScript *roomScript, const TTsentence *sentence) { + if (!roomScript || !sentence) + return 0; + CTrueTalkManager::setFlags(23, 0); + if (sentence->_field2C != 4) + return 0; + + if (sentence->localWord("garage")) { + addResponse(getDialogueId(200874)); + } else if (sentence->localWord("parrotfoodshop")) { + addResponse(getDialogueId(200821)); + } else if (sentence->localWord("sgt") && sentence->localWord("restaurant")) { + addResponse(getDialogueId(200857)); + } else if (sentence->localWord("firstclass") && sentence->localWord("restaurant")) { + addResponse(getDialogueId(200839)); + } else if (sentence->localWord("restaurant")) { + addResponse(getDialogueId(getValue(1) == 1 ? 200839 : 200857)); + } else if (getValue(1) == 1 && sentence->localWord("canal") && sentence->localWord("firstclass")) { + addResponse(getDialogueId(200846)); + } else if (getValue(1) == 2 && sentence->localWord("canal") && sentence->localWord("secondclass")) { + addResponse(getDialogueId(200847)); + } else if (sentence->localWord("canal")) { + addResponse(getDialogueId(getValue(1) == 1 ? 200846 : 200847)); + } else if (sentence->localWord("firstclass") && + (sentence->localWord("stateroom") || sentence->localWord("room"))) { + addResponse(getDialogueId(getValue(1) == 1 ? 200840 : 200306)); + } else if (sentence->localWord("secondclass") && sentence->localWord("stateroom") && sentence->localWord("room")) { + addResponse(getDialogueId(getValue(1) < 3 ? 202231 : 200306)); + } else if (sentence->localWord("stateroom") || sentence->contains("my room")) { + addResponse(getDialogueId(202231)); + } else if (sentence->localWord("firstclass")) { + addResponse(getDialogueId(200840)); + } else if (sentence->localWord("secondclass")) { + addResponse(getDialogueId(200841)); + } else if (sentence->localWord("thirdclass")) { + addResponse(getDialogueId(202231)); + } else if (sentence->localWord("arboretum")) { + addResponse(getDialogueId(200842)); + } else if (sentence->localWord("bar")) { + addResponse(getDialogueId(200843)); + } else if (sentence->localWord("bottomofwell")) { + addResponse(getDialogueId(200860)); + } else if (sentence->localWord("topwell") || sentence->localWord("well")) { + addResponse(getDialogueId(200861)); + } else if (sentence->localWord("bridge")) { + addResponse(getDialogueId(202213)); + } else if (sentence->localWord("creatorroom")) { + addResponse(getDialogueId(200848)); + } else if (sentence->localWord("servicelift")) { + addResponse(getDialogueId(200855)); + } else if (sentence->localWord("lift")) { + addResponse(getDialogueId(202256)); + } else if (sentence->localWord("bilgeroom")) { + addResponse(getDialogueId(202255)); + } else if (sentence->localWord("musicroom")) { + addResponse(getDialogueId(200851)); + } else if (sentence->localWord("parrotlobby")) { + addResponse(getDialogueId(200852)); + } else if (sentence->localWord("parrot") && + (sentence->localWord("room") || sentence->localWord("lobby"))) { + addResponse(getDialogueId(200852)); + } else if (sentence->localWord("promenade")) { + addResponse(getDialogueId(200853)); + } else if (sentence->localWord("sculpture") || sentence->localWord("sculptureroom") + || sentence->localWord("statue")) { + addResponse(getDialogueId(200854)); + } else if (sentence->localWord("lounge")) { + addResponse(getDialogueId(200856)); + } else if (sentence->localWord("titania")) { + if (sentence->localWord("room")) { + addResponse(getDialogueId(200859)); + } else if (sentence->localWord("nose")) { + addResponse(getDialogueId(200703)); + } else if (sentence->localWord("mouth")) { + addResponse(getDialogueId(200702)); + } else if (sentence->localWord("eyes")) { + addResponse(getDialogueId(200701)); + } else if (sentence->localWord("ear")) { + addResponse(getDialogueId(200698)); + } else if (sentence->localWord("brain")) { + addResponse(getDialogueId(200693)); + } else { + addResponse(getDialogueId(200686)); + } + } else if (sentence->localWord("embarklobby") + || sentence->localWord("lobby")) { + addResponse(getDialogueId(200850)); + } else if (sentence->localWord("pellerator")) { + addResponse(getDialogueId(200862)); + } else if (sentence->localWord("servicelift") + || (sentence->localWord("service") && sentence->localWord("elevator"))) { + addResponse(getDialogueId(200855)); + } else if (sentence->localWord("elevator")) { + addResponse(getDialogueId(202256)); + } else if (sentence->localWord("now")) { + addResponse(getDialogueId(200788)); + } else if (sentence->localWord("room")) { + addResponse(getDialogueId(200311)); + } else { + return false; + } + + return true; +} + +uint BellbotScript::getRoomDialogueId(const TTroomScript *roomScript) { + if (!roomScript) + return 0; + + for (int idx = 0; ROOM_DIALOGUE_IDS[idx]._roomNum; ++idx) { + if (ROOM_DIALOGUE_IDS[idx]._roomNum == roomScript->_scriptId) + return ROOM_DIALOGUE_IDS[idx]._dialogueId; + } + + return 0; +} + +bool BellbotScript::addRoomDescription(const TTroomScript *roomScript) { + if (!roomScript) + return false; + + switch (roomScript->_scriptId) { + case 101: + addResponse(getDialogueId(getValue(2) == 1 ? 20185 : 201832)); + break; + case 107: + if (_room107First) { + addResponse(getDialogueId(202162)); + } else { + addResponse(getDialogueId(202162)); + _room107First = true; + } + break; + case 108: + addResponse(getDialogueId(201844)); + break; + case 109: + addResponse(getDialogueId(200303)); + break; + case 110: + addResponse(getDialogueId(202257)); + break; + case 111: + addResponse(getDialogueId(202056)); + break; + case 112: + addResponse(getDialogueId(201828)); + break; + case 113: + addResponse(getDialogueId(201859)); + break; + case 114: + addResponse(getDialogueId(202052)); + break; + case 115: + addResponse(getDialogueId(202004)); + break; + case 116: + addResponse(getDialogueId(202092)); + break; + case 117: + addResponse(getDialogueId(202027)); + break; + case 124: + addResponse(getDialogueId(202110)); + break; + case 125: + addResponse(getDialogueId(202103)); + break; + case 126: + addResponse(getDialogueId(202116)); + break; + case 127: + addResponse(getDialogueId(202111)); + break; + case 128: + addResponse(getDialogueId(201815)); + break; + case 129: + addResponse(getDialogueId(201816)); + break; + case 131: + addResponse(getDialogueId(201930)); + break; + case 132: + addResponse(getDialogueId(201924)); + break; + default: + return false; + } + + return true; +} + + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/bellbot_script.h b/engines/titanic/true_talk/bellbot_script.h new file mode 100644 index 0000000000..3080b56902 --- /dev/null +++ b/engines/titanic/true_talk/bellbot_script.h @@ -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. + * + */ + +#ifndef TITANIC_BELLBOT_SCRIPT_H +#define TITANIC_BELLBOT_SCRIPT_H + +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class BellbotScript : public TTnpcScript { +private: + static uint _oldId; + TTmapEntryArray _states; + TTmapEntryArray _preResponses; + TTsentenceEntries _sentences[20]; + TTcommonPhraseArray _phrases; + int _array[150]; + int _field2D0; + int _field2D4; + int _field2D8; + int _field2DC; + bool _room107First; +private: + /** + * Setup sentence data + */ + void setupSentences(); + + /** + * Add the current location to the response + */ + int addLocation(); + + /** + * Get a dialogue Id based on the state + */ + int getStateDialogueId() const; + + /** + * Sets the state value 25 based on the passed Id + */ + void setValue23(uint id); + + /** + * Does preprocessing for the sentence + */ + int preprocess(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Checks for good, better, or bad in the sentence + */ + bool better(const TTsentence *sentence, uint id1, uint id2); + + bool randomResponse0(const TTroomScript *roomScript, uint id); + bool randomResponse1(const TTroomScript *roomScript, uint id); + bool randomResponse2(const TTroomScript *roomScript, uint id); + void randomResponse3(const TTroomScript *roomScript, uint id); + void randomResponse4(const TTroomScript *roomScript, uint id); + + int checkCommonSentences(const TTroomScript *roomScript, const TTsentence *sentence); + bool checkCommonWords(const TTroomScript *roomScript, const TTsentence *sentence); + + uint getRoomDialogueId(const TTroomScript *roomScript); + + /** + * Adds a description of the room to the conversation response + */ + bool addRoomDescription(const TTroomScript *roomScript); +public: + BellbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Handles a randomzied response + */ + virtual bool randomResponse(uint index); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_BELLBOT_SCRIPT_H */ diff --git a/engines/titanic/true_talk/deskbot_script.cpp b/engines/titanic/true_talk/deskbot_script.cpp new file mode 100644 index 0000000000..f3a997e218 --- /dev/null +++ b/engines/titanic/true_talk/deskbot_script.cpp @@ -0,0 +1,1502 @@ +/* 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/true_talk/deskbot_script.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +int DeskbotScript::_oldId; + +DeskbotScript::DeskbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, -1, -1, -1, 0) { + CTrueTalkManager::setFlags(18, 0); + CTrueTalkManager::setFlags(19, 0); + CTrueTalkManager::setFlags(20, 0); + CTrueTalkManager::setFlags(21, 0); + CTrueTalkManager::setFlags(22, 0); + + setupDials(0, 0, 0); + _data[0] = 100; + if (_currentDialNum == 1) + _currentDialNum = 0; + + loadRanges("Ranges/Deskbot"); + loadResponses("Responses/Deskbot", 4); + setupSentences(); + _tagMappings.load("TagMap/Deskbot"); + _words.load("Words/Deskbot"); + _quotes.load("Quotes/Deskbot"); + _states.load("States/Deskbot"); +} + +void DeskbotScript::setupSentences() { + _mappings.load("Mappings/Deskbot", 4); + _entries.load("Sentences/Deskbot"); + _entries2.load("Sentences/Deskbot/2"); + _entries3.load("Sentences/Deskbot/3"); + _dialValues[0] = _dialValues[1] = 0; + _field68 = 0; + _entryCount = 0; +} + +int DeskbotScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + if (roomScript->_scriptId != 110) + return 2; + + bool flag20 = getValue(20) != 0; + CTrueTalkManager::setFlags(20, 0); + checkItems(nullptr, nullptr); + + if (preprocess(roomScript, sentence) != 1) + return 1; + + CTrueTalkManager::setFlags(17, 0); + setState(0); + updateCurrentDial(false); + + if (getValue(1) == 3) { + if (sentence->localWord("competition") || sentence->contains("competition") + || sentence->localWord("won") || sentence->contains("won") + || sentence->localWord("winning") || sentence->contains("winning") + || sentence->localWord("winner") || sentence->contains("winner") + || sentence->contains("35279") || sentence->contains("3 5 2 7 9") + ) { + addResponse(getDialogueId(41773)); + applyResponse(); + return 2; + } else if (sentence->localWord("magazine") || sentence->contains("magazine")) { + addResponse(getDialogueId(41771)); + applyResponse(); + return 2; + } else if (sentence->localWord("upgrade") || sentence->contains("upgrade")) { + if (CTrueTalkManager::_currentNPC) { + CGameObject *obj; + if (CTrueTalkManager::_currentNPC->find("Magazine", &obj, FIND_PET)) { + addResponse(getDialogueId(41773)); + applyResponse(); + return 2; + } + } + } + } + + if (processEntries(&_entries, _entryCount, roomScript, sentence) != 2 + && processEntries(&_entries2, 0, roomScript, sentence) != 2) { + if (sentence->localWord("sauce") || sentence->localWord("pureed")) { + addResponse(getDialogueId(240398)); + applyResponse(); + } else if (sentence->contains("cherries")) { + addResponse(getDialogueId(240358)); + applyResponse(); + } else if (sentence->contains("42")) { + addResponse(getDialogueId(240453)); + applyResponse(); + } else if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(241778)); + applyResponse(); + } else { + if (sentence->contains("98129812")) + setDialRegion(1, 1); + + if (!defaultProcess(roomScript, sentence) + && processEntries(&_entries3, 0, roomScript, sentence) != 2 + && processEntries(_defaultEntries, 0, roomScript, sentence) != 2) { + if (flag20) + CTrueTalkManager::setFlags(20, 1); + addResponse(getDialogueId(240569)); + applyResponse(); + } + } + } + + return 2; +} + +ScriptChangedResult DeskbotScript::scriptChanged(const TTroomScript *roomScript, uint id) { + switch (id) { + case 3: + case 100: + case 108: + CTrueTalkManager::setFlags(21, getValue(21) + 1); + addResponse(getDialogueId(getValue(22) ? 240577 : 241261)); + applyResponse(); + break; + + case 109: + addResponse(getDialogueId(241627)); + applyResponse(); + break; + + case 140: + if (getValue(1) == 3) + addAssignedRoomDialogue3(); + break; + + case 148: + CTrueTalkManager::setFlags(3, 1); + break; + + case 150: + CTrueTalkManager::setFlags(2, 1); + break; + } + + return SCR_2; +} + +int DeskbotScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + switch (tagId) { + case MKTAG('A', 'D', 'V', 'T'): + case MKTAG('A', 'R', 'T', 'I'): + case MKTAG('A', 'R', 'T', 'Y'): + case MKTAG('B', 'R', 'N', 'D'): + case MKTAG('C', 'O', 'M', 'D'): + case MKTAG('D', 'N', 'C', 'E'): + case MKTAG('H', 'B', 'B', 'Y'): + case MKTAG('L', 'I', 'T', 'R'): + case MKTAG('M', 'A', 'G', 'S'): + case MKTAG('M', 'C', 'P', 'Y'): + case MKTAG('M', 'I', 'N', 'S'): + case MKTAG('M', 'U', 'S', 'I'): + case MKTAG('N', 'I', 'K', 'E'): + case MKTAG('S', 'F', 'S', 'F'): + case MKTAG('S', 'O', 'A', 'P'): + case MKTAG('S', 'O', 'N', 'G'): + case MKTAG('S', 'P', 'R', 'T'): + case MKTAG('T', 'E', 'A', 'M'): + case MKTAG('T', 'V', 'S', 'H'): + tagId = MKTAG('E', 'N', 'T', 'N'); + break; + case MKTAG('A', 'C', 'T', 'R'): + case MKTAG('A', 'C', 'T', 'S'): + case MKTAG('A', 'U', 'T', 'H'): + case MKTAG('B', 'A', 'R', 'K'): + case MKTAG('B', 'A', 'R', 'U'): + case MKTAG('B', 'L', 'F', '1'): + case MKTAG('B', 'L', 'F', '2'): + case MKTAG('B', 'L', 'P', '1'): + case MKTAG('B', 'L', 'P', '2'): + case MKTAG('B', 'L', 'P', '3'): + case MKTAG('B', 'L', 'P', '4'): + case MKTAG('B', 'L', 'R', '1'): + case MKTAG('B', 'L', 'R', '2'): + case MKTAG('B', 'L', 'T', '1'): + case MKTAG('B', 'L', 'T', '2'): + case MKTAG('B', 'L', 'T', '3'): + case MKTAG('B', 'L', 'T', '4'): + case MKTAG('B', 'L', 'T', '5'): + case MKTAG('B', 'O', 'Y', 'S'): + case MKTAG('C', 'O', 'P', 'S'): + case MKTAG('D', 'C', 'T', 'R'): + case MKTAG('F', 'A', 'M', 'E'): + case MKTAG('F', 'A', 'S', 'H'): + case MKTAG('G', 'I', 'R', 'L'): + case MKTAG('H', 'E', 'R', 'O'): + case MKTAG('H', 'O', 'S', 'T'): + case MKTAG('K', 'N', 'O', 'B'): + case MKTAG('N', 'H', 'R', 'O'): + case MKTAG('R', 'A', 'C', 'E'): + case MKTAG('S', 'C', 'I', 'T'): + case MKTAG('T', 'D', 'V', 'P'): + case MKTAG('T', 'W', 'A', 'T'): + case MKTAG('W', 'E', 'A', 'T'): + case MKTAG('W', 'W', 'E', 'B'): + tagId = MKTAG('P', 'R', 'S', 'N'); + break; + case MKTAG('C', 'H', 'S', 'E'): + case MKTAG('C', 'M', 'N', 'T'): + case MKTAG('F', 'I', 'L', 'M'): + case MKTAG('J', 'F', 'O', 'D'): + case MKTAG('L', 'I', 'Q', 'D'): + tagId = MKTAG('F', 'O', 'O', 'D'); + break; + case MKTAG('C', 'R', 'I', 'M'): + case MKTAG('C', 'S', 'P', 'Y'): + case MKTAG('D', 'R', 'U', 'G'): + tagId = MKTAG('V', 'B', 'A', 'D'); + break; + case MKTAG('E', 'A', 'R', 'T'): + case MKTAG('H', 'O', 'M', 'E'): + case MKTAG('N', 'P', 'L', 'C'): + case MKTAG('P', 'L', 'A', 'N'): + tagId = MKTAG('P', 'L', 'A', 'C'); + break; + case MKTAG('F', 'A', 'U', 'N'): + case MKTAG('F', 'I', 'S', 'H'): + case MKTAG('F', 'L', 'O', 'R'): + tagId = MKTAG('N', 'A', 'T', 'R'); + break; + case MKTAG('H', 'H', 'L', 'D'): + case MKTAG('T', 'O', 'Y', 'S'): + case MKTAG('W', 'E', 'A', 'P'): + tagId = MKTAG('M', 'A', 'C', 'H'); + break; + case MKTAG('M', 'L', 'T', 'Y'): + case MKTAG('P', 'G', 'R', 'P'): + case MKTAG('P', 'T', 'I', 'C'): + tagId = MKTAG('G', 'R', 'U', 'P'); + break; + case MKTAG('P', 'K', 'U', 'P'): + case MKTAG('S', 'E', 'X', '1'): + case MKTAG('S', 'W', 'E', 'R'): + tagId = MKTAG('R', 'U', 'D', 'E'); + break; + case MKTAG('P', 'H', 'I', 'L'): + case MKTAG('R', 'C', 'K', 'T'): + tagId = MKTAG('S', 'C', 'I', 'E'); + break; + case MKTAG('T', 'R', 'A', '2'): + case MKTAG('T', 'R', 'A', '3'): + tagId = MKTAG('T', 'R', 'A', 'V'); + break; + default: + break; + } + + return TTnpcScript::handleQuote(roomScript, sentence, val, tagId, remainder); + +} + +int DeskbotScript::updateState(uint oldId, uint newId, int index) { + if (isDial1Medium() || getValue(1) < 4) + CTrueTalkManager::setFlags(22, 1); + + if (newId == 240420 || newId == 240947 || newId == 241261) { + if (getValue(22) && (newId == 240947 || newId == 241261)) + newId = getRangeValue(241184); + } + + if (newId == 240832) + setDialRegion(1, 0); + + if (oldId == 241183) { + if (getValue(1) == 2) + newId = getRangeValue(241182); + else if (getValue(1) == 1) + newId = getRangeValue(241181); + } + + if (newId == 240931 && getValue(1) <= 2) { + newId = 240924; + } else if (newId == 240924 && getValue(1) > 2) { + newId = 240931; + } + + if (newId == 240830 && getValue(1) == 1) { + newId = 240801; + } else if (newId == 240801 && getValue(1) > 1) { + newId = 240830; + } + + if (oldId >= 241217 && oldId <= 241259) { + addResponse(getDialogueId(241202)); + addResponse(getDialogueId(241200)); + newId = getRangeValue(241199); + } + + if (newId == 241354) + newId = addAssignedRoomDialogue2(); + if (newId == 241353) + newId = getStateDialogueId(); + if (newId == 240464 && getValue(1) != 1) + newId = 240462; + + if (newId == 241635 && isDial1Medium()) { + addResponse(getDialogueId(241556)); + newId = getRangeValue(241632); + } + + if (getValue(20) && (oldId == 240569 || oldId == 240576)) + newId = 240460; + if (!getValue(20)) { + if (newId != 240460) + goto exit; + CTrueTalkManager::setFlags(20, 1); + } + if (newId == 240460 && _oldId != 240569) { + CTrueTalkManager::setFlags(20, 0); + newId = 240455; + } + +exit: + _oldId = oldId; + setFlags17(newId, index); + + return newId; +} + +int DeskbotScript::preResponse(uint id) { + int newId = 0; + if (getValue(1) >= 3 && (id == 41176 || id == 41738 || id == 41413 || id == 41740)) + newId = 241601; + + if (id == 42114) + CTrueTalkManager::triggerAction(20, 0); + + return newId; +} + +uint DeskbotScript::getDialsBitset() const { + if (getDialRegion(1)) + return getDialRegion(0) ? 2 : 3; + else + return getDialRegion(0) ? 0 : 1; +} + +int DeskbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + uint id; + + switch (val1) { + case 1: + id = *srcIdP; + if (id == 240431 || id == 240432) { + switch (getValue(1)) { + case 1: + id = 240336; + break; + case 2: + id = addAssignedRoomDialogue(); + break; + case 3: + if (getValue(3) == 1) { + if (id == 240431) + id = 240432; + } + else { + if (id == 240432) + id = 240431; + } + default: + break; + } + + addResponse(getDialogueId(id)); + applyResponse(); + return 2; + } + break; + + case 2: + if (getValue(1) == 1) + return true; + break; + + default: + break; + } + + return 0; +} + +bool DeskbotScript::randomResponse(uint index) { + if (getValue(1) == 1 || getRandomNumber(100) > 10 || getRandomNumber(2) <= index) + return 0; + + if (getRandomNumber(100) > 95) { + deleteResponses(); + addResponse(getDialogueId(241195)); + applyResponse(); + } else { + setResponseFromArray(index, 241193); + } + + return true; +} + +bool DeskbotScript::isDial0Medium() const { + return getDialRegion(0) == 1; +} + +bool DeskbotScript::isDial0Low() const { + return getDialRegion(0) == 0; +} + +bool DeskbotScript::isDial1Medium() const { + return getDialRegion(1) == 1; +} + +bool DeskbotScript::isDial1Low() const { + return getDialRegion(1) == 0; +} + +uint DeskbotScript::addAssignedRoomDialogue() { + if (isDial1Medium()) { + addResponse(getDialogueId(240407)); + addResponse(getDialogueId(241510)); + CTrueTalkManager::setFlags(1, 1); + CTrueTalkManager::triggerAction(19, 1); + + int roomNum, floorNum, elevatorNum; + getAssignedRoom(&roomNum, &floorNum, &elevatorNum); + + addResponse(getDialogueId(241317 + roomNum)); + addResponse(getDialogueId(241271 + floorNum)); + addResponse(getDialogueId(241511)); + addResponse(getDialogueId(241313 + elevatorNum)); + + return 241512; + } else { + return 240567; + } +} + +uint DeskbotScript::addAssignedRoomDialogue2() { + addResponse(getDialogueId(241355)); + int roomNum = 0, floorNum = 0, elevatorNum = 0; + getAssignedRoom(&roomNum, &floorNum, &elevatorNum); + + addResponse(getDialogueId(241317 + roomNum)); + addResponse(getDialogueId(241271 + floorNum)); + addResponse(getDialogueId(241356)); + addResponse(getDialogueId(241313 + elevatorNum)); + + return 241357; +} + +void DeskbotScript::addAssignedRoomDialogue3() { + addResponse(getDialogueId(241513)); + addResponse(getDialogueId(241510)); + + CTrueTalkManager::setFlags(1, 2); + setDialRegion(0, 0); + setDialRegion(1, 0); + CTrueTalkManager::triggerAction(19, 2); + CTrueTalkManager::setFlags(3, 0); + + int roomNum = 1, floorNum = 1, elevatorNum = 1; + getAssignedRoom(&roomNum, &floorNum, &elevatorNum); + + addResponse(getDialogueId(241317 + roomNum)); + addResponse(getDialogueId(241271 + floorNum)); + addResponse(getDialogueId(241511)); + addResponse(getDialogueId(241313 + elevatorNum)); + addResponse(getDialogueId(241512)); + applyResponse(); +} + +uint DeskbotScript::getStateDialogueId() const { + switch (getValue(1)) { + case 1: + return 241503; + case 2: + return 241504; + default: + return 241505; + } +} + +void DeskbotScript::setFlags17(uint newId, uint index) { + int newValue = getValue(17); + + for (uint idx = 0; idx < _states.size(); ++idx) { + const TTupdateState &us = _states[idx]; + if (newId == (idx == 0 ? 0 : us._newId)) { + uint bits = us._dialBits; + + if (!bits + || (index == 1 && (bits & 1) && (bits & 4)) + || (index == 0 && (bits & 2) && (bits & 4)) + || (index == 3 && (bits & 1) && (bits & 8)) + || (index == 2 && (bits & 2) && (bits & 8))) { + newValue = us._newValue; + break; + } + } + } + + CTrueTalkManager::setFlags(17, newValue); +} + +int DeskbotScript::preprocess(const TTroomScript *roomScript, const TTsentence *sentence) { + if (!roomScript || !sentence) + return 1; + + bool stateFlag = true, applyFlag = false; + switch (getValue(17)) { + case 1: + if (sentence->_field2C != 3 && sentence->_field2C != 4 + && sentence->_field2C != 6 && sentence->_field2C != 10 + && sentence->_field2C != 2) { + addResponse(getDialogueId(240423)); + applyFlag = true; + } + break; + + case 2: + if (sentence->localWord("gobbledygook")) { + addResponse(getDialogueId(240427)); + applyFlag = true; + } + break; + + case 3: + if (sentence->_field2C == 11 || sentence->_field2C == 13 + || sentence->_field2C == 3 || sentence->localWord("upgrade")) { + addResponse(getDialogueId(240433)); + applyFlag = true; + } + break; + + case 4: + addResponse(getDialogueId(sentence->_field2C == 11 || sentence->_field2C == 13 + ? 240495 : 240494)); + applyFlag = true; + break; + + case 5: + if (isDial1Low() && getValue(1) == 4) { + if (sentence->localWord("name") || sentence->localWord("called") + || sentence->localWord("passenger")) { + addResponse(getDialogueId(240867)); + addResponse(getDialogueId(240745)); + } else { + addResponse(getDialogueId(240446)); + } + + applyFlag = true; + stateFlag = false; + } + break; + + case 6: + if (isDial1Low() && getValue(1) == 4) { + if (sentence->localWord("passenger")) { + addResponse(getDialogueId(240449)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("home") + || sentence->localWord("destroy")) { + addResponse(getDialogueId(240574)); + stateFlag = true; + } else if (sentence->localWord("name") + || sentence->localWord("called") + || sentence->_field2C == 11) { + addResponse(getDialogueId(240448)); + stateFlag = true; + } else { + addResponse(getDialogueId(240489)); + stateFlag = true; + } + } + break; + + case 7: + if (sentence->_field2C == 11 || sentence->_field2C == 13 + || (sentence->localWord("what") && sentence->localWord("wrong")) + || sentence->localWord("clothes")) { + addResponse(getDialogueId(240489)); + applyFlag = true; + stateFlag = false; + } + break; + + case 8: + if (isDial1Low() && getValue(1) == 4) { + if (sentence->_field2C == 12 || sentence->_field2C == 13 + || sentence->contains("do not")) { + + addResponse(getDialogueId(240447)); + setDialRegion(0, 0); + setDialRegion(1, 0); + CTrueTalkManager::setFlags(1, 3); + CTrueTalkManager::triggerAction(19, 3); + CTrueTalkManager::setFlags(22, 1); + applyFlag = true; + } else if (sentence->_field2C == 11) { + addResponse(getDialogueId(240746)); + applyFlag = true; + stateFlag = false; + } else { + addResponse(getDialogueId(240448)); + applyFlag = true; + stateFlag = false; + } + } + break; + + case 9: + if (searchQuotes(roomScript, sentence)) { + if (isDial0Medium()) { + addResponse(getDialogueId(240382)); + applyFlag = true; + stateFlag = false; + } else { + addResponse(getDialogueId(240548)); + applyFlag = true; + } + } + break; + + case 10: + if (isDial1Medium() && searchQuotes(roomScript, sentence)) { + if (isDial0Medium()) { + addResponse(getDialogueId(240405)); + applyFlag = true; + stateFlag = false; + } else { + addResponse(getDialogueId(240548)); + applyFlag = true; + } + } + break; + + case 11: + if (isDial0Medium() && isDial1Medium() + && searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240403)); + applyFlag = true; + stateFlag = false; + } + break; + + case 12: + if (isDial0Medium() && isDial1Medium() + && searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240548)); + applyFlag = true; + stateFlag = false; + } + break; + + case 13: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240348)); + applyFlag = true; + stateFlag = false; + } + break; + + case 14: + if (isDial1Medium()) { + addResponse(getDialogueId(240568)); + applyFlag = true; + stateFlag = false; + } + break; + + case 15: + if (sentence->localWord("magazine")) { + addAssignedRoomDialogue3(); + stateFlag = true; + } + break; + + case 17: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240401)); + applyFlag = true; + stateFlag = false; + } + break; + + case 18: + if (!isDial0Low() || !isDial1Low()) { + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240402)); + applyFlag = true; + stateFlag = false; + } + } + break; + + case 19: + if (!isDial0Low() && searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240403)); + applyFlag = true; + stateFlag = false; + } + break; + + case 20: + if (!isDial1Medium() && searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240548)); + applyFlag = true; + } + break; + + case 21: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240382)); + applyFlag = true; + stateFlag = false; + } + break; + + case 22: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240383)); + applyFlag = true; + stateFlag = false; + } + break; + + case 23: + if (isDial0Medium() && searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240384)); + applyFlag = true; + stateFlag = false; + } + break; + + case 24: + setDialRegion(0, 0); + + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240548)); + applyFlag = true; + } + break; + + case 25: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240349)); + applyFlag = true; + stateFlag = false; + } + break; + + case 26: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240350)); + applyFlag = true; + stateFlag = false; + } + break; + + case 27: + case 30: + case 33: + case 36: + case 40: + case 43: + case 46: + case 50: + case 55: + case 58: + case 61: + case 68: + case 73: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240548)); + applyFlag = true; + } + break; + + case 28: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240373)); + applyFlag = true; + stateFlag = false; + } + break; + + case 29: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240374)); + applyFlag = true; + stateFlag = false; + } + break; + + case 31: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240346)); + applyFlag = true; + stateFlag = false; + } + break; + + case 32: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240347)); + applyFlag = true; + stateFlag = false; + } + break; + + case 34: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240376)); + applyFlag = true; + stateFlag = false; + } + break; + + case 35: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240377)); + applyFlag = true; + stateFlag = false; + } + break; + + case 37: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240369)); + applyFlag = true; + stateFlag = false; + } + break; + + case 38: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240370)); + applyFlag = true; + stateFlag = false; + } + break; + + case 39: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240371)); + applyFlag = true; + stateFlag = false; + } + break; + + case 41: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240352)); + applyFlag = true; + stateFlag = false; + } + break; + + case 42: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240353)); + applyFlag = true; + stateFlag = false; + } + break; + + case 44: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240389)); + applyFlag = true; + stateFlag = false; + } + break; + + case 45: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240390)); + applyFlag = true; + stateFlag = false; + } + break; + + case 47: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240395)); + applyFlag = true; + stateFlag = false; + } + break; + + case 48: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240396)); + applyFlag = true; + stateFlag = false; + } + break; + + case 49: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240397)); + applyFlag = true; + stateFlag = false; + } + break; + + case 51: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240363)); + applyFlag = true; + stateFlag = false; + } + break; + + case 52: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240364)); + applyFlag = true; + stateFlag = false; + } + break; + + case 53: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240365)); + applyFlag = true; + stateFlag = false; + } + break; + + case 54: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240366)); + applyFlag = true; + stateFlag = false; + } + break; + + case 56: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240392)); + applyFlag = true; + stateFlag = false; + } + break; + + case 57: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240393)); + applyFlag = true; + stateFlag = false; + } + break; + + case 59: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240386)); + applyFlag = true; + stateFlag = false; + } + break; + + case 60: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240387)); + applyFlag = true; + stateFlag = false; + } + break; + + case 62: + if (isDial1Medium() && getValue(1) == 1) { + if (isDial0Medium()) { + if (sentence->localWord("down")) { + addResponse(getDialogueId(240413)); + applyFlag = true; + } + } else if (sentence->contains("left") || sentence->contains("right")) { + addResponse(getDialogueId(240415)); + CTrueTalkManager::triggerAction(sentence->localWord("down") ? 22 : 23, 0); + } else { + addResponse(getDialogueId(240414)); + applyFlag = true; + } + } + break; + + case 63: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240836)); + applyFlag = true; + stateFlag = false; + } + break; + + case 64: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240837)); + applyFlag = true; + stateFlag = false; + } + break; + + case 65: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240838)); + applyFlag = true; + stateFlag = false; + } + break; + + case 66: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240839)); + applyFlag = true; + stateFlag = false; + } + break; + + case 67: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(240840)); + applyFlag = true; + stateFlag = false; + } + break; + + case 69: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(241104)); + applyFlag = true; + stateFlag = false; + } + break; + + case 70: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(241105)); + applyFlag = true; + stateFlag = false; + } + break; + + case 71: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(241106)); + applyFlag = true; + stateFlag = false; + } + break; + + case 72: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(241107)); + applyFlag = true; + stateFlag = false; + } + break; + + case 74: + case 75: + if (sentence->_field2C == 24) { + addResponse(getDialogueId(240972)); + applyFlag = true; + } else if (sentence->localWord("good") || sentence->localWord("yes") + || sentence->localWord("well") || sentence->localWord("ill") + || sentence->localWord("sad")) { + addResponse(getDialogueId(240805)); + applyFlag = true; + } + break; + + case 76: + if (sentence->_field2C == 6) { + addResponse(getDialogueId(240767)); + applyFlag = true; + stateFlag = false; + } + break; + + case 77: + if (sentence->_field2C == 3) { + addResponse(getDialogueId(241109)); + applyFlag = true; + stateFlag = false; + } + + case 78: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(241262)); + } else if (sentence->_field2C == 12 || sentence->contains("do not")) { + setDialRegion(0, 0); + setDialRegion(1, 0); + addResponse(getDialogueId(241268)); + add241716(); + } else { + addResponse(getDialogueId(240745)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 79: + switch (checkCommonWords(sentence)) { + case 1: + addResponse(getDialogueId(241263)); + break; + case 2: + addResponse(getDialogueId(241266)); + break; + case 3: + addAssignedRoom(); + setState(0); + CTrueTalkManager::setFlags(17, 0); + return 2; + default: + addResponse(getDialogueId(241267)); + break; + } + + add241716(); + applyFlag = true; + stateFlag = false; + break; + + case 81: + addResponse(getDialogueId(sentence->_field2C == 12 ? 240602 : 241337)); + applyResponse(); + setState(0); + CTrueTalkManager::setFlags(17, 0); + return 2; + + case 82: + if (sentence->_field2C == 2) { + addResponse(getDialogueId(241339)); + applyFlag = true; + } + break; + + case 83: + if ((isDial1Medium() && isDial0Low()) || + (isDial1Low() && isDial0Medium())) { + if (sentence->localWord("yes") || sentence->localWord("but")) { + if (sentence->localWord("will") || sentence->localWord("do")) { + addResponse(getDialogueId(241366)); + applyFlag = true; + } + } + } + break; + + case 84: + if (sentence->_field2C == 12 || sentence->contains("vegetarian") + || sentence->contains("vegitarian")) { + addResponse(getDialogueId(241718)); + addResponse(getDialogueId(241709)); + applyFlag = true; + stateFlag = false; + } else if (sentence->contains("continental") + || sentence->contains("full") + || sentence->contains("porky") + || sentence->contains("the 1") + || sentence->contains("the 2") + || sentence->contains("former") + || sentence->contains("latter")) { + addResponse(getDialogueId(241717)); + addResponse(getDialogueId(241709)); + applyFlag = true; + stateFlag = false; + } else { + if (sentence2C(sentence)) + addResponse(getDialogueId(241707)); + addResponse(getDialogueId(241719)); + applyFlag = true; + stateFlag = false; + } + break; + + case 85: + if (sentence->_field2C == 12 || sentence->contains("bugle") + || sentence->contains("buggle") || sentence->contains("trumpet") + || sentence->contains("saxophone") || sentence->contains("kazoo") + || sentence->contains("blerontin 1") || sentence->contains("the 1") + || sentence->contains("the 2") || sentence->contains("the 3") + || sentence->contains("the 4") || sentence->contains("all of them") + || sentence->contains("the lot")) { + addResponse(getDialogueId(241710)); + addResponse(getDialogueId(241713)); + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + + addResponse(getDialogueId(241711)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 86: + if (sentence->_field2C == 12 || sentence->_field2C == 11 || sentence->contains("view")) { + addResponse(getDialogueId(241714)); + addResponse(getDialogueId(241699)); + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + + if (getRandomNumber(100) < 50) { + addResponse(getDialogueId(241715)); + } else { + addResponse(getDialogueId(241712)); + addResponse(getDialogueId(241713)); + } + + } + + applyFlag = true; + stateFlag = false; + break; + + case 87: + if (sentence->contains("corner") || sentence->contains("on the end") + || sentence->contains("balcony") || sentence->contains("neither") + || sentence->contains("the 1") || sentence->contains("the 2") + || sentence->contains("former") || sentence->contains("latter") + || sentence->contains("either")) { + addResponse(getDialogueId(241700)); + addResponse(getDialogueId(241687)); + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + + addResponse(getDialogueId(241701)); + addResponse(getDialogueId(241699)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 88: + if (sentence->contains("imperial") || sentence->contains("the 1")) { + addResponse(getDialogueId(241700)); + addResponse(getDialogueId(241739)); + } else if (sentence->contains("royal") || sentence->contains("the 2")) { + addResponse(getDialogueId(241690)); + } else if (sentence->contains("despotic") || sentence->contains("the last") + || sentence->contains("latter")) { + addResponse(getDialogueId(241688)); + } else if (sentence->contains("president") || sentence->contains("presidential") + || sentence->contains("the 3")) { + addResponse(getDialogueId(241689)); + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + + addResponse(getDialogueId(241692)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 89: + if (sentence->contains("king")) { + addResponse(getDialogueId(241691)); + } else if (sentence->contains("queen") || sentence->contains("prince") + || sentence->contains("princess") || sentence->contains("small") + || sentence->contains("the 1") || sentence->contains("the 2") + || sentence->contains("the 3") || sentence->contains("the 4") + || sentence->contains("big") || sentence->contains("large")) { + addResponse(getDialogueId(241700)); + addResponse(getDialogueId(241739)); + } else { + if (getRandomNumber(100) < 100 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + + addResponse(getDialogueId(241690)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 90: + if (sentence->contains("constitutional") || sentence->contains("const") + || sentence->contains("absolute") || sentence->contains("small") + || sentence->contains("the 1") || sentence->contains("the 2") + || sentence->contains("big") || sentence->contains("large")) { + addResponse(getDialogueId(241700)); + addResponse(getDialogueId(241739)); + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241708)); + + addResponse(getDialogueId(241691)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 91: + if (sentence->contains("benev") || sentence->contains("dict") + || sentence->contains("small") || sentence->contains("the 1") + || sentence->contains("the 2") || sentence->contains("big") + || sentence->contains("large") || sentence->contains("former") + || sentence->contains("latter")) { + addResponse(getDialogueId(241700)); + addResponse(getDialogueId(241739)); + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241708)); + + addResponse(getDialogueId(241688)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 92: + case 93: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(241077)); + addResponse(getDialogueId(241706)); + } else if (sentence->_field2C == 12) { + addAssignedRoom(); + setState(0); + CTrueTalkManager::setFlags(17, 0); + return 2; + } else if (g_vm->_trueTalkManager->_quotes.find(sentence->_normalizedLine.c_str()) + == MKTAG('F', 'I', 'S', 'H')) { + addResponse(getDialogueId(240877)); + addResponse(getDialogueId(241706)); + }else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + + addResponse(getDialogueId(241705)); + if (getRandomNumber(100) < 80) + addResponse(getDialogueId(241739)); + } + + applyFlag = true; + stateFlag = false; + break; + + case 94: + if (sentence->contains("seperate") || sentence->contains("separate") + || sentence->contains("detached") || sentence->contains("outside") + || sentence->contains("onsweet") || sentence->contains("ensuite") + || sentence->contains("suite") || sentence->contains("next door") + || sentence->contains("the 1") || sentence->contains("the 2") + || sentence->contains("former") || sentence->contains("latter") + || sentence->contains("same room")) { + addAssignedRoom(); + setState(0); + CTrueTalkManager::setFlags(17, 0); + return 2; + } else { + if (getRandomNumber(100) < 80 && sentence2C(sentence)) + addResponse(getDialogueId(241707)); + addResponse(getDialogueId(241706)); + applyFlag = true; + stateFlag = false; + } + break; + + case 95: + if (isDial1Medium()) { + if ((sentence->localWord("i") && sentence->localWord("am")) + || sentence->localWord("me")) { + addResponse(getDialogueId(240632)); + applyFlag = true; + stateFlag = false; + } + } + break; + + case 96: + if (sentence->_field2C == 2) { + addResponse(getDialogueId(241350)); + applyFlag = true; + stateFlag = false; + } + break; + + case 97: + if (searchQuotes(roomScript, sentence)) { + addResponse(getDialogueId(241351)); + applyFlag = true; + stateFlag = false; + } + break; + + default: + break; + } + + if (applyFlag) + applyResponse(); + if (stateFlag) { + setState(0); + CTrueTalkManager::setFlags(17, 0); + } + + return applyFlag ? 2 : 1; +} + +int DeskbotScript::searchQuotes(const TTroomScript *roomScript, const TTsentence *sentence) { + TTtreeResult treeResult; + return g_vm->_trueTalkManager->_quotesTree.search(sentence->_normalizedLine.c_str(), + TREE_2, &treeResult, 0, 0) != -1; +} + +int DeskbotScript::checkCommonWords(const TTsentence *sentence) { + if (sentence->contains("xyzzy")) + return 3; + + const TTquotes "es = g_vm->_trueTalkManager->_quotes; + if (quotes._loaded) { + uint tagId = quotes.find(sentence->_normalizedLine.c_str()); + if (tagId == MKTAG('F', 'U', 'L', 'N') + || tagId == MKTAG('T', 'D', 'V', 'P') + || tagId == MKTAG('H', 'E', 'R', 'O') + || sentence->contains("douglas adam")) + return 1; + else if (tagId == MKTAG('J', 'N', 'A', 'M') + || tagId == MKTAG('N', 'I', 'K', 'N') + || tagId == MKTAG('B', 'O', 'Y', 'S') + || tagId == MKTAG('G', 'I', 'R', 'L')) + return 2; + } else { + if (sentence->contains("douglas adams") + || sentence->contains("shaikh") + || sentence->contains("millican") + || sentence->contains("williams") + || sentence->contains("henkes") + || sentence->contains("kenny")) + return 1; + else if (sentence->contains("richard") + || sentence->contains("jason") + || sentence->contains("mike") + || sentence->contains("renata")) + return 2; + } + + return 0; +} + +void DeskbotScript::add241716() { + addResponse(getDialogueId(241716)); +} + +void DeskbotScript::addAssignedRoom() { + addResponse(getDialogueId(241696)); + addResponse(getDialogueId(241697)); + CTrueTalkManager::setFlags(1, 3); + CTrueTalkManager::triggerAction(19, 3); + CTrueTalkManager::setFlags(22, 1); + + int roomNum = 1, floorNum = 1, elevatorNum = 1; + getAssignedRoom(&roomNum, &floorNum, &elevatorNum); + addResponse(getDialogueId(241313 + elevatorNum)); + addResponse(getDialogueId(241271 + floorNum)); + addResponse(getDialogueId(241317 + roomNum)); + addResponse(getDialogueId(241698)); +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/deskbot_script.h b/engines/titanic/true_talk/deskbot_script.h new file mode 100644 index 0000000000..f5978553ce --- /dev/null +++ b/engines/titanic/true_talk/deskbot_script.h @@ -0,0 +1,157 @@ +/* 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_DESKBOT_SCRIPT_H +#define TITANIC_DESKBOT_SCRIPT_H + +#include "common/array.h" +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class DeskbotScript : public TTnpcScript { +private: + static int _oldId; + TTupdateStateArray _states; + TTsentenceEntries _entries2; + TTsentenceEntries _entries3; +private: + /** + * Setup sentence data + */ + void setupSentences(); + + /** + * Adds dialogue for the player's assigned room + */ + uint addAssignedRoomDialogue(); + + /** + * Adds dialogue for the player's assigned room + */ + uint addAssignedRoomDialogue2(); + + /** + * Adds dialogue for the player's assigned room + */ + void addAssignedRoomDialogue3(); + + /** + * Gets a dialogue Id based on the NPC's state + */ + uint getStateDialogueId() const; + + /** + * Sets state data in flags 17 + */ + void setFlags17(uint newId, uint index); + + /** + * Does preprocessing for the sentence + */ + int preprocess(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Scans the quotes tree + */ + int searchQuotes(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Checks for common words + */ + int checkCommonWords(const TTsentence *sentence); + + /** + * Adds response dialogue 241716 + */ + void add241716(); + + /** + * Adds a dialogue description for the player's assigned room + */ + void addAssignedRoom(); +public: + DeskbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); + + /** + * Returns a bitset of the first three dialgs being on or not + */ + virtual uint getDialsBitset() const; + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Handles a randomzied response + */ + virtual bool randomResponse(uint index); + + /** + * Returns true if dial 1 is the medium (1) region + */ + virtual bool isDial0Medium() const; + + /** + * Returns true if dial 0 is the low end region + */ + virtual bool isDial0Low() const; + + /** + * Returns true if dial 1 is the medium (1) region + */ + bool isDial1Medium() const; + + /** + * Returns true if dial 1 is the low end region + */ + virtual bool isDial1Low() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DESKBOT_SCRIPT_H */ diff --git a/engines/titanic/true_talk/dialogue_file.cpp b/engines/titanic/true_talk/dialogue_file.cpp new file mode 100644 index 0000000000..34eb164779 --- /dev/null +++ b/engines/titanic/true_talk/dialogue_file.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 "titanic/true_talk/dialogue_file.h" + +namespace Titanic { + +void DialogueIndexEntry::load(Common::SeekableReadStream &s) { + _v1 = s.readUint32LE(); + _offset = s.readUint32LE(); +} + +/*------------------------------------------------------------------------*/ + +CDialogueFile::CDialogueFile(const CString &filename, uint count) { + if (!_file.open(filename)) + error("Could not locate dialogue file - %s", filename.c_str()); + + _cache.resize(count); + + _file.readUint32LE(); // Skip over file Id + _index.resize(_file.readUint32LE()); + + // Read in the entries + for (uint idx = 0; idx < _index.size(); ++idx) + _index[idx].load(_file); +} + +CDialogueFile::~CDialogueFile() { + clear(); +} + +void CDialogueFile::clear() { + _file.close(); +} + +DialogueResource *CDialogueFile::addToCache(int index) { + if (_index.size() == 0 || index < 0 || index >= (int)_index.size() + || _cache.empty()) + return nullptr; + + // Scan cache for a free slot + uint cacheIndex = 0; + while (cacheIndex < _cache.size() && !_cache[cacheIndex]._active) + ++cacheIndex; + if (cacheIndex == _cache.size()) + return nullptr; + + DialogueIndexEntry &indexEntry = _index[index]; + DialogueResource &res = _cache[cacheIndex]; + + res._active = true; + res._offset = indexEntry._offset; + res._bytesRead = 0; + res._entryPtr = &indexEntry; + + // Figure out the size of the entry + if (index == ((int)_index.size() - 1)) { + res._size = _file.size() - indexEntry._offset; + } else { + res._size = _index[index + 1]._offset - indexEntry._offset; + } + + // Return a pointer to the loaded entry + return &res; +} + +bool CDialogueFile::closeEntry(DialogueResource *cacheEntry) { + if (!cacheEntry || !cacheEntry->_active) + return false; + + cacheEntry->_active = false; + return true; +} + +bool CDialogueFile::read(DialogueResource *cacheEntry, byte *buffer, size_t bytesToRead) { + // Sanity checks that a valid record is passed, and the size can be read + if (!cacheEntry || !cacheEntry->_active || !bytesToRead + || (cacheEntry->_bytesRead + bytesToRead) > cacheEntry->_size) + return false; + + // Move to the correct position in the file + _file.seek(cacheEntry->_offset + cacheEntry->_bytesRead); + bool result = _file.read(buffer, bytesToRead) == bytesToRead; + cacheEntry->_bytesRead += bytesToRead; + + return result; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/dialogue_file.h b/engines/titanic/true_talk/dialogue_file.h new file mode 100644 index 0000000000..19e94cf9b9 --- /dev/null +++ b/engines/titanic/true_talk/dialogue_file.h @@ -0,0 +1,100 @@ +/* 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_DIALOGUE_FILE_H +#define TITANIC_DIALOGUE_FILE_H + +#include "titanic/support/simple_file.h" +#include "titanic/support/string.h" + +namespace Titanic { + +struct DialogueIndexEntry { + uint _v1, _offset; + + DialogueIndexEntry() : _v1(0), _offset(0) {} + void load(Common::SeekableReadStream &s); +}; + +struct DialogueResource { + bool _active; + uint _offset, _bytesRead, _size; + DialogueIndexEntry *_entryPtr; + + DialogueResource() : _active(false), _offset(0), + _bytesRead(0), _size(0), _entryPtr(nullptr) {} + + /** + * Return the size of a cache entry + */ + size_t size() const { return _active ? _size : 0; } +}; + +class CDialogueFile { +private: + File _file; + Common::Array<DialogueIndexEntry> _index; + Common::Array<DialogueResource> _cache; +private: + /** + * Add a dialogue file entry to the active cache + */ + DialogueResource *addToCache(int index); +public: + CDialogueFile(const CString &filename, uint count); + ~CDialogueFile(); + + /** + * Clear the loaded data + */ + void clear(); + + File *getFile() { return &_file; } + + /** + * Sets up a text entry within the dialogue file for access + */ + DialogueResource *openTextEntry(int index) { + return addToCache(index * 2); + } + + /** + * Sets up a wave (sound) entry within the dialogue file for access + */ + DialogueResource *openWaveEntry(int index) { + return addToCache(index * 2 + 1); + } + + /** + * Removes an entry from the cache + */ + bool closeEntry(DialogueResource *cacheEntry); + + /** + * Read data for a resource + */ + bool read(DialogueResource *cacheEntry, byte *buffer, size_t bytesToRead); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TITLE_ENGINE_H */ diff --git a/engines/titanic/true_talk/doorbot_script.cpp b/engines/titanic/true_talk/doorbot_script.cpp new file mode 100644 index 0000000000..1ca1ab13e5 --- /dev/null +++ b/engines/titanic/true_talk/doorbot_script.cpp @@ -0,0 +1,1013 @@ +/* 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/true_talk/doorbot_script.h" +#include "titanic/true_talk/tt_room_script.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +static const int STATE_ARRAY[9] = { + 0x2E2A, 0x2E2B, 0x2E2C, 0x2E2D, 0x2E2E, 0x2E2F, 0x2E30, 0x2E31, 0x2E32 +}; + +static const RoomDialogueId ROOM_DIALOGUES1[] = { + { 100, 10523 }, { 101, 10499 }, { 107, 10516 }, { 108, 10500 }, + { 109, 10490 }, { 110, 10504 }, { 111, 10506 }, { 112, 10498 }, + { 113, 10502 }, { 114, 10507 }, { 115, 10497 }, { 116, 10508 }, + { 117, 10505 }, { 118, 10505 }, { 122, 10516 }, { 123, 10383 }, + { 124, 10510 }, { 125, 10511 }, { 126, 10513 }, { 127, 10512 }, + { 128, 10495 }, { 129, 10496 }, { 130, 10491 }, { 131, 10493 }, + { 132, 10492 }, { 0, 0 } +}; +static const RoomDialogueId ROOM_DIALOGUES2[] = { + { 102, 221981 }, { 110, 221948 }, { 111, 221968 }, { 107, 222000 }, + { 101, 221935 }, { 112, 221924 }, { 113, 221942 }, { 116, 221977 }, + { 124, 221987 }, { 125, 221984 }, { 127, 221991 }, { 128, 221916 }, + { 129, 221919 }, { 131, 221912 }, { 132, 221908 }, { 0, 0 } +}; + +DoorbotScript::DoorbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, v4, v5, v6, v7) { + loadRanges("Ranges/Doorbot"); + loadResponses("Responses/Doorbot"); + setupSentences(); + _tagMappings.load("TagMap/Doorbot"); + _words.load("Words/Doorbot"); + _quotes.load("Quotes/Doorbot"); + _states.load("States/Doorbot"); +} + +void DoorbotScript::setupSentences() { + for (int idx = 35; idx < 40; ++idx) + CTrueTalkManager::setFlags(idx, 0); + _doorbotState = 1; + _field68 = 0; + _entryCount = 0; + _dialValues[0] = _dialValues[1] = 100; + + _mappings.load("Mappings/Doorbot", 4); + _entries.load("Sentences/Doorbot"); + + static const int SENTENCE_NUMS[11] = { + 2, 100, 101, 102, 107, 110, 111, 124, 129, 131, 132 + }; + for (int idx = 0; idx < 11; ++idx) { + _sentences[idx] = TTsentenceEntries(); + _sentences[idx].load(CString::format("Sentences/Doorbot/%d", SENTENCE_NUMS[idx])); + } +} + +int DoorbotScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + if (tag == MKTAG('D', 'N', 'A', '1') || tag == MKTAG('H', 'H', 'G', 'Q') || + tag == MKTAG('A', 'N', 'S', 'W') || tag == MKTAG('S', 'U', 'M', 'S')) { + if (_stateIndex > 9) + _stateIndex = 0; + addResponse(STATE_ARRAY[_stateIndex]); + applyResponse(); + + if (STATE_ARRAY[_stateIndex] == 11826) + setState(1); + ++_stateIndex; + return 2; + } + + if (tag == MKTAG('C', 'H', 'S', 'E') || tag == MKTAG('C', 'M', 'N', 'T') || + tag == MKTAG('J', 'F', 'O', 'D')) + tag = MKTAG('F', 'O', 'O', 'D'); + + if (tag == MKTAG('F', 'O', 'O', 'D') && roomScript->_scriptId == 132) { + return setResponse(getDialogueId(220818)); + } + + if (tag == MKTAG('T', 'R', 'A', 'V')) { + return setResponse(11858 - getRandomBit()); + } else if (tag == MKTAG('C', 'S', 'P', 'Y')) { + return setResponse(10405, 3); + } else if (tag == MKTAG('S', 'C', 'I', 'T')) { + return setResponse(10410, 14); + } else if (tag == MKTAG('L', 'I', 'T', 'E')) { + return setResponse(10296, 17); + } else if (tag == MKTAG('D', 'O', 'R', '1')) { + return setResponse(getDialogueId(222034)); + } else if (tag == MKTAG('W', 'T', 'H', 'R')) { + return setResponse(getDialogueId(222126)); + } else if (tag == MKTAG('N', 'A', 'U', 'T')) { + return setResponse(getDialogueId(222259)); + } else if (tag == MKTAG('T', 'R', 'A', '2')) { + return setResponse(getRandomBit() ? 11860 : 11859); + } else if (tag == MKTAG('T', 'R', 'A', '3')) { + return setResponse(getRandomBit() ? 11859 : 11858); + } else if (tag == MKTAG('B', 'R', 'N', 'D')) { + switch (getRandomNumber(3)) { + case 1: + tag = MKTAG('B', 'R', 'N', '2'); + break; + case 2: + tag = MKTAG('B', 'R', 'N', '3'); + break; + default: + break; + } + } + + return TTnpcScript::chooseResponse(roomScript, sentence, tag); +} + +int DoorbotScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + int currState; + + switch (roomScript->_scriptId) { + case 100: + case 101: + case 102: + case 103: + case 104: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 113: + case 116: + case 117: + case 118: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 132: + break; + + default: + return 2; + } + + checkItems(nullptr, nullptr); + if (getState() == 0) { + if (CTrueTalkManager::_v2 > getValue(36)) { + if (getDialRegion(1) == 1 && getRandomBit()) { + setDialRegion(0, getDialRegion(1) ? 0 : 1); + } else { + setDialRegion(1, getDialRegion(1) ? 0 : 1); + } + CTrueTalkManager::setFlags(36, CTrueTalkManager::_v2 + 3 + getRandomNumber(5)); + + if (getValue(37)) { + CTrueTalkManager::setFlags(37, 0); + setState(0); + return setResponse(getDialogueId(221140)); + } + } + } + + if (getValue(35) == 0 && roomScript->_scriptId != 100 && sentence->localWord("parrot")) { + CTrueTalkManager::setFlags(35, 1); + setState(0); + return setResponse(getDialogueId(220113)); + } + + if (sentence->_field2C == 6 && sentence->contains("why not")) { + return setResponse(11871, 8); + } + + currState = getState(); + if (currState) { + int sentMode = sentence->_field2C; + bool flag1 = sentMode == 11 || sentMode == 13; + bool flag2 = sentMode == 12; + + switch (currState) { + case 1: + if (flag1) + return setResponse(11828, 2); + if (flag2) + return setResponse(11827, 0); + break; + + case 2: + if (flag1) + return setResponse(11827, 0); + break; + + case 3: + if (sentMode == 3) + return setResponse(10406, 0); + break; + + case 4: + if (flag1) + return setResponse(11332, 0); + if (flag2) + return setResponse(11331, 0); + break; + + case 5: + return setResponse(11868, 0); + + case 6: + return setResponse(11872, 0); + + case 7: + return setResponse(11869, 0); + + case 8: + return setResponse(11870, 0); + + case 12: + if (flag1) + return setResponse(11894, 13); + if (flag2) + return setResponse(11893, 13); + break; + + case 13: + return setResponse(11895, 12); + + case 15: + if (sentMode == 3 || sentMode == 6) + return setResponse(10257, 0); + break; + + case 16: { + TTtreeResult treeResult; + if (g_vm->_trueTalkManager->_quotesTree.search(sentence->_normalizedLine.c_str(), + TREE_3, &treeResult, 0, nullptr) != -1) + return setResponse(getDialogueId(221380), 0); + break; + } + + case 17: + return setResponse(getDialogueId(221126), 0); + + case 18: + if (flag1) + return setResponse(getDialogueId(221135), 0); + if (flag2) + return setResponse(getDialogueId(221134), 0); + break; + + case 19: + if (flag1) { + if (addRandomResponse(true)) { + setState(10); + return 2; + } + } + if (flag2) + return setResponse(getDialogueId(221966), 0); + break; + + case 20: + if (flag1) { + if (addRandomResponse(true)) { + setState(19); + return 2; + } + } + if (flag2 || sentMode == 7 || sentMode == 10) { + return setResponse(getDialogueId(221879), 0); + } + break; + + case 21: + if (flag2) + return setResponse(10935, 0); + break; + + case 22: + if (flag1) { + if (getRandomBit()) { + return setResponse(11211, 23); + } else { + return setResponse(10127, 0); + } + } + if (flag2) + return setResponse(10136, 0); + break; + + case 23: + return setResponse(10212, 0); + + case 24: + if (flag1) + return setResponse(11151, 0); + if (flag2) + return setResponse(11150, 0); + break; + + case 25: + case 26: + if (flag2) { + if (getRandomBit()) { + return setResponse(11211, 23); + } else { + return setResponse(10127, 0); + } + } + if (flag1) + return setResponse(10136, 0); + break; + + case 27: + if (flag1 || sentence->localWord("did") || sentence->contains("did")) + return setResponse(221175, 28); + break; + + case 28: + if (flag1 || sentence->localWord("did") || sentence->contains("did")) + return setResponse(getDialogueId(221176), 29); + break; + + case 29: + if (flag1 || sentence->localWord("did") || sentence->contains("did")) + return setResponse(getDialogueId(221177), 30); + break; + + case 30: + return setResponse(getDialogueId(221178), 31); + + case 31: + if (sentMode == 3 || sentMode == 10) + return setResponse(10350, 0); + break; + + case 32: + return setResponse(10110, 0); + + case 33: + if (sentence->contains("sieve") || sentence->contains("colander") + || sentence->contains("vegetable") || sentence->contains("ground") + || sentence->contains("earth") || sentence->contains("garden") + || sentence->contains("cheese") || sentence->contains("strainer")) { + return setResponse(getDialogueId(221375), 0); + } else if (getRandomNumber(100) > 30) { + return setResponse(getDialogueId(221376), 33); + } else { + return setResponse(getDialogueId(221376), 0); + } + break; + + case 34: + if (sentence->localWord("bellbot")) + return setResponse(10094, 0); + if (sentence->localWord("bellbot")) + return setResponse(10349, 0); + if (sentence->localWord("deskbot") || sentence->localWord("titania")) + return setResponse(10148, 0); + if (sentence->localWord("barbot") || sentence->localWord("rowbot") + || sentence->localWord("liftbot") || sentence->localWord("maitredbot")) + return setResponse(10147, 0); + break; + + case 35: + return setResponse(10811, 36); + + case 36: + if (flag1) + return setResponse(10813, 37); + if (flag2) + return setResponse(10812, 37); + break; + + case 37: + if (flag1) + return setResponse(10815, 37); + if (flag2) + return setResponse(10814, 37); + break; + + case 38: + return setResponse(10848, 39); + + case 39: + return setResponse(10823, 40); + + case 40: + return setResponse(10832, 41); + + case 41: + addResponse(10833); + return setResponse(10835, 0); + + case 42: + if (sentence->localWord("please")) + return setResponse(10840, 43); + return setResponse(10844, 0); + + case 43: + case 45: + return setResponse(10844, 0); + + case 44: + if (sentence->localWord("thanks")) + return setResponse(10843, 45); + return setResponse(10844, 0); + + case 46: + if (flag1) + return setResponse(getDialogueId(222251), 0); + if (flag2) + return setResponse(10713, 0); + break; + + } + } + + if (currState != 14) + setState(0); + + if (getDialRegion(1) != 1 && getRandomNumber(100) > 92) + return setResponse(getDialogueId(221043), 0); + + int result = 0; + switch (roomScript->_scriptId) { + case 100: + case 101: + case 102: + case 107: + case 110: + case 111: + case 124: + case 129: + case 131: + case 132: + result = processEntries(&_sentences[roomScript->_scriptId], 0, roomScript, sentence); + break; + default: + break; + } + if (result == 2) + return 2; + + if (processEntries(&_entries, _entryCount, roomScript, sentence) == 2 + || processEntries(_defaultEntries, 0, roomScript, sentence) == 2 + || defaultProcess(roomScript, sentence)) + return 2; + + switch (sentence->_field2C) { + case 11: + if (getRandomNumber(100) > 90) + return setResponse(10839, 42); + return setResponse(222415, 0); + + case 12: + if (getRandomNumber(100) > 90) + return setResponse(10841, 44); + return setResponse(getDialogueId(222416), 0); + + case 13: + return setResponse(getDialogueId(222415), 0); + + default: + if (getRandomNumber(100) > 75 && getStateValue()) + return setResponse(getDialogueId(221095)); + + if (processEntries(&_sentences[2], 0, roomScript, sentence) != 2) + return setResponse(getDialogueId(220000)); + break; + } + + return 2; +} + +ScriptChangedResult DoorbotScript::scriptChanged(const TTroomScript *roomScript, uint id) { + if (id == 3) { + if (roomScript != nullptr && roomScript->_scriptId != 100) { + if (CTrueTalkManager::_v9 == 101) { + addResponse(getDialogueId(220873)); + applyResponse(); + } else { + bool flag = false; + if (CTrueTalkManager::_currentNPC) { + CGameObject *obj; + if (CTrueTalkManager::_currentNPC->find("Magazine", &obj, FIND_PET)) { + setResponse(getDialogueId(222248), 46); + flag = true; + } + } + + if (!flag) { + if (getRandomNumber(100) > 80 && getStateValue()) { + addResponse(getDialogueId(221095)); + applyResponse(); + flag = true; + } + + if (!flag && (_doorbotState || !fn10(true))) { + addResponse(getDialogueId(220074)); + applyResponse(); + } + } + } + } + + _doorbotState = 0; + resetFlags(); + CTrueTalkManager::_v9 = 0; + } else if (id == 4) { + setState(0); + if (getValue(38) == 0) { + addResponse(getDialogueId(220883)); + applyResponse(); + } + + CTrueTalkManager::setFlags(38, 0); + CTrueTalkManager::setFlags(39, 0); + } + + if (id >= 220000 && id <= 222418) { + addResponse(getDialogueId(id)); + applyResponse(); + } else if (id >= 10000 && id <= 11986) { + addResponse(id); + applyResponse(); + } + + return SCR_2; +} + +int DoorbotScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + switch (tagId) { + case MKTAG('A', 'D', 'V', 'T'): + case MKTAG('A', 'R', 'T', 'I'): + case MKTAG('A', 'R', 'T', 'Y'): + case MKTAG('B', 'R', 'N', 'D'): + case MKTAG('C', 'O', 'M', 'D'): + case MKTAG('D', 'N', 'C', 'E'): + case MKTAG('H', 'B', 'B', 'Y'): + case MKTAG('L', 'I', 'T', 'R'): + case MKTAG('M', 'A', 'G', 'S'): + case MKTAG('M', 'C', 'P', 'Y'): + case MKTAG('M', 'I', 'N', 'S'): + case MKTAG('M', 'U', 'S', 'I'): + case MKTAG('N', 'I', 'K', 'E'): + case MKTAG('S', 'F', 'S', 'F'): + case MKTAG('S', 'O', 'A', 'P'): + case MKTAG('S', 'O', 'N', 'G'): + case MKTAG('S', 'P', 'R', 'T'): + case MKTAG('T', 'E', 'A', 'M'): + case MKTAG('T', 'V', 'S', 'H'): + case MKTAG('W', 'W', 'E', 'B'): + tagId = MKTAG('E', 'N', 'T', 'N'); + break; + case MKTAG('A', 'C', 'T', 'R'): + case MKTAG('A', 'C', 'T', 'S'): + case MKTAG('A', 'U', 'T', 'H'): + case MKTAG('B', 'A', 'R', 'K'): + case MKTAG('B', 'A', 'R', 'U'): + case MKTAG('B', 'L', 'F', '1'): + case MKTAG('B', 'L', 'F', '2'): + case MKTAG('B', 'L', 'P', '1'): + case MKTAG('B', 'L', 'P', '2'): + case MKTAG('B', 'L', 'P', '3'): + case MKTAG('B', 'L', 'P', '4'): + case MKTAG('B', 'L', 'T', '1'): + case MKTAG('B', 'L', 'T', '2'): + case MKTAG('B', 'L', 'T', '3'): + case MKTAG('B', 'L', 'T', '4'): + case MKTAG('B', 'L', 'T', '5'): + case MKTAG('B', 'O', 'Y', 'S'): + case MKTAG('D', 'C', 'T', 'R'): + case MKTAG('F', 'A', 'M', 'E'): + case MKTAG('F', 'A', 'S', 'H'): + case MKTAG('G', 'I', 'R', 'L'): + case MKTAG('H', 'E', 'R', 'O'): + case MKTAG('H', 'O', 'S', 'T'): + case MKTAG('K', 'N', 'O', 'B'): + case MKTAG('N', 'H', 'R', 'O'): + case MKTAG('R', 'A', 'C', 'E'): + case MKTAG('S', 'C', 'I', 'T'): + case MKTAG('T', 'D', 'V', 'P'): + case MKTAG('T', 'W', 'A', 'T'): + case MKTAG('W', 'E', 'A', 'T'): + tagId = MKTAG('P', 'R', 'S', 'N'); + break; + case MKTAG('C', 'H', 'S', 'E'): + case MKTAG('C', 'M', 'N', 'T'): + case MKTAG('F', 'I', 'L', 'M'): + case MKTAG('J', 'F', 'O', 'D'): + case MKTAG('L', 'I', 'Q', 'D'): + tagId = MKTAG('F', 'O', 'O', 'D'); + break; + case MKTAG('C', 'R', 'I', 'M'): + case MKTAG('C', 'S', 'P', 'Y'): + case MKTAG('D', 'R', 'U', 'G'): + tagId = MKTAG('V', 'B', 'A', 'D'); + break; + case MKTAG('E', 'A', 'R', 'T'): + case MKTAG('H', 'O', 'M', 'E'): + case MKTAG('N', 'P', 'L', 'C'): + case MKTAG('P', 'L', 'A', 'N'): + tagId = MKTAG('P', 'L', 'A', 'C'); + break; + case MKTAG('F', 'A', 'U', 'N'): + case MKTAG('F', 'I', 'S', 'H'): + case MKTAG('F', 'L', 'O', 'R'): + tagId = MKTAG('N', 'A', 'T', 'R'); + break; + case MKTAG('H', 'H', 'L', 'D'): + case MKTAG('T', 'O', 'Y', 'S'): + case MKTAG('W', 'E', 'A', 'P'): + tagId = MKTAG('M', 'A', 'C', 'H'); + break; + case MKTAG('M', 'L', 'T', 'Y'): + case MKTAG('P', 'G', 'R', 'P'): + case MKTAG('P', 'T', 'I', 'C'): + tagId = MKTAG('G', 'R', 'U', 'P'); + break; + case MKTAG('P', 'K', 'U', 'P'): + case MKTAG('S', 'E', 'X', '1'): + case MKTAG('S', 'W', 'E', 'R'): + tagId = MKTAG('R', 'U', 'D', 'E'); + break; + case MKTAG('P', 'H', 'I', 'L'): + case MKTAG('R', 'C', 'K', 'T'): + tagId = MKTAG('S', 'C', 'I', 'E'); + break; + case MKTAG('T', 'R', 'A', '2'): + case MKTAG('T', 'R', 'A', '3'): + tagId = MKTAG('T', 'R', 'A', 'V'); + break; + default: + break; + } + + return TTnpcScript::handleQuote(roomScript, sentence, val, tagId, remainder); +} + +int DoorbotScript::updateState(uint oldId, uint newId, int index) { + getValue(38); + bool flag39 = getValue(39) != 0; + CTrueTalkManager::setFlags(38, 0); + CTrueTalkManager::setFlags(39, 0); + + if (newId > 220890) { + switch (newId) { + case 221064: + return getValue(1) == 2 ? newId : 221062; + case 221080: + return getValue(1) >= 2 ? newId : 221066; + case 221078: + case 221079: + return getValue(1) >= 3 ? newId : 221065; + case 221081: + return getValue(7) == 0 ? newId : 221070; + case 221251: + CTrueTalkManager::triggerAction(28, 0); + break; + default: + break; + } + } else if (newId >= 220883) { + CTrueTalkManager::setFlags(38, 1); + CTrueTalkManager::triggerAction(28, 0); + } else if (newId >= 220076) { + switch (newId) { + case 220078: + case 220080: + case 220081: + case 220082: + case 220083: + case 220084: + if (flag39) + return getRangeValue(221381); + break; + default: + break; + } + + CTrueTalkManager::setFlags(39, 1); + } else if (newId == 220075) { + if (flag39) + return getRangeValue(221381); + CTrueTalkManager::setFlags(39, 1); + } else if (newId == 220038) { + return 220038; + } + + for (uint idx = 0; idx < _states.size(); ++idx) { + TTupdateState &us = _states[idx]; + if (us._newId == newId) { + uint bits = us._dialBits; + + if (!bits + || (index == 0 && (bits == 5 || bits == 1)) + || (index == 1 && (bits == 6 || bits == 2)) + || (index == 2 && (bits == 9 || bits == 1)) + || (index == 3 && (bits == 10 || bits == 2))) { + setState(us._newValue); + break; + } + } + } + + return newId; +} + +int DoorbotScript::preResponse(uint id) { + uint newId = 0; + if (getDialRegion(0) != 1 && getRandomNumber(100) > 60) { + addResponse(11195); + newId = 222193; + } + + return newId; +} + +uint DoorbotScript::getDialsBitset() const { + uint bits = 0; + if (!getDialRegion(1)) + bits = 1; + if (!getDialRegion(0)) + bits |= 2; + + return bits; +} + +int DoorbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + int id2, id = 0; + + switch (val1) { + case 2: + if (getValue(1) != 1) + return 1; + break; + case 3: + if (getValue(1) != 2) + return 1; + break; + case 4: + if (getValue(1) != 3) + return 1; + break; + case 5: + if (getValue(1) == 3) + return 1; + case 6: + if (getRoom54(132)) + return 1; + break; + case 9: + if (sentence->localWord("my") || sentence->contains("my")) + return true; + id2 = getRoomDialogueId1(roomScript); + if (id2) { + addResponse(id2); + applyResponse(); + return 2; + } + break; + case 11: + switch (getValue(1)) { + case 1: + id = 220837; + break; + case 2: + id = 220849; + break; + default: + id = 220858; + break; + } + break; + case 12: + if (getValue(4) != 1) + id = 221157; + break; + case 13: + if (getValue(4) != 2) + id = 221157; + break; + case 14: + if (getValue(4) != 3) + id = 221157; + break; + case 15: + if (getValue(4) != 0) + id = 221157; + break; + case 16: + if (!sentence->localWord("weather")) + return true; + switch (getRandomNumber(4)) { + case 1: + if (getValue(4) != 0) + id = 221354 - getRandomNumber(2) ? -489 : 0; + break; + case 2: + switch (getValue(4)) { + case 0: + id = 220851; + break; + case 1: + id = 221268; + break; + case 2: + id = 221270; + break; + default: + id = 220865; + } + break; + case 3: + id = 221280; + break; + default: + break; + } + break; + case 17: + if (getState()) + return 1; + setState(0); + break; + case 18: + if (roomScript->_scriptId == 100) { + CTrueTalkManager::triggerAction(3, 0); + return 2; + } + break; + case 19: + CTrueTalkManager::_v9 = 104; + CTrueTalkManager::triggerAction(4, 0); + break; + case 20: + CTrueTalkManager::triggerAction(28, 0); + break; + case 22: + CTrueTalkManager::triggerAction(29, 1); + break; + case 23: + CTrueTalkManager::triggerAction(29, 2); + break; + case 24: + CTrueTalkManager::triggerAction(29, 3); + break; + case 25: + CTrueTalkManager::triggerAction(29, 4); + break; + case 26: + if (!sentence->localWord("my") && !sentence->contains("my")) + return 1; + break; + case 27: + if (!sentence->localWord("earth") && !sentence->contains("earth")) + return 1; + break; + case 28: + id2 = getRoomDialogueId2(roomScript); + if (id2) { + addResponse(id2); + applyResponse(); + return 2; + } + break; + case 29: + if (sentence->localWord("another") || sentence->localWord("more") || + sentence->localWord("additional") || sentence->contains("another") || + sentence->contains("more") || sentence->contains("additional")) { + addResponse(getDialogueId(220058)); + applyResponse(); + return 2; + } + break; + case 30: + if (!sentence->localWord("because") && !sentence->contains("because")) + return 1; + break; + case 0x200: + if (getValue(4) != 1) + id = 221157; + break; + case 0x201: + if (getValue(4) != 2) + id = 221157; + break; + case 0x202: + if (getValue(4) != 3) + id = 221157; + break; + case 0x203: + if (getValue(4) != 0) + id = 221157; + break; + default: + break; + } + + if (id) { + addResponse(getDialogueId(id)); + applyResponse(); + return 2; + } else { + return 0; + } +} + +void DoorbotScript::setDialRegion(int dialNum, int region) { + TTnpcScript::setDialRegion(dialNum, region); + if (dialNum == 1 && region != 1) { + CTrueTalkManager::setFlags(37, dialNum); + } else { + addResponse(getDialogueId(221777)); + applyResponse(); + } +} + +bool DoorbotScript::randomResponse(uint index) { + static const int DIALOGUE_IDS[] = { + 220133, 220074, 220000, 220008, 220009, 220010, 220011, + 220012, 220013, 220014, 220015, 220016, 221053, 221054, + 221055, 221056, 221057, 221058, 221059, 221060, 221061, + 221173, 221174, 221175, 221176, 221177, 222415, 222416, + 221157, 221165, 221166, 221167, 221168, 221169, 221170, + 221171, 221172, 221158, 221159, 221356, 221364, 221365, + 221366, 221367, 221368, 221369, 221370, 221371, 221357, + 221358, 221359, 221360, 221252, 221019, 221355, 220952, + 220996, 220916, 220924, 220926, 220931, 220948, 220956, + 220965, 220967, 220968, 220980, 220981, 220982, 220983, + 220984, 220988, 220903, 221095, 222202, 222239, 221758, + 221759, 221762, 221763, 221766, 221767, 221768, 0 + }; + + int *dataP = _data.getSlot(index); + bool flag = false; + for (const int *idP = DIALOGUE_IDS; *idP && !flag; ++idP) { + flag = *idP == *dataP; + } + + if (flag || (getDialRegion(1) != 1 && getRandomNumber(100) > 33) + || getRandomNumber(8) <= index) + return false; + + if (getRandomNumber(100) > 40) { + deleteResponses(); + addResponse(getDialogueId(221242)); + applyResponse(); + } else { + setResponseFromArray(index, 221245); + } + + return true; +} + +int DoorbotScript::setResponse(int dialogueId, int v34) { + addResponse(dialogueId); + applyResponse(); + + if (v34 != -1) + setState(v34); + return 2; +} + +int DoorbotScript::getRoomDialogueId1(const TTroomScript *roomScript) { + for (const RoomDialogueId *r = ROOM_DIALOGUES1; r->_roomNum; ++r) { + if (r->_roomNum == roomScript->_scriptId) + return getDialogueId(r->_dialogueId); + } + + return 0; +} + +int DoorbotScript::getRoomDialogueId2(const TTroomScript *roomScript) { + for (const RoomDialogueId *r = ROOM_DIALOGUES2; r->_roomNum; ++r) { + if (r->_roomNum == roomScript->_scriptId) + return getDialogueId(r->_dialogueId); + } + + return 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/doorbot_script.h b/engines/titanic/true_talk/doorbot_script.h new file mode 100644 index 0000000000..78ebcbfd68 --- /dev/null +++ b/engines/titanic/true_talk/doorbot_script.h @@ -0,0 +1,113 @@ +/* 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_DOORBOT_SCRIPT_H +#define TITANIC_DOORBOT_SCRIPT_H + +#include "common/hashmap.h" +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class DoorbotScript : public TTnpcScript { + typedef Common::HashMap<uint, TTsentenceEntries> SentenceEntriesMap; +private: + TTupdateStateArray _states; + SentenceEntriesMap _sentences; + int _stateIndex; + int _doorbotState; +private: + /** + * Setup sentence data + */ + void setupSentences(); + + /** + * Sets a response + */ + int setResponse(int dialogueId, int v34 = -1); + + /** + * Gets the dialogue Id for a given room + */ + int getRoomDialogueId1(const TTroomScript *roomScript); + + /** + * Gets the dialogue Id for a given room + */ + int getRoomDialogueId2(const TTroomScript *roomScript); +public: + DoorbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); + + /** + * Returns a bitset of the dials being off or not + */ + virtual uint getDialsBitset() const; + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Sets a given dial to be pointing in a specified region (0 to 2) + */ + virtual void setDialRegion(int dialNum, int region); + + /** + * Handles a randomzied response + */ + virtual bool randomResponse(uint index); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_DOORBOT_SCRIPT_H */ diff --git a/engines/titanic/true_talk/liftbot_script.cpp b/engines/titanic/true_talk/liftbot_script.cpp new file mode 100644 index 0000000000..ab995b71b9 --- /dev/null +++ b/engines/titanic/true_talk/liftbot_script.cpp @@ -0,0 +1,695 @@ +/* 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/true_talk/liftbot_script.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +int LiftbotScript::_stateIndex; + +static const int STATE_ARRAY[7] = { + 0x78BE, 0x78C0, 0x78C1, 0x78C2, 0x78C3, 0x78C4, 0x78C5 +}; + +LiftbotScript::LiftbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, v4, v5, v6, v7) { + _stateIndex = 0; + + loadRanges("Ranges/Liftbot"); + loadResponses("Responses/Liftbot"); + setupSentences(); + _tagMappings.load("TagMap/Liftbot"); + _words.load("Words/Liftbot"); + _quotes.load("Quotes/Liftbot"); + _states.load("States/Liftbot"); +} + +void LiftbotScript::setupSentences() { + CTrueTalkManager::setFlags(27, 0); + setupDials(getRandomNumber(40) + 60, getRandomNumber(40) + 60, 0); + + _mappings.load("Mappings/Liftbot", 4); + _entries.load("Sentences/Liftbot"); + _field68 = 0; + _entryCount = 0; +} + +int LiftbotScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + switch (tag) { + case MKTAG('D', 'N', 'A', '1'): + case MKTAG('H', 'H', 'G', 'Q'): + case MKTAG('A', 'N', 'S', 'W'): + if (_stateIndex >= 7) { + selectResponse(30918); + setState(2); + _stateIndex = 0; + } else { + addResponse(STATE_ARRAY[_stateIndex++]); + } + + applyResponse(); + return 2; + + case MKTAG('O', 'R', 'D', '8'): + addResponse(30475); + addResponse(30467); + addResponse(30466); + addResponse(30474); + applyResponse(); + return SS_2; + + default: + return TTnpcScript::chooseResponse(roomScript, sentence, tag); + } +} + +int LiftbotScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + if (roomScript->_scriptId != 103) + return 2; + + checkItems(roomScript, sentence); + int currState = getState(); + int sentMode = sentence->_field2C; + TTtreeResult treeResult; + + if (currState) { + setState(0); + bool flag1 = sentMode == 11 || sentMode == 13; + bool flag2 = sentMode == 12; + + switch (currState) { + case 2: + if (flag1) + return addDialogueAndState(30920, 3); + if (flag2) + return addDialogueAndState(30919, 1); + break; + + case 3: + if (flag1) + return addDialogueAndState(30919, 1); + break; + + case 4: + return addDialogueAndState(210391, 1); + + case 5: + if (sentence->contains("reborzo") || sentence->contains("is that")) + return addDialogueAndState(30515, 1); + break; + + case 6: + if (sentMode == 6) + return addDialogueAndState(getDialogueId(210771), 1); + break; + + case 7: + case 8: + if (sentMode == 6 || sentMode == 10) + return addDialogueAndState(getDialogueId(210099), 1); + break; + + case 9: + if (sentMode == 10 || g_vm->_trueTalkManager->_quotesTree.search( + sentence->_normalizedLine.c_str(), TREE_2, &treeResult, 0, 0) != -1) + return addDialogueAndState(getDialogueId(210970), 9); + break; + + default: + break; + } + } + + updateCurrentDial(true); + if (processEntries(&_entries, _entryCount, roomScript, sentence) == 2) + return 2; + + if (sentence->localWord("injury") || sentence->localWord("illness")) { + addResponse(getDialogueId(210059)); + applyResponse(); + } else if (processEntries(_defaultEntries, 0, roomScript, sentence) != 2 + && !defaultProcess(roomScript, sentence) + && !sentence1(sentence)) { + if (getDialRegion(1) != 0 && getRandomNumber(100) <= 20) { + addResponse(getDialogueId(210906)); + addResponse(getDialogueId(210901)); + } else { + addResponse(getDialogueId(210590)); + } + applyResponse(); + } + + return 2; +} + +ScriptChangedResult LiftbotScript::scriptChanged(uint id) { + return scriptChanged(nullptr, id); +} + +ScriptChangedResult LiftbotScript::scriptChanged(const TTroomScript *roomScript, uint id) { + switch (id) { + case 3: + if (getValue(27) == 0) { + addResponse(getDialogueId(210018)); + } else if (getStateValue()) { + addResponse(getDialogueId(210682)); + } else { + addResponse(getDialogueId(210033)); + } + CTrueTalkManager::setFlags(27, 1); + break; + + case 155: + selectResponse(30446); + applyResponse(); + break; + + case 156: + if (getCurrentFloor() == 1) { + addResponse(getDialogueId(210614)); + } else { + selectResponse(30270); + } + applyResponse(); + break; + + default: + break; + } + + if (id >= 210000 && id <= 211001) { + addResponse(getDialogueId(id)); + applyResponse(); + } + + return SCR_2; +} + +int LiftbotScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + switch (tagId) { + case MKTAG('A', 'D', 'V', 'T'): + case MKTAG('A', 'R', 'T', 'I'): + case MKTAG('A', 'R', 'T', 'Y'): + case MKTAG('B', 'R', 'N', 'D'): + case MKTAG('C', 'O', 'M', 'D'): + case MKTAG('D', 'N', 'C', 'E'): + case MKTAG('H', 'B', 'B', 'Y'): + case MKTAG('L', 'I', 'T', 'R'): + case MKTAG('M', 'A', 'G', 'S'): + case MKTAG('M', 'C', 'P', 'Y'): + case MKTAG('M', 'I', 'N', 'S'): + case MKTAG('M', 'U', 'S', 'I'): + case MKTAG('N', 'I', 'K', 'E'): + case MKTAG('S', 'F', 'S', 'F'): + case MKTAG('S', 'O', 'A', 'P'): + case MKTAG('S', 'O', 'N', 'G'): + case MKTAG('S', 'P', 'R', 'T'): + case MKTAG('T', 'E', 'A', 'M'): + case MKTAG('T', 'V', 'S', 'H'): + case MKTAG('W', 'W', 'E', 'B'): + tagId = MKTAG('E', 'N', 'T', 'N'); + break; + case MKTAG('A', 'C', 'T', 'R'): + case MKTAG('A', 'C', 'T', 'S'): + case MKTAG('A', 'U', 'T', 'H'): + case MKTAG('B', 'A', 'R', 'K'): + case MKTAG('B', 'A', 'R', 'U'): + case MKTAG('B', 'L', 'F', '1'): + case MKTAG('B', 'L', 'F', '2'): + case MKTAG('B', 'L', 'R', '1'): + case MKTAG('B', 'L', 'R', '2'): + case MKTAG('B', 'L', 'P', '1'): + case MKTAG('B', 'L', 'P', '2'): + case MKTAG('B', 'L', 'P', '3'): + case MKTAG('B', 'L', 'P', '4'): + case MKTAG('B', 'L', 'T', '1'): + case MKTAG('B', 'L', 'T', '2'): + case MKTAG('B', 'L', 'T', '3'): + case MKTAG('B', 'L', 'T', '4'): + case MKTAG('B', 'L', 'T', '5'): + case MKTAG('B', 'O', 'Y', 'S'): + case MKTAG('C', 'O', 'P', 'S'): + case MKTAG('D', 'C', 'T', 'R'): + case MKTAG('F', 'A', 'M', 'E'): + case MKTAG('F', 'A', 'S', 'H'): + case MKTAG('G', 'I', 'R', 'L'): + case MKTAG('H', 'E', 'R', 'O'): + case MKTAG('H', 'O', 'S', 'T'): + case MKTAG('K', 'N', 'O', 'B'): + case MKTAG('N', 'H', 'R', 'O'): + case MKTAG('R', 'A', 'C', 'E'): + case MKTAG('S', 'C', 'I', 'T'): + case MKTAG('T', 'D', 'V', 'P'): + case MKTAG('T', 'W', 'A', 'T'): + case MKTAG('W', 'E', 'A', 'T'): + tagId = MKTAG('P', 'R', 'S', 'N'); + break; + case MKTAG('C', 'H', 'S', 'E'): + case MKTAG('C', 'M', 'N', 'T'): + case MKTAG('F', 'I', 'L', 'M'): + case MKTAG('J', 'F', 'O', 'D'): + case MKTAG('L', 'I', 'Q', 'D'): + tagId = MKTAG('F', 'O', 'O', 'D'); + break; + case MKTAG('C', 'R', 'I', 'M'): + case MKTAG('C', 'S', 'P', 'Y'): + case MKTAG('D', 'R', 'U', 'G'): + tagId = MKTAG('V', 'B', 'A', 'D'); + break; + case MKTAG('E', 'A', 'R', 'T'): + case MKTAG('H', 'O', 'M', 'E'): + case MKTAG('N', 'P', 'L', 'C'): + case MKTAG('P', 'L', 'A', 'N'): + tagId = MKTAG('P', 'L', 'A', 'C'); + break; + case MKTAG('F', 'A', 'U', 'N'): + case MKTAG('F', 'I', 'S', 'H'): + case MKTAG('F', 'L', 'O', 'R'): + tagId = MKTAG('N', 'A', 'T', 'R'); + break; + case MKTAG('H', 'H', 'L', 'D'): + case MKTAG('T', 'O', 'Y', 'S'): + case MKTAG('W', 'E', 'A', 'P'): + tagId = MKTAG('M', 'A', 'C', 'H'); + break; + case MKTAG('M', 'L', 'T', 'Y'): + case MKTAG('P', 'G', 'R', 'P'): + case MKTAG('P', 'T', 'I', 'C'): + tagId = MKTAG('G', 'R', 'U', 'P'); + break; + case MKTAG('P', 'K', 'U', 'P'): + case MKTAG('S', 'E', 'X', '1'): + case MKTAG('S', 'W', 'E', 'R'): + tagId = MKTAG('R', 'U', 'D', 'E'); + break; + case MKTAG('P', 'H', 'I', 'L'): + case MKTAG('R', 'C', 'K', 'T'): + tagId = MKTAG('S', 'C', 'I', 'E'); + break; + case MKTAG('T', 'R', 'A', '2'): + case MKTAG('T', 'R', 'A', '3'): + tagId = MKTAG('T', 'R', 'A', 'V'); + break; + } + + return TTnpcScript::handleQuote(roomScript, sentence, val, tagId, remainder); +} + +int LiftbotScript::updateState(uint oldId, uint newId, int index) { + for (uint idx = 0; idx < _states.size(); ++idx) { + TTmapEntry &us = _states[idx]; + if (us._src == newId) { + setState(us._dest); + break; + } + } + + return newId; +} + +int LiftbotScript::preResponse(uint id) { + if (id == 30565 || id == 30566 || id == 30567 || id == 30568 + || id == 30569 || id == 30570 || id == 30571) + return 210901; + + if (getDialRegion(0) == 0 && getRandomNumber(100) > 60) + return 210830; + + return 0; +} + +uint LiftbotScript::getDialsBitset() const { + uint bits = 0; + if (!getDialRegion(1)) + bits = 1; + if (!getDialRegion(0)) + bits |= 2; + if (bits > 1) + bits ^= 1; + + return bits; +} + + +int LiftbotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + static const int ARRAY13[] = { + 210724, 210735, 210746, 210757, 210758, 210759, 210760, + 210761, 210762, 210725, 210726, 210727, 210728, 210729, + 210730, 210731, 210732, 210733, 210734, 210736, 210737, + 210738, 210739, 210740, 210741, 210742, 210743, 210744, + 210745, 210747, 210748, 210749, 210750, 210751, 210752, + 210753, 210754, 210755, 210756 + }; + static const int ARRAY14[] = { + 0, 210849, 210850, 210851, 210852, 210838, 210839, 210840, 210841, 0 + }; + + getState(); + int stateVal; + + switch (val1) { + case 1: + if (getValue(1) != 1) + return 1; + break; + case 2: + if (getValue(1) != 2) + return 1; + break; + case 3: + if (getValue(1) != 3) + return 1; + break; + case 4: + case 5: + return !sentence1(sentence); + case 6: + if (sentence->localWord("big") || sentence->localWord("small")) { + addResponse(getDialogueId(210215)); + applyResponse(); + } else if (sentence->localWord("my") || sentence->contains("my") || + sentence->contains("bedroom") || sentence->contains("state")) { + addResponse1(CTrueTalkManager::getStateValue(4), true, 0); + } else { + selectResponse(210763); + applyResponse(); + } + return 2; + case 7: + if (!sentence->localWord("ill") && !sentence->localWord("well")) + return 1; + break; + case 8: + if (!sentence->localWord("long")) + return 1; + break; + case 9: + if (addResponse1(1, false, 0)) + return 2; + break; + case 10: + if (addResponse1(39, false, 0)) + return 2; + break; + case 11: + if (getState6() == 2 || getState6() == 4) + return 1; + break; + case 12: + if (getState6() == 1 || getState6() == 3) + return 1; + break; + case 13: + selectResponse(ARRAY13[getCurrentFloor()]); + applyResponse(); + return 2; + case 14: + stateVal = getState6(); + if (sentence->contains("elevator") || + (!sentence->contains("lift") && getRandomNumber(100) > 60)) + stateVal += 4; + selectResponse(ARRAY14[stateVal]); + applyResponse(); + return 2; + case 15: + if (getRandomNumber(100) > 60) { + addResponse(getDialogueId(210440)); + } else { + addResponse(getDialogueId(210906)); + addResponse(getDialogueId(210901)); + } + applyResponse(); + return 2; + case 16: + if (sentence->contains("elevator") || sentence->contains("elavator")) + addResponse(30579); + else + addResponse(30580); + applyResponse(); + return 2; + case 17: + if (sentence->localWord("restaurant") || sentence->contains("restaurant")) + return 1; + break; + default: + break; + } + + return 0; +} + +void LiftbotScript::setDialRegion(int dialNum, int region) { + TTnpcScript::setDialRegion(dialNum, region); + addResponse(getDialogueId(210688)); + applyResponse(); +} + +int LiftbotScript::getCurrentFloor() const { + int val = CTrueTalkManager::getStateValue(5); + return CLIP(val, 1, 39); +} + +int LiftbotScript::getState6() const { + int val = CTrueTalkManager::getStateValue(6); + return (val < 1 || val > 4) ? 1 : val; +} + +int LiftbotScript::addDialogueAndState(int id, int state) { + addResponse(id); + applyResponse(); + + if (state != 1) + setState(state); + return 2; +} + +int LiftbotScript::addResponse1(int index, bool flag, int id) { + static const int DIALOGUE_IDS[37] = { + 210735, 210746, 210757, 210758, 210759, 210760, 210761, 210762, + 210725, 210726, 210727, 210728, 210729, 210730, 210731, 210732, + 210733, 210734, 210736, 210737, 210738, 210739, 210740, 210741, + 210742, 210743, 210744, 210745, 210747, 210748, 210749, 210750, + 210751, 210752, 210753, 210754, 210755 + }; + + int stateVal = getState6(); + int maxIndex = (stateVal == 2 || stateVal == 4) ? 27 : 39; + + if (index < 1 || index > maxIndex) { + addResponse(getDialogueId(maxIndex == 27 ? 210587 : 210586)); + applyResponse(); + return 1; + } else if (index == getCurrentFloor()) { + if (index == 1) { + addResponse(30558 - getRandomBit() ? 290 : 0); + addResponse(getDialogueId(210589)); + } else { + if (index == 39) + addResponse(30346); + addResponse(getDialogueId(210589)); + } + + applyResponse(); + return 2; + } + + stateVal = getValue(1); + if (index >= 2 && index <= 19 && stateVal > 1) { + addResponse(getDialogueId(210203)); + applyResponse(); + setState(7); + return true; + } + + if (index >= 20 && index <= 27 && stateVal > 2) { + addResponse(getDialogueId(210210)); + applyResponse(); + setState(8); + return true; + } + + if (flag) { + if (index == 1) { + selectResponse(30558 - getRandomBit() ? 290 : 0); + } else if (index == 39) { + addResponse(30346); + } else { + if (getRandomNumber(100) > 35 && index >= 2 && index <= 38) { + addResponse(getDialogueId(DIALOGUE_IDS[index - 2])); + } + + addResponse(getDialogueId(210588)); + } + + if (id) { + if (id == 210717 || id == 210716 || id == 210719 || id == 210718) { + addResponse(getDialogueId(210720)); + addResponse(getDialogueId(id)); + addResponse(getDialogueId(210715)); + } else { + addResponse(getDialogueId(id)); + } + } + + applyResponse(); + } + + CTrueTalkManager::triggerAction(2, index); + return flag; +} + +int LiftbotScript::sentence1(const TTsentence *sentence) { + if (CTrueTalkManager::_v1 >= 0) { + if (sentence->localWord("room")) { + addResponse1(getStateValue(), true, 0); + } else if (CTrueTalkManager::_v1 >= 1 && CTrueTalkManager::_v1 <= 39) { + if (CTrueTalkManager::_v1 != 1 || !sentence->localWord("floor")) { + addResponse1(CTrueTalkManager::_v1, true, 0); + } else if (sentence->localWord("up") || sentence->localWord("above")) { + addResponse1(getCurrentFloor() - 1, true, 0); + } else if (sentence->localWord("down") || sentence->localWord("below")) { + addResponse1(getCurrentFloor() + 1, true, 0); + } else { + addResponse1(CTrueTalkManager::_v1, true, 0); + } + } + return 1; + } + + int classNum = 1; + bool classSet = true; + if (sentence->localWord("firstclass")) + classNum = 1; + else if (sentence->localWord("secondclass")) + classNum = 2; + else if (sentence->localWord("thirdclass")) + classNum = 3; + else + classSet = false; + + uint newId = 0; + int diff = 1; + if (sentence->localWord("promenade")) { + newId = 210718; + } else if (sentence->localWord("bar")) { + newId = 210894 - (getRandomBit() ? 178 : 0); + } else if (sentence->localWord("musicroom")) { + newId = 210897 - (getRandomBit() ? 180 : 0); + } else if (sentence->localWord("creatorroom")) { + newId = 210713; + } else if (sentence->localWord("sculpture") || sentence->localWord("sculptureroom")) { + newId = 210722; + } else if (sentence->localWord("embarklobby")) { + newId = 210714; + } else if (sentence->localWord("parrotlobby")) { + newId = 210721; + } else if (sentence->localWord("arboretum")) { + newId = 210711; + } else if (sentence->localWord("canal")) { + newId = 210896; + } else if (sentence->localWord("bar")) { + newId = 210894; + } else if (sentence->localWord("bilgeroom")) { + newId = 210895; + } else if (sentence->localWord("titaniaroom")) { + newId = 210723; + } else if (sentence->localWord("restaurant")) { + if (classNum == 1) { + newId = 210719; + diff = 1; + } else { + newId = 210898; + diff = -98; + } + } else if (sentence->localWord("topwell") || sentence->localWord("servicelift") + || sentence->localWord("bridge") || sentence->localWord("dome") + || sentence->localWord("pellerator") || sentence->localWord("top")) { + diff = 1; + } else { + diff = -100; + } + + if (sentence->localWord("lobby")) + diff = (getValue(1) == 0 ? 1 : 0) - 99; + if (sentence->localWord("bottomofwell") || sentence->contains("bottom")) + diff = 39; + + if (diff == -99 || (diff == -100 && classSet)) { + if (classNum == 1) + addResponse(getDialogueId(210235)); + else if (classNum == 2) + addResponse(getDialogueId(210241)); + else + addResponse(getDialogueId(210242)); + applyResponse(); + + return 1; + } + + if (sentence->_field2C == 4 || sentence->localWord("find") + || sentence->contains("get to")) { + if (getCurrentFloor() != diff) { + selectResponse(diff == 1 ? 210769 : 210764); + applyResponse(); + } else if (!newId) { + selectResponse(210764); + applyResponse(); + } else if (newId >= 210715 && newId <= 210719) { + selectResponse(newId); + applyResponse(); + } else { + addResponse(getDialogueId(210720)); + selectResponse(210715); + applyResponse(); + } + + return 1; + } + + if (diff == -98) { + addResponse1(getStateValue(), true, newId); + return 1; + } else if (diff >= 0) { + addResponse1(diff, true, newId); + return 1; + } else if (sentence->localWord("up") || sentence->localWord("ascend")) { + selectResponse(210128); + applyResponse(); + return 1; + } else if (sentence->localWord("down") || sentence->localWord("descend")) { + selectResponse(210138); + applyResponse(); + return 1; + } else if (diff >= 0) { + addResponse1(diff, true, newId); + return 1; + } else { + return 0; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/liftbot_script.h b/engines/titanic/true_talk/liftbot_script.h new file mode 100644 index 0000000000..0a9cdfd6f0 --- /dev/null +++ b/engines/titanic/true_talk/liftbot_script.h @@ -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. + * + */ + +#ifndef TITANIC_LIFTBOT_SCRIPT_H +#define TITANIC_LIFTBOT_SCRIPT_H + +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class LiftbotScript : public TTnpcScript { +private: + TTmapEntryArray _states; + static int _stateIndex; +private: + /** + * Setup sentence data + */ + void setupSentences(); + + int addResponse1(int mode, bool flag, int id); + int sentence1(const TTsentence *sentence); + + /** + * Gets the current floor + */ + int getCurrentFloor() const; + + int getState6() const; + + /** + * Adds a dialogue response and sets the state + */ + int addDialogueAndState(int id, int state); +public: + LiftbotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(uint id); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); + + /** + * Returns a bitset of the dials being off or not + */ + virtual uint getDialsBitset() const; + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Sets a given dial to be pointing in a specified region (0 to 2) + */ + virtual void setDialRegion(int dialNum, int region); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_LIFTBOT_SCRIPT_H */ diff --git a/engines/titanic/true_talk/maitred_script.cpp b/engines/titanic/true_talk/maitred_script.cpp new file mode 100644 index 0000000000..e0636d045f --- /dev/null +++ b/engines/titanic/true_talk/maitred_script.cpp @@ -0,0 +1,1057 @@ +/* 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/true_talk/maitred_script.h" +#include "titanic/true_talk/true_talk_manager.h" + +namespace Titanic { + +MaitreDScript::MaitreDScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, -1, -1, -1, 0) { + _answerCtr = 0; + + CTrueTalkManager::setFlags(9, 1); + CTrueTalkManager::setFlags(10, 0); + CTrueTalkManager::setFlags(11, 0); + CTrueTalkManager::setFlags(12, 0); + CTrueTalkManager::setFlags(13, 0); + CTrueTalkManager::setFlags(14, 0); + CTrueTalkManager::setFlags(15, 0); + CTrueTalkManager::setFlags(16, 0); + + loadRanges("Ranges/MaitreD"); + loadResponses("Responses/MaitreD"); + setupSentences(); + _tagMappings.load("TagMap/MaitreD"); + _quotes.load("Quotes/MaitreD"); + _states.load("States/MaitreD"); +} + +void MaitreDScript::setupSentences() { + _mappings.load("Mappings/MaitreD", 1); + _entries.load("Sentences/MaitreD"); + _sentences1.load("Sentences/MaitreD/1"); + _field68 = 0; + _entryCount = 0; +} + +int MaitreDScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + if (tag == MKTAG('F', 'O', 'O', 'D') || tag == MKTAG('F', 'I', 'S', 'H') || + tag == MKTAG('C', 'H', 'S', 'E')) { + addResponse(getDialogueId(260388)); + addResponse(getDialogueId(260659)); + applyResponse(); + return 2; + } + + return TTnpcScript::chooseResponse(roomScript, sentence, tag); +} + +int MaitreDScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + if (roomScript->_scriptId != 132) + return 2; + if (preprocess(roomScript, sentence) == 1) + return 1; + + CTrueTalkManager::setFlags(10, 0); + setState(0); + + if (getValue(12) == 0) { + trigger12(false); + _answerCtr = 0; + + if (sentence->contains("restaurant at the end of the universe") + || sentence->contains("milliway") + || sentence->contains("big bang burger bar")) { + addResponse(getDialogueId(260975)); + applyResponse(); + } else if (processEntries(&_entries, _entryCount, roomScript, sentence) == 2) { + // Do nothing further + } else if (sentence->localWord("menu")) { + addResponse(getDialogueId(260683)); + applyResponse(); + } else if (sentence->localWord("table") && sentence->localWord("other")) { + addResponse(getDialogueId(260091)); + applyResponse(); + } else if ((sentence->localWord("not") && sentence->localWord("busy")) + || (sentence->localWord("no") && sentence->localWord("people")) + || sentence->localWord("empty")) { + addResponse(getDialogueId(260087)); + applyResponse(); + } else if (!defaultProcess(roomScript, sentence) + && processEntries(&_sentences1, 0, roomScript, sentence) != 2 + && processEntries(_defaultEntries, 0, roomScript, sentence) != 2) { + addResponse(getDialogueId(260975)); + applyResponse(); + } + + return 2; + } + + if (++_answerCtr > 50 || sentence->localWord("stop") || sentence->localWord("enough") + || sentence->contains("i give up") || sentence->contains("i give in") + || sentence->contains("i surrender") || sentence->contains("i submit")) { + _answerCtr = 0; + trigger12(false); + addResponse(getDialogueId(260063)); + } else if (sentence->localWord("not") && sentence->localWord("fight") && + (sentence->localWord("feel") || sentence->localWord("want") + || sentence->localWord("do") || sentence->localWord("will"))) { + _answerCtr = 0; + trigger12(false); + addResponse(getDialogueId(260678)); + } else if (sentence->contains("touche") || sentence->contains("toushe")) { + addResponse(getDialogueId(260098)); + } else if (sentence->contains("have at you")) { + addResponse(getDialogueId(260047)); + } else if (sentence->contains("en garde") || sentence->contains("on guard")) { + addResponse(getDialogueId(260008)); + } else if ((sentence->localWord("surrender") && !sentence->contains("i surrender")) + || (sentence->contains("give up") && !sentence->contains("i give up")) + || (sentence->contains("give in") && !sentence->contains("i give in")) + || (sentence->contains("submit") && !sentence->contains("i submit"))) { + addResponse(getDialogueId(260086)); + } else { + addResponse(getDialogueId(260031)); + } + + applyResponse(); + return 2; +} + +ScriptChangedResult MaitreDScript::scriptChanged(const TTroomScript *roomScript, uint id) { + resetFlags(); + bool flag1 = false, flag2 = false; + + switch (id) { + case 3: + if (getValue(4)) + addResponse(getDialogueId(260655)); + else if (getValue(12)) + addResponse(getDialogueId(260622)); + else if (getValue(9) && getValue(16)) + addResponse(getDialogueId(getValue(16))); + else if (getValue(15)) + addResponse(getDialogueId(260649)); + else + addResponse(getDialogueId(260112)); + + CTrueTalkManager::setFlags(16, 0); + CTrueTalkManager::setFlags(15, 1); + applyResponse(); + break; + + case 110: + addResponse(getDialogueId(260118)); + applyResponse(); + trigger12(true); + CTrueTalkManager::setFlags(8, 1); + CTrueTalkManager::setFlags(9, 1); + break; + + case 111: + CTrueTalkManager::setFlags(16, 260680); + CTrueTalkManager::setFlags(8, 0); + CTrueTalkManager::setFlags(9, 1); + break; + + case 112: + addResponse(getDialogueId(getValue(8) ? 260095 : 260127)); + applyResponse(); + break; + + case 113: + CTrueTalkManager::setFlags(16, 260266); + CTrueTalkManager::setFlags(8, 0); + CTrueTalkManager::setFlags(9, 1); + break; + + case 114: + CTrueTalkManager::setFlags(16, 260267); + CTrueTalkManager::setFlags(8, 0); + CTrueTalkManager::setFlags(9, 1); + break; + + case 115: + CTrueTalkManager::setFlags(16, 260268); + CTrueTalkManager::setFlags(8, 0); + CTrueTalkManager::setFlags(9, 1); + break; + + case 116: + CTrueTalkManager::setFlags(8, 0); + CTrueTalkManager::setFlags(9, 1); + break; + + case 117: + CTrueTalkManager::setFlags(8, 0); + CTrueTalkManager::setFlags(9, 0); + setFlags12(); + break; + + case 132: + addResponse(getDialogueId(260655)); + applyResponse(); + break; + + default: + flag1 = true; + break; + } + + if (!getValue(8)) { + switch (id - 118) { + case 0: + addResponse(getDialogueId(260676)); + applyResponse(); + break; + case 1: + addResponse(getDialogueId(260677)); + applyResponse(); + break; + case 2: + addResponse(getDialogueId(260189)); + applyResponse(); + break; + case 3: + case 4: + case 5: + case 6: + case 7: + CTrueTalkManager::setFlags(13, id - 120); + break; + case 8: + CTrueTalkManager::setFlags(13, 0); + break; + case 9: + if (!getValue(12)) { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260120)); + applyResponse(); + } else if (getRandomNumber(4) == 1) { + addResponse(getDialogueId(260067)); + applyResponse(); + } else { + addResponse(getDialogueId(260131)); + applyResponse(); + } + break; + + case 10: + if (getValue(12) == 0) { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } else if (getRandomNumber(4) == 1) { + addResponse(getDialogueId(260077)); + applyResponse(); + } else { + addResponse(getDialogueId(260131)); + applyResponse(); + } + break; + + case 11: + if (getValue(12)) { + addResponse(getDialogueId(260121)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + case 12: + if (getValue(12)) { + addResponse(getDialogueId(260131)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + case 13: + setFlags12(); + addResponse(getDialogueId(260131)); + applyResponse(); + break; + + case 15: + CTrueTalkManager::setFlags(13, 1); + if (getValue(12)) { + addResponse(getDialogueId(260122)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + case 16: + CTrueTalkManager::setFlags(13, 2); + if (getValue(12)) { + addResponse(getDialogueId(260123)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + case 17: + CTrueTalkManager::setFlags(13, 3); + if (getValue(12)) { + addResponse(getDialogueId(260124)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + case 18: + CTrueTalkManager::setFlags(13, 4); + if (getValue(12)) { + addResponse(getDialogueId(260125)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + case 19: + CTrueTalkManager::setFlags(13, 5); + if (getValue(12)) { + addResponse(getDialogueId(260126)); + applyResponse(); + } else { + addResponse(getDialogueId(getValue(14) == 1 ? 260063 : 260119)); + applyResponse(); + } + break; + + default: + flag2 = true; + break; + } + } + + return !flag1 || !flag2 ? SCR_2 : SCR_0; +} + +int MaitreDScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + switch (tagId) { + case MKTAG('A', 'D', 'V', 'T'): + case MKTAG('A', 'R', 'T', 'I'): + case MKTAG('A', 'R', 'T', 'Y'): + case MKTAG('B', 'R', 'N', 'D'): + case MKTAG('C', 'O', 'M', 'D'): + case MKTAG('D', 'N', 'C', 'E'): + case MKTAG('H', 'B', 'B', 'Y'): + case MKTAG('L', 'I', 'T', 'R'): + case MKTAG('M', 'A', 'G', 'S'): + case MKTAG('M', 'C', 'P', 'Y'): + case MKTAG('M', 'I', 'N', 'S'): + case MKTAG('M', 'U', 'S', 'I'): + case MKTAG('N', 'I', 'K', 'E'): + case MKTAG('S', 'F', 'S', 'F'): + case MKTAG('S', 'O', 'A', 'P'): + case MKTAG('S', 'P', 'R', 'T'): + case MKTAG('S', 'O', 'N', 'G'): + case MKTAG('T', 'E', 'A', 'M'): + case MKTAG('T', 'V', 'S', 'H'): + case MKTAG('W', 'W', 'E', 'B'): + tagId = MKTAG('E', 'N', 'T', 'N'); + break; + case MKTAG('A', 'C', 'T', 'R'): + case MKTAG('A', 'C', 'T', 'S'): + case MKTAG('A', 'U', 'T', 'H'): + case MKTAG('B', 'A', 'R', 'K'): + case MKTAG('B', 'A', 'R', 'U'): + case MKTAG('B', 'L', 'F', '1'): + case MKTAG('B', 'L', 'F', '2'): + case MKTAG('B', 'L', 'P', '1'): + case MKTAG('B', 'L', 'P', '2'): + case MKTAG('B', 'L', 'P', '3'): + case MKTAG('B', 'L', 'P', '4'): + case MKTAG('B', 'L', 'R', '1'): + case MKTAG('B', 'L', 'R', '2'): + case MKTAG('B', 'L', 'T', '1'): + case MKTAG('B', 'L', 'T', '2'): + case MKTAG('B', 'L', 'T', '3'): + case MKTAG('B', 'L', 'T', '4'): + case MKTAG('B', 'L', 'T', '5'): + case MKTAG('C', 'O', 'P', 'S'): + case MKTAG('D', 'C', 'T', 'R'): + case MKTAG('F', 'A', 'M', 'E'): + case MKTAG('F', 'A', 'S', 'H'): + case MKTAG('G', 'I', 'R', 'L'): + case MKTAG('H', 'E', 'R', 'O'): + case MKTAG('H', 'O', 'S', 'T'): + case MKTAG('K', 'N', 'O', 'B'): + case MKTAG('N', 'H', 'R', 'O'): + case MKTAG('R', 'A', 'C', 'E'): + case MKTAG('S', 'C', 'I', 'T'): + case MKTAG('T', 'D', 'V', 'P'): + case MKTAG('T', 'W', 'A', 'T'): + case MKTAG('W', 'E', 'A', 'T'): + tagId = MKTAG('P', 'R', 'S', 'N'); + break; + case MKTAG('C', 'H', 'S', 'E'): + case MKTAG('C', 'M', 'N', 'T'): + case MKTAG('F', 'I', 'L', 'M'): + case MKTAG('L', 'I', 'Q', 'D'): + tagId = MKTAG('F', 'O', 'O', 'D'); + break; + case MKTAG('C', 'R', 'I', 'M'): + case MKTAG('C', 'S', 'P', 'Y'): + case MKTAG('D', 'R', 'U', 'G'): + tagId = MKTAG('V', 'B', 'A', 'D'); + break; + case MKTAG('E', 'A', 'R', 'T'): + case MKTAG('H', 'O', 'M', 'E'): + case MKTAG('N', 'P', 'L', 'C'): + case MKTAG('P', 'L', 'A', 'N'): + tagId = MKTAG('P', 'L', 'A', 'C'); + break; + case MKTAG('F', 'A', 'U', 'N'): + case MKTAG('F', 'I', 'S', 'H'): + case MKTAG('F', 'L', 'O', 'R'): + tagId = MKTAG('N', 'A', 'T', 'R'); + break; + case MKTAG('H', 'H', 'L', 'D'): + case MKTAG('T', 'O', 'Y', 'S'): + case MKTAG('W', 'E', 'A', 'P'): + tagId = MKTAG('M', 'A', 'C', 'H'); + break; + case MKTAG('M', 'L', 'T', 'Y'): + case MKTAG('P', 'G', 'R', 'P'): + case MKTAG('P', 'T', 'I', 'C'): + tagId = MKTAG('G', 'R', 'U', 'P'); + break; + case MKTAG('P', 'K', 'U', 'P'): + case MKTAG('S', 'E', 'X', '1'): + case MKTAG('S', 'W', 'E', 'R'): + tagId = MKTAG('R', 'U', 'D', 'E'); + break; + case MKTAG('P', 'H', 'I', 'L'): + case MKTAG('R', 'C', 'K', 'T'): + tagId = MKTAG('S', 'C', 'I', 'E'); + break; + case MKTAG('T', 'R', 'A', '2'): + case MKTAG('T', 'R', 'A', '3'): + tagId = MKTAG('T', 'R', 'A', 'V'); + break; + + } + + return TTnpcScript::handleQuote(roomScript, sentence, val, tagId, remainder); +} + +int MaitreDScript::updateState(uint oldId, uint newId, int index) { + if (getValue(8)) { + if (oldId == 260112) + return getRangeValue(260654); + if (oldId != 260655 && oldId != 260654) + return getRangeValue(260655); + } + + newId = getStateDialogueId(oldId, newId); + + if (newId == 260023) { + switch (getValue(13)) { + case 1: + newId = 260023; break; + case 2: + newId = 260024; break; + case 3: + newId = 260025; break; + case 4: + newId = 260026; break; + case 5: + newId = 260027; break; + default: + newId = 260016; break; + } + } + + if (newId == 260034) { + switch (getValue(13)) { + case 1: + newId = 260034; break; + case 2: + newId = 260035; break; + case 3: + newId = 260036; break; + case 4: + newId = 260037; break; + case 5: + newId = 260038; break; + default: + newId = 260045; break; + } + } + + if (newId == 260070) { + switch (getValue(13)) { + case 1: + newId = 260070; break; + case 2: + newId = 260071; break; + case 3: + newId = 260072; break; + case 4: + newId = 260073; break; + case 5: + newId = 260074; break; + default: + newId = 260110; break; + } + } + + if (newId == 260076 || newId == 260181 || newId == 261010) { + CTrueTalkManager::setFlags(14, 1); + trigger12(true); + setFlags10(newId, index); + return newId; + } + + if (!getValue(12)) { + static const uint FLAG_IDS[] = { + 260080, 260066, 260067, 260062, 260050, 260087, 260090, 260171, 260173, + 260184, 260193, 260202, 260205, 260220, 260221, 260223, 260231, 260232, + 260365, 260373, 260374, 260387, 260421, 260622, 260695, 0 + }; + + for (uint idx = 0; FLAG_IDS[idx]; ++idx) { + if (FLAG_IDS[idx] == newId) { + setFlags12(); + break; + } + } + } + + if (newId == 261018) { + if (getValue(8) == 0 && getValue(9) == 0) { + newId = getRangeValue(260961); + setFlags10(newId, index); + return newId; + } + + if (getValue(8) == 1 && getValue(9) == 1) { + newId = getRangeValue(260655); + setFlags10(newId, index); + return newId; + } + + if (getValue(9) && getValue(16)) { + newId = getValue(16); + setFlags10(newId, index); + return index; + } + + newId = 260989; + } + + setFlags10(newId, index); + return newId; +} + +int MaitreDScript::preResponse(uint id) { + if (id == 60911) + return 260101; + + return 0; +} + +uint MaitreDScript::getStateDialogueId(uint oldId, uint newId) { + if (getValue(8) || getValue(9)) + return newId; + + switch (newId) { + case 260009: + case 260010: + case 260011: + case 260012: + return getRangeValue(260961); + case 260052: + return 260094; + case 260203: + return 260204; + case 260211: + case 260212: + case 260761: + case 260986: + case 260987: + case 260989: + return getRangeValue(260961); + case 260263: + case 260264: + return 260265; + case 260411: + return 260457; + case 260427: + case 260053: + case 260054: + case 260055: + case 260056: + case 260057: + case 260058: + case 260059: + case 260060: + return 260135; + case 260698: + case 260895: + case 260896: + return 260457; + case 260799: + return 260214; + + default: + return newId; + } +} + + +void MaitreDScript::setFlags12() { + int val = getValue(12); + CTrueTalkManager::setFlags(12, 1); + + if (!val) { + CTrueTalkManager::triggerAction(8, 0); + resetRange(260121); + resetRange(260122); + resetRange(260123); + resetRange(260124); + resetRange(260125); + resetRange(260126); + } +} + +void MaitreDScript::setFlags10(uint newId, uint index) { + int val = 28; + for (uint idx = 0; idx < _states.size(); ++idx) { + TTmapEntry &us = _states[idx]; + if (us._src == newId) { + val = us._dest; + break; + } + } + + CTrueTalkManager::setFlags(10, val); +} + +void MaitreDScript::trigger12(bool flag) { + int val = getValue(12); + CTrueTalkManager::setFlags(12, 0); + + if (val) { + CTrueTalkManager::triggerAction(flag ? 10 : 9, 0); + } +} + +int MaitreDScript::preprocess(const TTroomScript *roomScript, const TTsentence *sentence) { + if (!roomScript || !sentence || getValue(8)) + return 1; + + bool stateFlag = true, applyFlag = false; + switch (getValue(10)) { + case 1: + if (!getValue(11) && !getValue(8)) { + addResponse(getDialogueId(260052)); + applyFlag = true; + stateFlag = false; + } + break; + + case 2: + if (sentence->localWord("change") || sentence->localWord("music")) { + addResponse(getDialogueId(200684)); + applyFlag = true; + } + break; + + case 3: + if (sentence->localWord("chance") && (sentence->localWord("another") + || sentence->localWord("other") || sentence->localWord("more"))) { + addResponse(getDialogueId(260106)); + } else { + addResponse(getDialogueId(260107)); + } + applyFlag = true; + break; + + case 4: + if (sentence->contains("unless what")) { + addResponse(getDialogueId(260099)); + } else { + addResponse(getDialogueId(260131)); + applyFlag = true; + stateFlag = false; + } + break; + + case 5: + addResponse(getDialogueId(260096)); + applyFlag = true; + stateFlag = false; + break; + + case 6: + addResponse(getDialogueId(260097)); + applyFlag = true; + stateFlag = false; + break; + + case 7: + if (sentence->_field2C == 12) { + addResponse(getDialogueId(260089)); + applyFlag = true; + stateFlag = false; + } else { + addResponse(getDialogueId(260094)); + applyFlag = true; + CTrueTalkManager::setFlags(11, 1); + } + break; + + case 8: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + trigger12(false); + addResponse(getDialogueId(260094)); + CTrueTalkManager::setFlags(11, 1); + } else { + setFlags12(); + addResponse(getDialogueId(260131)); + } + applyFlag = true; + break; + + case 9: + setFlags12(); + break; + + case 11: + if ((sentence->localWord("say") || sentence->localWord("talk")) || + sentence->localWord("you")) { + addResponse(getDialogueId(260216)); + applyFlag = true; + } + break; + + case 12: + if (sentence->localWord("why") && sentence->localWord("naughty")) { + addResponse(getDialogueId(260196)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("what") && sentence->localWord("his") + && sentence->localWord("name")) { + addResponse(getDialogueId(260197)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("i") && sentence->localWord("meet")) { + addResponse(getDialogueId(260198)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("i") && sentence->localWord("speak")) { + addResponse(getDialogueId(260206)); + applyFlag = true; + stateFlag = false; + } + break; + + case 13: + if (sentence->localWord("why") || sentence->localWord("please") + || sentence->contains("go on") || sentence->localWord("need") + || sentence->contains("got to") || sentence->localWord("must")) { + addResponse(getDialogueId(260199)); + applyFlag = true; + stateFlag = false; + } + break; + + case 14: + if (sentence->localWord("what") || sentence->localWord("why") + || sentence->localWord("kill")) { + addResponse(getDialogueId(260200)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("you") && sentence->localWord("kill")) { + addResponse(getDialogueId(260574)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("how") && sentence->localWord("kill")) { + addResponse(getDialogueId(260557)); + applyFlag = true; + stateFlag = false; + } + break; + + case 15: + if ((sentence->localWord("what") && sentence->localWord("way")) + || sentence->localWord("how")) { + addResponse(getDialogueId(260201)); + applyFlag = true; + stateFlag = false; + } + break; + + case 16: + addResponse(getDialogueId(sentence->_field2C == 11 ? 260209 : 260210)); + applyFlag = true; + stateFlag = false; + break; + + case 17: + if (sentence->localWord("what") && sentence->localWord("mean")) { + addResponse(getDialogueId(260222)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("laugh") && sentence->localWord("with") + && sentence->localWord("you")) { + addResponse(getDialogueId(260221)); + applyFlag = true; + stateFlag = false; + } else { + setFlags12(); + addResponse(getDialogueId(260221)); + applyFlag = true; + stateFlag = false; + } + break; + + case 18: + if (sentence->_field2C == 11) { + addResponse(getDialogueId(260232)); + applyFlag = true; + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(260231)); + applyFlag = true; + } else if (sentence->_field2C == 13) { + addResponse(getDialogueId(260444)); + addResponse(getDialogueId(260233)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("what") && sentence->localWord("happen")) { + addResponse(getDialogueId(260233)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why") && sentence->localWord("stressed")) { + addResponse(getDialogueId(260245)); + addResponse(getDialogueId(260233)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why")) { + addResponse(getDialogueId(260453)); + addResponse(getDialogueId(260233)); + applyFlag = true; + stateFlag = false; + } + break; + + case 19: + if ((sentence->localWord("what") && sentence->localWord("scral")) + || (sentence->localWord("what") && sentence->localWord("happen")) + || sentence->contains("go on") || sentence->contains("and then")) { + addResponse(getDialogueId(260234)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why") && sentence->localWord("stressed")) { + addResponse(getDialogueId(260245)); + addResponse(getDialogueId(260234)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why")) { + addResponse(getDialogueId(260276)); + addResponse(getDialogueId(260237)); + addResponse(getDialogueId(260234)); + applyFlag = true; + stateFlag = false; + } + break; + + case 20: + if ((sentence->localWord("what") && sentence->localWord("leovinus")) + || (sentence->localWord("what") && sentence->localWord("happen"))) { + addResponse(getDialogueId(260235)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("where") && sentence->localWord("leovinus")) { + addResponse(getDialogueId(260236)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why") && sentence->localWord("stressed")) { + addResponse(getDialogueId(260245)); + addResponse(getDialogueId(260235)); + applyFlag = true; + stateFlag = false; + } else { + addResponse(getDialogueId(260237)); + applyFlag = true; + stateFlag = false; + } + break; + + case 21: + case 22: + if (sentence->contains("cooking") + || (sentence->localWord("what") && sentence->localWord("mean"))) { + addResponse(getDialogueId(260238)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("where") && sentence->localWord("now")) { + addResponse(getDialogueId(260236)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why") && sentence->localWord("stressed")) { + addResponse(getDialogueId(260245)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why")) { + addResponse(getDialogueId(260239)); + applyFlag = true; + stateFlag = false; + } + break; + + case 23: + if (sentence->_field2C == 11) { + addResponse(getDialogueId(260237)); + applyFlag = true; + stateFlag = false; + } + break; + + case 24: + if ((sentence->localWord("can") && sentence->localWord("i") + && sentence->localWord("have")) + || (sentence->localWord("give") && sentence->localWord("me")) + || (sentence->localWord("i") && sentence->localWord("want")) + || (sentence->localWord("i") && sentence->localWord("need")) + ) { + addResponse(getDialogueId(260251)); + applyFlag = true; + } + + case 25: + if ((sentence->localWord("open") && sentence->localWord("it")) + || (sentence->localWord("how") && sentence->localWord("open")) + || (sentence->localWord("how") && sentence->localWord("get") && sentence->localWord("in")) + || (sentence->localWord("how") && sentence->localWord("change") && sentence->localWord("music")) + ) { + addResponse(getDialogueId(260253)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("where") && (sentence->localWord("it") + || sentence->localWord("that"))) { + addResponse(getDialogueId(260252)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("where") && sentence->localWord("key")) { + addResponse(getDialogueId(260254)); + applyFlag = true; + stateFlag = false; + } else if ((sentence->localWord("how") && sentence->localWord("work")) + || (sentence->localWord("what") && sentence->localWord("i") && sentence->localWord("do"))) { + addResponse(getDialogueId(260259)); + applyFlag = true; + stateFlag = false; + } + break; + + case 26: + if (sentence->localWord("where") && (sentence->localWord("key") + || sentence->localWord("it"))) { + addResponse(getDialogueId(260254)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("where") && (sentence->localWord("hand") + || sentence->localWord("that"))) { + addResponse(getDialogueId(260256)); + applyFlag = true; + stateFlag = false; + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(260255)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("why") && sentence->localWord("need")) { + addResponse(getDialogueId(260685)); + applyFlag = true; + stateFlag = false; + } + break; + + case 27: + if (sentence->localWord("where") && (sentence->localWord("that") + || sentence->localWord("it"))) { + addResponse(getDialogueId(260262)); + applyFlag = true; + } + break; + + case 28: + if (sentence->localWord("why")) { + addResponse(getDialogueId(260386)); + applyFlag = true; + stateFlag = false; + } else if (sentence->localWord("insist")) { + addResponse(getDialogueId(260387)); + applyFlag = true; + stateFlag = false; + } + break; + + case 29: + if (sentence->_field2C == 11) { + setFlags12(); + addResponse(getDialogueId(260131)); + } else { + addResponse(getDialogueId(260966)); + } + applyFlag = true; + break; + + case 30: + if (sentence->_field2C == 11 || sentence->_field2C == 13) { + addResponse(getDialogueId(260695)); + applyFlag = true; + } else if (sentence->_field2C == 12) { + addResponse(getDialogueId(260696)); + applyFlag = true; + } + break; + } + + if (applyFlag) + applyResponse(); + if (stateFlag) { + setState(0); + CTrueTalkManager::setFlags(10, 0); + } + + return applyFlag ? 2 : 1; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/maitred_script.h b/engines/titanic/true_talk/maitred_script.h new file mode 100644 index 0000000000..0472050d20 --- /dev/null +++ b/engines/titanic/true_talk/maitred_script.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_MAITRED_SCRIPT_H +#define TITANIC_MAITRED_SCRIPT_H + +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class MaitreDScript : public TTnpcScript { +private: + TTmapEntryArray _states; + TTsentenceEntries _sentences1; + int _answerCtr; +private: + /** + * Setup sentence data + */ + void setupSentences(); + + /** + * Alter dialogue Id based on current NPC state + */ + uint getStateDialogueId(uint oldId, uint newId); + + /** + * Sets flags 12 and resets some ranges + */ + void setFlags12(); + + /** + * Sets flags 10 to different values based on the passed + * dialogue Id + */ + void setFlags10(uint newId, uint index); + + /** + * Trigers 12 + */ + void trigger12(bool flag); + + /** + * Does preprocessing for the sentence + */ + int preprocess(const TTroomScript *roomScript, const TTsentence *sentence); +public: + MaitreDScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_MAITRED_SCRIPT_H */ diff --git a/engines/titanic/true_talk/parrot_script.cpp b/engines/titanic/true_talk/parrot_script.cpp new file mode 100644 index 0000000000..b09e74505c --- /dev/null +++ b/engines/titanic/true_talk/parrot_script.cpp @@ -0,0 +1,110 @@ +/* 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/true_talk/parrot_script.h" +#include "titanic/titanic.h" + +namespace Titanic { + +ParrotScript::ParrotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, v4, v5, v6, v7) { + + loadRanges("Ranges/Parrot"); + setupSentences(); +} + +void ParrotScript::setupSentences() { + _mappings.load("Mappings/Parrot", 1); + _entries.load("Sentences/Parrot"); + _field68 = 0; + _entryCount = 0; +} + +int ParrotScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + if (tag == MKTAG('B', 'Y', 'Z', 'A')) { + addResponse(getDialogueId(280246)); + applyResponse(); + return 2; + } else { + return 1; + } +} + +int ParrotScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + if (processEntries(roomScript, sentence) == 2) { + int tagId = g_vm->_trueTalkManager->_quotes.find(sentence->_normalizedLine); + if (!tagId || chooseResponse(roomScript, sentence, tagId) != 2) { + addResponse(getDialogueId(sentence->check2C() ? 280248 : 280235)); + applyResponse(); + } + } + + return 2; +} + +ScriptChangedResult ParrotScript::scriptChanged(const TTroomScript *roomScript, uint id) { + if (id >= 280000 && id <= 280276) { + if (id == 280258) { + if (CTrueTalkManager::_currentNPC) { + CGameObject *chicken; + if (CTrueTalkManager::_currentNPC->find("Chicken", &chicken, FIND_PET)) + id = 280147 - getRandomBit(); + } + + id = getDialogueId(id); + } else { + if ((id == 280146 || id == 280147) && CTrueTalkManager::_currentNPC) { + CGameObject *chicken; + if (CTrueTalkManager::_currentNPC->find("Chicken", &chicken, FIND_PET)) + id = 280142; + } + + addResponse(getDialogueId(id)); + if (id == 280192) + addResponse(getDialogueId(280222)); + applyResponse(); + } + } + + if (id >= 80000 && id <= 80244) { + if ((id == 80155 || id == 80156) && CTrueTalkManager::_currentNPC) { + CGameObject *chicken; + if (CTrueTalkManager::_currentNPC->find("Chicken", &chicken, FIND_PET)) + id = 80151; + } + + addResponse(id); + if (id == 80201) + addResponse(getDialogueId(280222)); + applyResponse(); + } + + return (id == 3) ? SCR_2 : SCR_1; +} + +int ParrotScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + return 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/parrot_script.h b/engines/titanic/true_talk/parrot_script.h new file mode 100644 index 0000000000..ec7bec7629 --- /dev/null +++ b/engines/titanic/true_talk/parrot_script.h @@ -0,0 +1,63 @@ +/* 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_PARROT_SCRIPT_H +#define TITANIC_PARROT_SCRIPT_H + +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class ParrotScript : public TTnpcScript { +private: + /** + * Setup sentence data + */ + void setupSentences(); +public: + ParrotScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_PARROT_SCRIPT_H */ diff --git a/engines/titanic/true_talk/script_handler.cpp b/engines/titanic/true_talk/script_handler.cpp new file mode 100644 index 0000000000..64e789a4b9 --- /dev/null +++ b/engines/titanic/true_talk/script_handler.cpp @@ -0,0 +1,148 @@ +/* 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/true_talk/script_handler.h" +#include "titanic/true_talk/tt_concept.h" +#include "titanic/true_talk/tt_sentence.h" +#include "titanic/true_talk/tt_parser.h" +#include "titanic/true_talk/tt_word.h" +#include "titanic/titanic.h" + +namespace Titanic { + +/*------------------------------------------------------------------------*/ + +CScriptHandler::CScriptHandler(CTitleEngine *owner, int val1, int val2) : + _owner(owner), _script(owner->_script), _resources(g_vm->_exeResources), + _parser(this), _field10(0), _inputCtr(0), + _concept1P(nullptr), _concept2P(nullptr), _concept3P(nullptr), + _concept4P(nullptr), _field30(0) { + g_vm->_scriptHandler = this; + g_vm->_script = _script; + g_vm->_exeResources.reset(this, val1, val2); + _vocab = new TTvocab(val2); +} + +CScriptHandler::~CScriptHandler() { + delete _vocab; + delete _concept1P; + delete _concept2P; + delete _concept3P; + delete _concept4P; +} + +ScriptChangedResult CScriptHandler::scriptChanged(TTroomScript *roomScript, TTnpcScript *npcScript, uint dialogueId) { + if (!npcScript || !roomScript) { + ++_inputCtr; + return SCR_5; + } + + ScriptChangedResult result = roomScript->notifyScript(npcScript, dialogueId); + if (result == SCR_1) + result = npcScript->notifyScript(roomScript, dialogueId); + + if (result != SCR_3 && result != SCR_4) + return result; + + ++_inputCtr; + delete _concept1P; + delete _concept2P; + delete _concept3P; + delete _concept4P; + _concept1P = nullptr; + _concept2P = nullptr; + _concept3P = nullptr; + _concept4P = nullptr; + + return result; +} + +int CScriptHandler::processInput(TTroomScript *roomScript, TTnpcScript *npcScript, + const TTstring &line) { + if (!roomScript || !line.isValid()) + return SS_5; + + TTsentence *sentence = new TTsentence(_inputCtr++, line, this, roomScript, npcScript); + int result = _parser.preprocess(sentence); + roomScript->scriptPreprocess(sentence); + npcScript->scriptPreprocess(sentence); + + int canProcess = 0; + if (result) { + sentence->setState(result); + if (roomScript->canRespond(npcScript, sentence, result)) { + canProcess = npcScript->chooseResponse(roomScript, sentence, result); + } + } + + if (canProcess == 0 || canProcess == 1) { + if (!_parser.findFrames(sentence)) { + if (roomScript->canProcess(npcScript, sentence) && npcScript) { + npcScript->process(roomScript, sentence); + } + } + } + + delete sentence; + return SS_VALID; +} + +SimpleFile *CScriptHandler::openResource(const CString &name) { + return _owner->open(name); +} + +void CScriptHandler::setParserConcept(TTconcept *newConcept, TTconcept *oldConcept) { + _parser.conceptChanged(newConcept, oldConcept); +} + +int CScriptHandler::setResponse(TTscriptBase *script, TTresponse *response) { + return _owner->setResponse(script, response); +} + +void CScriptHandler::handleWord(const TTstring *str) { + handleWord1(str); + handleWord2(str); +} + +void CScriptHandler::handleWord1(const TTstring *str) { + if (_concept2P) + delete _concept2P; + _concept2P = nullptr; + + if (str) { + TTword word(*str, WC_UNKNOWN, 0); + _concept2P = new TTconcept(&word); + } +} + +void CScriptHandler::handleWord2(const TTstring *str) { + if (_concept1P) + delete _concept1P; + _concept1P = nullptr; + + if (str) { + TTword word(*str, WC_UNKNOWN, 0); + _concept1P = new TTconcept(&word); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/script_handler.h b/engines/titanic/true_talk/script_handler.h new file mode 100644 index 0000000000..193c60f719 --- /dev/null +++ b/engines/titanic/true_talk/script_handler.h @@ -0,0 +1,89 @@ +/* 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_SCRIPT_HANDLER_H +#define TITANIC_SCRIPT_HANDLER_H + +#include "titanic/true_talk/tt_npc_script.h" +#include "titanic/true_talk/tt_parser.h" +#include "titanic/true_talk/tt_room_script.h" +#include "titanic/true_talk/tt_string.h" +#include "titanic/true_talk/tt_vocab.h" +#include "titanic/support/exe_resources.h" + +namespace Titanic { + +class CTitleEngine; +class CScriptHandler; + +class CScriptHandler { +private: + CTitleEngine *_owner; + CExeResources &_resources; + int _field10; + int _inputCtr; + int _field30; +private: + void handleWord1(const TTstring *str); + void handleWord2(const TTstring *str); +public: + TTparser _parser; + TTvocab *_vocab; + TTscriptBase *_script; + TTconcept *_concept1P; + TTconcept *_concept2P; + TTconcept *_concept3P; + TTconcept *_concept4P; +public: + CScriptHandler(CTitleEngine *owner, int val1, int val2); + ~CScriptHandler(); + + /** + * Set the character and room + */ + ScriptChangedResult scriptChanged(TTroomScript *roomScript, + TTnpcScript *npcScript, uint dialogueId); + + int processInput(TTroomScript *roomScript, TTnpcScript *npcScript, + const TTstring &line); + + /** + * Open a resource for access + */ + SimpleFile *openResource(const CString &name); + + /** + * Called when concept data is copied from one to another + */ + void setParserConcept(TTconcept *newConcept, TTconcept *oldConcept); + + /** + * Sets a conversation reponse + */ + int setResponse(TTscriptBase *script, TTresponse *response); + + void handleWord(const TTstring *str); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SCRIPT_HANDLER_H */ diff --git a/engines/titanic/true_talk/script_support.cpp b/engines/titanic/true_talk/script_support.cpp new file mode 100644 index 0000000000..c24e275827 --- /dev/null +++ b/engines/titanic/true_talk/script_support.cpp @@ -0,0 +1,226 @@ +/* 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/true_talk/script_support.h" +#include "titanic/titanic.h" + +namespace Titanic { + +int TTnpcScriptResponse::size() const { + for (int idx = 0; idx < 4; ++idx) { + if (_values[idx] == 0) + return idx; + } + + return 4; +} + +/*------------------------------------------------------------------------*/ + +TTscriptRange::TTscriptRange(uint id, const Common::Array<uint> &values, + bool isRandom, bool isSequential) : + _id(id), _nextP(nullptr) { + _mode = SF_NONE; + if (isRandom) + _mode = SF_RANDOM; + if (isSequential) + _mode = SF_SEQUENTIAL; + + for (uint idx = 0; idx < values.size(); ++idx) + _values.push_back(values[idx]); +} + +/*------------------------------------------------------------------------*/ + + +bool TTsentenceEntry::load(Common::SeekableReadStream *s) { + if (s->pos() >= s->size()) + return false; + + _field0 = s->readUint32LE(); + _field4 = s->readUint32LE(); + _string8 = readStringFromStream(s); + _fieldC = s->readUint32LE(); + _string10 = readStringFromStream(s); + _string14 = readStringFromStream(s); + _string18 = readStringFromStream(s); + _string1C = readStringFromStream(s); + _field20 = s->readUint32LE(); + _string24 = readStringFromStream(s); + _field28 = s->readUint32LE(); + _field2C = s->readUint32LE(); + _field30 = s->readUint32LE(); + + return true; +} + +/*------------------------------------------------------------------------*/ + +void TTsentenceEntries::load(const CString &resName) { + TTsentenceEntry entry; + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(resName); + + while (entry.load(r)) + push_back(entry); + + delete r; +} + +/*------------------------------------------------------------------------*/ + +TTscriptMapping::TTscriptMapping() : _id(0) { + Common::fill(&_values[0], &_values[8], 0); +} + +/*------------------------------------------------------------------------*/ + +void TTscriptMappings::load(const char *name, int valuesPerMapping) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + _valuesPerMapping = valuesPerMapping; + + while (r->pos() < r->size()) { + resize(size() + 1); + TTscriptMapping &m = (*this)[size() - 1]; + + m._id = r->readUint32LE(); + for (int idx = 0; idx < valuesPerMapping; ++idx) + m._values[idx] = r->readUint32LE(); + } + + delete r; +} + +/*------------------------------------------------------------------------*/ + +void TTtagMappings::load(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + uint src = r->readUint32LE(); + uint dest = r->readUint32LE(); + + push_back(TTtagMapping(src, dest)); + } + + delete r; +} + +/*------------------------------------------------------------------------*/ + +void TTwordEntries::load(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + TTwordEntry we; + we._id = r->readUint32LE(); + we._text = readStringFromStream(r); + + push_back(we); + } + + delete r; +} + +/*------------------------------------------------------------------------*/ + +void TThandleQuoteEntries::load(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + _tag1 = r->readUint32LE(); + _tag2 = r->readUint32LE(); + _rangeStart = r->readUint32LE(); + _rangeEnd = r->readUint32LE(); + + while (r->pos() < r->size()) { + TThandleQuoteEntry qe; + qe._index = r->readUint32LE(); + qe._tagId = r->readUint32LE(); + qe._dialogueId = r->readUint32LE(); + + push_back(qe); + } + + delete r; +} + +/*------------------------------------------------------------------------*/ + +void TTmapEntryArray::load(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + TTmapEntry us; + us._src = r->readUint32LE(); + us._dest = r->readUint32LE(); + + push_back(us); + } + + delete r; +} + +int TTmapEntryArray::find(uint id) const { + for (uint idx = 0; idx < size(); ++idx) { + const TTmapEntry &me = (*this)[idx]; + if (me._src == id) + return me._dest; + } + + return 0; +} + +/*------------------------------------------------------------------------*/ + +void TTupdateStateArray::load(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + TTupdateState us; + us._newId = r->readUint32LE(); + us._newValue = r->readUint32LE(); + us._dialBits = r->readUint32LE(); + + push_back(us); + } + + delete r; +} + +/*------------------------------------------------------------------------*/ + +void TTcommonPhraseArray::load(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + TTcommonPhrase cp; + cp._str = readStringFromStream(r); + cp._dialogueId = r->readUint32LE(); + cp._roomNum = r->readUint32LE(); + cp._val1 = r->readUint32LE(); + + push_back(cp); + } + + delete r; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/script_support.h b/engines/titanic/true_talk/script_support.h new file mode 100644 index 0000000000..a41673bd5c --- /dev/null +++ b/engines/titanic/true_talk/script_support.h @@ -0,0 +1,194 @@ +/* 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_SCRIPT_SUPPORT_H +#define TITANIC_SCRIPT_SUPPORT_H + +#include "titanic/support/simple_file.h" + +namespace Titanic { + +#define DIALS_ARRAY_COUNT 10 + +enum ScriptArrayFlag { SF_NONE = 0, SF_RANDOM = 1, SF_SEQUENTIAL = 2 }; + +struct RoomDialogueId { + uint _roomNum; + uint _dialogueId; +}; + +struct TTnpcScriptResponse { + uint _tag; + uint _values[4]; + + /** + * Returns the size of the values list plus 1 + */ + int size() const; +}; + +struct TTscriptRange { + uint _id; + Common::Array<uint> _values; + TTscriptRange *_nextP; + uint _priorIndex; + ScriptArrayFlag _mode; + + TTscriptRange() : _id(0), _nextP(nullptr), + _priorIndex(0), _mode(SF_NONE) {} + TTscriptRange(uint id, const Common::Array<uint> &values, bool isRandom, + bool isSequential); +}; + + +struct TTsentenceEntry { + int _field0; + int _field4; + CString _string8; + int _fieldC; + CString _string10; + CString _string14; + CString _string18; + CString _string1C; + int _field20; + CString _string24; + int _field28; + int _field2C; + int _field30; + + TTsentenceEntry() : _field0(0), _field4(0), _fieldC(0), + _field20(0), _field28(0), _field2C(0), _field30(0) {} + + /** + * Load an entry from the passed stream, and returns true + * if an entry was successfully loaded + */ + bool load(Common::SeekableReadStream *s); +}; + +class TTsentenceEntries : public Common::Array<TTsentenceEntry> { +public: + /** + * Load a list of entries from the specified resource + */ + void load(const CString &resName); +}; + +struct TTscriptMapping { + uint _id; + uint _values[8]; + + TTscriptMapping(); +}; + +class TTscriptMappings : public Common::Array<TTscriptMapping> { +public: + int _valuesPerMapping; + + void load(const char *name, int valuesPerMapping); +}; + +struct TTtagMapping { + uint _src, _dest; + TTtagMapping() : _src(0), _dest(0) {} + TTtagMapping(uint src, uint dest) : _src(src), _dest(dest) {} +}; + +class TTtagMappings : public Common::Array<TTtagMapping> { +public: + void load(const char *name); +}; + +struct TTwordEntry { + uint _id; + CString _text; + + TTwordEntry() : _id(0) {} +}; + +class TTwordEntries : public Common::Array<TTwordEntry> { +public: + void load(const char *name); +}; + +struct TThandleQuoteEntry { + uint _index; + uint _tagId; + uint _dialogueId; + + TThandleQuoteEntry() : _index(0), _tagId(0), _dialogueId(0) {} +}; + +class TThandleQuoteEntries : public Common::Array<TThandleQuoteEntry> { +public: + uint _tag1, _tag2; + uint _rangeStart, _rangeEnd; +public: + TThandleQuoteEntries() : _tag1(0), _tag2(0), _rangeStart(0), _rangeEnd(0) {} + void load(const char *name); +}; + +struct TTmapEntry { + uint _src; + uint _dest; + + TTmapEntry() : _src(0), _dest(0) {} +}; + +class TTmapEntryArray : public Common::Array<TTmapEntry> { +public: + void load(const char *name); + + /** + * Finds a record by Id, and returns it's associated value + */ + int find(uint id) const; +}; + +struct TTupdateState { + uint _newId; + uint _newValue; + uint _dialBits; + + TTupdateState() : _newId(0), _newValue(0), _dialBits(0) {} +}; + +class TTupdateStateArray : public Common::Array<TTupdateState> { +public: + void load(const char *name); +}; + +struct TTcommonPhrase { + CString _str; + uint _dialogueId; + uint _roomNum; + uint _val1; +}; + +class TTcommonPhraseArray : public Common::Array<TTcommonPhrase> { +public: + void load(const char *name); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_NPC_SCRIPT_H */ diff --git a/engines/titanic/true_talk/succubus_script.cpp b/engines/titanic/true_talk/succubus_script.cpp new file mode 100644 index 0000000000..db537c6470 --- /dev/null +++ b/engines/titanic/true_talk/succubus_script.cpp @@ -0,0 +1,237 @@ +/* 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/true_talk/succubus_script.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +SuccUBusScript::SuccUBusScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTnpcScript(val1, charClass, v2, charName, v3, val2, v4, v5, v6, v7), + _isRoom101(false) { + + loadRanges("Ranges/SuccUBus"); + setupSentences(); +} + +void SuccUBusScript::setupSentences() { + _mappings.load("Mappings/SuccUBus", 1); + _entries.load("Sentences/SuccUBus"); + _field68 = 0; + _entryCount = 0; +} + +int SuccUBusScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + uint dialogueId = tag; + + switch (tag) { + case MKTAG('S', 'L', 'O', 'W'): + case MKTAG('T', 'H', 'R', 'T'): + dialogueId = 70021; + + case MKTAG('S', 'U', 'C', '1'): + dialogueId = getDialogueId(230009); + break; + + case MKTAG('S', 'U', 'C', '2'): + dialogueId = 70117; + break; + + case MKTAG('S', 'W', 'E', 'R'): + dialogueId = getRandomNumber(100) > 40 ? 70103 : getDialogueId(230030); + break; + + default: + break; + } + + if (dialogueId) { + addResponse(dialogueId); + applyResponse(); + return 2; + } else { + return 1; + } +} + +int SuccUBusScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + if (!CTrueTalkManager::getStateValue(1)) + return 2; + + if (roomScript && roomScript->_scriptId == 101) + _isRoom101 = true; + + int currState = getState(); + if (currState) { + int currMode = sentence->_field2C; + bool modeFlag1 = currMode == 11 || currMode == 13; + bool modeFlag2 = currMode == 12; + setState(0); + + switch (currState) { + case 1: + if (currMode == 3 || currMode == 10) + return setResponse(70050, 0); + break; + + case 2: + if (modeFlag1 || modeFlag2) + return setResponse(70070 + (getRandomBit() ? 254 : 0), 0); + break; + + case 3: + if (currMode == 3 || currMode == 10) + return setResponse(70074, 0); + break; + + case 4: + if (currMode == 4) + return setResponse(70077, 0); + if (currMode == 3) + return setResponse(getDialogueId(230117), 0); + break; + + case 5: + if (currMode == 3 || currMode == 10) + return setResponse(70089, 0); + break; + + case 6: + if (modeFlag1) + return setResponse(70103, 0); + if (modeFlag2) + return setResponse(70102, 0); + break; + + case 7: + if (modeFlag1) + return setResponse(getDialogueId(230157), 0); + break; + + case 8: + if (modeFlag1) + return setResponse(getDialogueId(230159), 0); + break; + + case 9: + if (modeFlag1) + return setResponse(getDialogueId(230160), 0); + break; + + case 10: + if (modeFlag1) + return setResponse(getDialogueId(230161), 0); + break; + + case 11: + if (modeFlag1) + return setResponse(getDialogueId(230142), 0); + break; + + case 12: + return setResponse(70030, 0); + + default: + break; + } + } + + if (processEntries(&_entries, _entryCount, roomScript, sentence) != 2) { + uint tagId = g_vm->_trueTalkManager->_quotes.find(sentence->_normalizedLine.c_str()); + if (tagId && chooseResponse(roomScript, sentence, tagId) != 2) { + addResponse(getDialogueId(230030)); + applyResponse(); + } + } + + return 2; +} + +ScriptChangedResult SuccUBusScript::scriptChanged(const TTroomScript *roomScript, uint id) { + if (id == 148) + CTrueTalkManager::setFlags(3, 1); + else if (id == 150) + CTrueTalkManager::setFlags(2, 1); + + if (id >= 230000 && id <= 230245) { + addResponse(getDialogueId(id)); + applyResponse(); + } + else if (id >= 70000 && id <= 70243) { + addResponse(id); + applyResponse(); + } + + return SCR_2; +} + +int SuccUBusScript::updateState(uint oldId, uint newId, int index) { + if (newId == 230199) { + return _isRoom101 ? 230148 : newId; + } else if (newId >= 230208 && newId <= 230235) { + addResponse(70158 - getRandomBit()); + return newId; + } else if (newId >= 230061 && newId <= 230063) { + if (getValue(2)) + return 230125; + } + + static const uint UPDATE_STATES[][2] = { + { 230078, 1 }, { 230106, 2 }, { 230112, 3 }, { 230115, 4 }, + { 230127, 5 }, { 230140, 6 }, { 230156, 7 }, { 230157, 8 }, + { 230159, 9 }, { 230160, 10 }, { 230161, 11 }, { 230072, 12 } + }; + + for (int idx = 0; idx < 12; ++idx) { + if (UPDATE_STATES[idx][0] == newId) { + setState(UPDATE_STATES[idx][1]); + break; + } + } + + return newId; +} + +int SuccUBusScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + if (val1 == 1 && roomScript && roomScript->_scriptId == 101) { + addResponse(getDialogueId(230239)); + applyResponse(); + return 2; + } + + return 0; +} + +int SuccUBusScript::setResponse(int dialogueId, int state) { + addResponse(dialogueId); + applyResponse(); + + if (state != -1) + setState(state); + + return 2; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/succubus_script.h b/engines/titanic/true_talk/succubus_script.h new file mode 100644 index 0000000000..d5cea7e66f --- /dev/null +++ b/engines/titanic/true_talk/succubus_script.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_SUCCUBUS_SCRIPT_H +#define TITANIC_SUCCUBUS_SCRIPT_H + +#include "titanic/true_talk/tt_npc_script.h" + +namespace Titanic { + +class SuccUBusScript : public TTnpcScript { +private: + bool _isRoom101; +private: + /** + * Setup sentence data + */ + void setupSentences(); + + /** + * Add a response and optionally set the state + */ + int setResponse(int dialogueId, int state = -1); +public: + SuccUBusScript(int val1, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Process a sentence fragment entry + */ + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_SUCCUBUS_SCRIPT_H */ diff --git a/engines/titanic/true_talk/title_engine.cpp b/engines/titanic/true_talk/title_engine.cpp new file mode 100644 index 0000000000..4dd45ba335 --- /dev/null +++ b/engines/titanic/true_talk/title_engine.cpp @@ -0,0 +1,83 @@ +/* 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/true_talk/title_engine.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CTitleEngine::CTitleEngine() : _script(nullptr), _scriptHandler(nullptr) { +} + +CTitleEngine::~CTitleEngine() { + delete _script; + delete _scriptHandler; +} + +void CTitleEngine::setup(int val1, int val2) { + _script = new TTTitleScript(); + _scriptHandler = new CScriptHandler(this, val1, val2); +} + +/*------------------------------------------------------------------------*/ + +STtitleEngine::STtitleEngine(): CTitleEngine(), + _responseP(nullptr), _field58(0) { +} + +STtitleEngine::~STtitleEngine() { + delete _stream; +} + +void STtitleEngine::reset() { + _field58 = 0; + _indexes.clear(); +} + +void STtitleEngine::setup(int val1, int val2) { + CTitleEngine::setup(val1, 3); +} + +int STtitleEngine::setResponse(TTscriptBase *script, TTresponse *response) { + _indexes.clear(); + for (TTresponse *respP = response; respP; respP = respP->getNext()) { + _indexes.push_back(respP->getDialogueId()); + } + + return 0; +} + +void STtitleEngine::dump(int val1, int val2) { + // TODO +} + +SimpleFile *STtitleEngine::open(const CString &name) { + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource( + CString::format("TEXT/%s", name.c_str())); + assert(stream); + + SimpleFile *file = new SimpleFile(); + file->open(stream); + return file; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/title_engine.h b/engines/titanic/true_talk/title_engine.h new file mode 100644 index 0000000000..afd2d3b92f --- /dev/null +++ b/engines/titanic/true_talk/title_engine.h @@ -0,0 +1,113 @@ +/* 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_TITLE_ENGINE_H +#define TITANIC_TITLE_ENGINE_H + +#include "common/stream.h" +#include "common/winexe_pe.h" +#include "titanic/support/string.h" +#include "titanic/true_talk/script_handler.h" +#include "titanic/true_talk/tt_response.h" +#include "titanic/true_talk/tt_script_base.h" +#include "titanic/true_talk/tt_title_script.h" + +namespace Titanic { + +class CTitleEngine; + +class CTitleStream : public SimpleFile { +public: + CTitleStream() : SimpleFile() {} +}; + +class CTitleEngine { +public: + CScriptHandler *_scriptHandler; + TTscriptBase *_script; +public: + CTitleEngine(); + virtual ~CTitleEngine(); + + /** + * Setup the engine + */ + virtual void setup(int val1, int val2 = 0); + + /** + * Sets a conversation reponse + */ + virtual int setResponse(TTscriptBase *script, TTresponse *response) { return SS_4; } + + virtual int proc4(int unused) const = 0; + virtual int proc5(int64 unused) const = 0; + virtual int proc6(int64 unused) const = 0; + virtual int proc7(int64 unused) const = 0; + virtual int proc8() const = 0; + + /** + * Open a designated file + */ + virtual SimpleFile *open(const CString &name) = 0; +}; + +class STtitleEngine : public CTitleEngine { +private: + Common::SeekableReadStream *_stream; + TTresponse *_responseP; + int _field58; +public: + Common::Array<uint> _indexes; + Common::Array<byte> _data; +public: + STtitleEngine(); + virtual ~STtitleEngine(); + + void reset(); + + /** + * Setup the engine + */ + virtual void setup(int val1, int val2 = 0); + + /** + * Sets a conversation reponse + */ + virtual int setResponse(TTscriptBase *script, TTresponse *response); + + virtual void dump(int val1, int val2); + + virtual int proc4(int unused) const { return 0; } + virtual int proc5(int64 unused) const { return 0; } + virtual int proc6(int64 unused) const { return 0; } + virtual int proc7(int64 unused) const { return 0; } + virtual int proc8() const { return 0; } + + /** + * Open a designated file + */ + virtual SimpleFile *open(const CString &name); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TITLE_ENGINE_H */ diff --git a/engines/titanic/true_talk/true_talk_manager.cpp b/engines/titanic/true_talk/true_talk_manager.cpp new file mode 100644 index 0000000000..19beee9796 --- /dev/null +++ b/engines/titanic/true_talk/true_talk_manager.cpp @@ -0,0 +1,597 @@ +/* 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/true_talk/true_talk_manager.h" +#include "titanic/core/tree_item.h" +#include "titanic/npcs/true_talk_npc.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" + +#define MKTAG_BE(a3,a2,a1,a0) ((uint32)((a3) | ((a2) << 8) | ((a1) << 16) | ((a0) << 24))) + +namespace Titanic { + +int CTrueTalkManager::_v1; +int CTrueTalkManager::_v2; +int CTrueTalkManager::_v3; +bool CTrueTalkManager::_v4; +bool CTrueTalkManager::_v5; +int CTrueTalkManager::_v6; +int CTrueTalkManager::_v7; +bool CTrueTalkManager::_v8; +int CTrueTalkManager::_v9; +bool CTrueTalkManager::_v10; +int CTrueTalkManager::_v11[41]; +CTrueTalkNPC *CTrueTalkManager::_currentNPC; + +/*------------------------------------------------------------------------*/ + +CTrueTalkManager::CTrueTalkManager(CGameManager *owner) : + _gameManager(owner), _scripts(&_titleEngine), _currentCharId(0), + _dialogueFile(nullptr), _dialogueId(0) { + _titleEngine.setup(3, 3); + _quotes.load(); + _quotesTree.load(); + + _currentNPC = nullptr; + g_vm->_trueTalkManager = this; +} + +CTrueTalkManager::~CTrueTalkManager() { + clear(); + g_vm->_trueTalkManager = nullptr; +} + +void CTrueTalkManager::save(SimpleFile *file) const { + saveStatics(file); + + saveNPC(file, 101); + saveNPC(file, 103); + saveNPC(file, 104); + saveNPC(file, 105); + saveNPC(file, 111); + saveNPC(file, 100); + saveNPC(file, 112); + saveNPC(file, 107); + file->writeNumber(0); +} + +void CTrueTalkManager::load(SimpleFile *file) { + loadStatics(file); + + // Iterate through loading characters + int charId = file->readNumber(); + while (charId) { + loadNPC(file, charId); + + int ident1 = file->readNumber(); + int ident2 = file->readNumber(); + + if (ident1 != MKTAG_BE('U', 'R', 'A', 'H')) { + while (ident2 != MKTAG_BE('A', 'K', 'E', 'R')) { + ident1 = ident2; + ident2 = file->readNumber(); + + if (!ident1) + break; + } + } + + // Get start of next character + charId = file->readNumber(); + } +} + +void CTrueTalkManager::loadStatics(SimpleFile *file) { + int count = file->readNumber(); + _v1 = file->readNumber(); + _v2 = file->readNumber(); + _v3 = file->readNumber(); + _v4 = file->readNumber() != 0; + _v5 = file->readNumber() != 0; + _v6 = file->readNumber(); + _v7 = file->readNumber(); + _v8 = file->readNumber() != 0; + _v9 = file->readNumber(); + _v10 = file->readNumber() != 0; + + for (int idx = count; idx > 10; --idx) + file->readNumber(); + + int count2 = file->readNumber(); + for (int idx = 0; idx < count2; ++idx) { + int v = file->readNumber(); + if (idx < 41) + _v11[idx] = v; + } +} + +void CTrueTalkManager::saveStatics(SimpleFile *file) { + file->writeNumber(10); + file->writeNumber(_v1); + file->writeNumber(_v2); + file->writeNumber(_v3); + file->writeNumber(_v4 ? 1 : 0); + file->writeNumber(_v5 ? 1 : 0); + file->writeNumber(_v6); + file->writeNumber(_v7); + file->writeNumber(_v8 ? 1 : 0); + file->writeNumber(_v9); + file->writeNumber(_v10 ? 1 : 0); + + file->writeNumber(41); + for (int idx = 0; idx < 41; ++idx) + file->writeNumber(_v11[idx]); +} + +void CTrueTalkManager::clear() { + delete _dialogueFile; + _dialogueFile = nullptr; + _currentCharId = 0; +} + +void CTrueTalkManager::setFlags(int index, int val) { + switch (index) { + case 1: + if (val >= 1 && val <= 3) + _v3 = val; + break; + + case 2: + _v4 = !val; + break; + + case 3: + _v5 = val != 0; + break; + + case 4: + if (val >= 0 && val <= 3) + _v6 = val; + break; + + case 5: + _v7 = val; + break; + + case 6: + _v8 = val != 0; + break; + + default: + if (index < 41) + _v11[index] = val; + break; + } +} + +void CTrueTalkManager::loadNPC(SimpleFile *file, int charId) { + TTnpcScript *script = _scripts.getNpcScript(charId); + if (script) + script->load(file); +} + +void CTrueTalkManager::saveNPC(SimpleFile *file, int charId) const { + TTnpcScript *script = _scripts.getNpcScript(charId); + if (script) { + script->save(file); + file->writeNumber(MKTAG_BE('U', 'R', 'A', 'H')); + file->writeNumber(MKTAG_BE('A', 'K', 'E', 'R')); + } +} + +void CTrueTalkManager::preLoad() { + // Delete any previous talkers + for (TTtalkerList::iterator i = _talkers.begin(); i != _talkers.end(); ++i) + delete *i; + _talkers.clear(); +} + +void CTrueTalkManager::removeCompleted() { + for (TTtalkerList::iterator i = _talkers.begin(); i != _talkers.end(); ) { + TTtalker *talker = *i; + + if (talker->_done) { + i = _talkers.erase(i); + delete talker; + } else { + ++i; + } + } +} + +void CTrueTalkManager::update2() { + //warning("CTrueTalkManager::update2"); +} + +void CTrueTalkManager::start(CTrueTalkNPC *npc, uint id, CViewItem *view) { + TTnpcScript *npcScript = getNpcScript(npc); + TTroomScript *roomScript = getRoomScript(); + + _titleEngine.reset(); + uint charId = npcScript->charId(); + loadAssets(npc, charId); + + _currentNPC = npc; + _titleEngine._scriptHandler->scriptChanged(roomScript, npcScript, id); + _currentNPC = nullptr; + + setDialogue(npc, roomScript, view); +} + +void CTrueTalkManager::start3(CTrueTalkNPC *npc, CViewItem *view) { + start(npc, 3, view); +} + +void CTrueTalkManager::start4(CTrueTalkNPC *npc, CViewItem *view) { + start(npc, 4, view); +} + +TTnpcScript *CTrueTalkManager::getTalker(const CString &name) const { + if (name.contains("Doorbot")) + return _scripts.getNpcScript(104); + else if (name.contains("DeskBot")) + return _scripts.getNpcScript(103); + else if (name.contains("LiftBot")) + return _scripts.getNpcScript(105); + else if (name.contains("Parrot")) + return _scripts.getNpcScript(107); + else if (name.contains("BarBot")) + return _scripts.getNpcScript(100); + else if (name.contains("ChatterBot")) + return _scripts.getNpcScript(102); + else if (name.contains("BellBot")) + return _scripts.getNpcScript(101); + else if (name.contains("MaitreD")) + return _scripts.getNpcScript(112); + else if (name.contains("Succubus") || name.contains("Sub")) + return _scripts.getNpcScript(111); + + return nullptr; +} + +TTnpcScript *CTrueTalkManager::getNpcScript(CTrueTalkNPC *npc) const { + CString npcName = npc->getName(); + TTnpcScript *script = getTalker(npcName); + + if (!script) { + // Fall back on the default NPC script + script = _scripts.getNpcScript(101); + } + + return script; +} + +TTroomScript *CTrueTalkManager::getRoomScript() const { + CRoomItem *room = _gameManager->getRoom(); + TTroomScript *script = nullptr; + if (room) { + int scriptId = room->getScriptId(); + if (scriptId) + script = _scripts.getRoomScript(scriptId); + } + + if (!script) { + // Fall back on the default Room script + script = _scripts.getRoomScript(110); + } + + return script; +} + +TTroomScript *CTrueTalkManager::getRoomScript(int roomId) const { + TTroomScript *script = nullptr; + if (roomId) + script = _scripts.getRoomScript(roomId); + + if (!script) + // Fall back on the default Room script + script = _scripts.getRoomScript(110); + + return script; +} + +void CTrueTalkManager::loadAssets(CTrueTalkNPC *npc, int charId) { + // If assets for the character are already loaded, simply exit + if (_currentCharId == charId) + return; + + // Clear any previously loaded data + clear(); + + // Signal the NPC to get the asset details + CTrueTalkGetAssetDetailsMsg detailsMsg; + detailsMsg.execute(npc); + + if (!detailsMsg._filename.empty()) { + _dialogueFile = new CDialogueFile(detailsMsg._filename, 20); + _dialogueId = detailsMsg._numValue + 1; + } +} + +void CTrueTalkManager::processInput(CTrueTalkNPC *npc, CTextInputMsg *msg, CViewItem *view) { + TTnpcScript *npcScript = getNpcScript(npc); + TTroomScript *roomScript = getRoomScript(); + _titleEngine.reset(); + + if (npcScript && roomScript) { + _currentNPC = npc; + _titleEngine._scriptHandler->processInput(roomScript, npcScript, TTstring(msg->_input)); + _currentNPC = nullptr; + + loadAssets(npc, npcScript->charId()); + setDialogue(npc, roomScript, view); + } + + _currentNPC = nullptr; +} + +void CTrueTalkManager::setDialogue(CTrueTalkNPC *npc, TTroomScript *roomScript, CViewItem *view) { + // Get the dialog text + CString dialogueStr = readDialogueString(); + if (dialogueStr.empty()) + return; + + int soundId = readDialogSound(); + TTtalker *talker = new TTtalker(this, npc); + _talkers.push_back(talker); + + bool isParrot = npc->getName().contains("parrot"); + triggerNPC(npc); + playSpeech(talker, roomScript, view, isParrot); + talker->speechStarted(dialogueStr, _titleEngine._indexes[0], soundId); +} + +#define STRING_BUFFER_SIZE 2048 + +CString CTrueTalkManager::readDialogueString() { + byte buffer[STRING_BUFFER_SIZE]; + CString result; + + for (uint idx = 0; idx < _titleEngine._indexes.size(); ++idx) { + if (idx != 0) + result += " "; + + // Open a text entry from the dialogue file for access + DialogueResource *textRes = _dialogueFile->openTextEntry( + _titleEngine._indexes[idx] - _dialogueId); + if (!textRes) + continue; + + size_t entrySize = textRes->size(); + byte *tempBuffer = (entrySize < STRING_BUFFER_SIZE) ? buffer : + new byte[entrySize + 1]; + + _dialogueFile->read(textRes, tempBuffer, entrySize); + buffer[entrySize] = '\0'; + + // Close the resource + _dialogueFile->closeEntry(textRes); + + // Strip off any non-printable characters + for (byte *p = buffer; *p != '\0'; ++p) { + if (*p < 32 || *p > 127) + *p = ' '; + } + + // Add string to result + result += CString((const char *)buffer); + + // Free buffer if one was allocated + if (entrySize >= STRING_BUFFER_SIZE) + delete[] tempBuffer; + } + + return result; +} + +int CTrueTalkManager::readDialogSound() { + _field18 = 0; + + for (uint idx = 0; idx < _titleEngine._indexes.size(); ++idx) { + CWaveFile *waveFile = _gameManager->_sound.getTrueTalkSound( + _dialogueFile, _titleEngine._indexes[idx] - _dialogueId); + if (waveFile) { + _field18 = waveFile->fn1(); + } + } + + return _field18; +} + +void CTrueTalkManager::triggerNPC(CTrueTalkNPC *npc) { + CTrueTalkSelfQueueAnimSetMsg queueSetMsg; + if (queueSetMsg.execute(npc)) { + if (_field18 > 300) { + CTrueTalkQueueUpAnimSetMsg upMsg(_field18); + upMsg.execute(npc); + } + } else { + CTrueTalkGetAnimSetMsg getAnimMsg; + if (_field18 > 300) { + do { + getAnimMsg.execute(npc); + if (!getAnimMsg._endFrame) + break; + + npc->playMovie(getAnimMsg._startFrame, getAnimMsg._endFrame, 0); + getAnimMsg._endFrame = 0; + + uint numFrames = getAnimMsg._endFrame - getAnimMsg._startFrame; + int64 val = (numFrames * 1000) * 0x88888889; + uint diff = (val >> (32 + 5)) - 500; + _field18 += diff; + + getAnimMsg._index++; + } while (_field18 > 0); + } + } +} + +void CTrueTalkManager::playSpeech(TTtalker *talker, TTroomScript *roomScript, CViewItem *view, bool isParrot) { + uint milli, index; + switch (roomScript->_scriptId) { + case 101: + milli = 300; + index = 16; + break; + case 106: + case 107: + case 110: + case 114: + case 115: + case 122: + milli = 130; + index = 10; + break; + case 108: + case 109: + milli = 200; + index = 10; + break; + case 111: + case 116: + case 121: + milli = 80; + index = 12; + break; + case 112: + case 124: + case 128: + case 130: + milli = 80; + index = 4; + break; + case 132: + milli = 60; + index = 4; + break; + default: + milli = 0; + index = 4; + break; + } + + // Setup proximities + CProximity p1, p2, p3; + if (isParrot) { + p1._channel = 3; + p2._channel = 5; + p3._channel = 4; + } else { + p1._channel = 0; + p2._channel = 1; + p3._channel = 2; + } + + if (milli > 0) { + p3._channelVolume = (index * 3) / 2; + p3._positioningMode = POSMODE_POLAR; + p3._azimuth = -135.0; + p3._range = 1.0; + p3._elevation = 0; + + p2._channelVolume = (index * 3) / 4; + p2._positioningMode = POSMODE_NONE; + p2._azimuth = 135.0; + p2._range = 1.0; + p2._elevation = 0; + } + + _gameManager->_sound.stopChannel(p1._channel); + if (view) { + p1._positioningMode = POSMODE_VECTOR; + view->getPosition(p1._posX, p1._posY, p1._posZ); + } + + // Loop through adding each of the speech portions in. We use the + // _priorSoundHandle of CProximity to chain each successive speech + // to start when the prior one finishes + for (uint idx = 0; idx < _titleEngine._indexes.size(); ++idx) { + uint id = _titleEngine._indexes[idx]; + if (id > 100000) + continue; + + if (idx == (_titleEngine._indexes.size() - 1)) { + // Final iteration of speech segments to play + p1._endTalkerFn = &talkerEnd; + p1._talker = talker; + } + + // Start the speech + p1._priorSoundHandle = _gameManager->_sound.playSpeech(_dialogueFile, id - _dialogueId, p1); + if (!milli) + continue; + + if (idx == 0) + g_vm->_events->sleep(milli); + + p3._priorSoundHandle = _gameManager->_sound.playSpeech(_dialogueFile, id - _dialogueId, p3); + if (idx == 0) + g_vm->_events->sleep(milli); + + p2._priorSoundHandle = _gameManager->_sound.playSpeech(_dialogueFile, id - _dialogueId, p2); + } +} + +int CTrueTalkManager::getStateValue(int stateNum) { + if (!_currentNPC) + return -1000; + + CTrueTalkGetStateValueMsg msg(stateNum, -1000); + msg.execute(_currentNPC); + return msg._stateVal; +} + +bool CTrueTalkManager::triggerAction(int action, int param) { + if (!_currentNPC) + return false; + + CTrueTalkTriggerActionMsg msg(action, param, 0); + msg.execute(_currentNPC); + return true; +} + +void CTrueTalkManager::talkerEnd(TTtalker *talker) { + if (talker) + talker->endSpeech(0); +} + +CGameManager *CTrueTalkManager::getGameManager() const { + return _gameManager; +} + +CGameState *CTrueTalkManager::getGameState() const { + return _gameManager ? &_gameManager->_gameState : nullptr; +} + +int CTrueTalkManager::getPassengerClass() const { + CGameState *gameState = getGameState(); + return gameState ? gameState->_passengerClass : 4; +} + +int CTrueTalkManager::getState14() const { + CGameState *gameState = getGameState(); + return gameState ? gameState->_field14 : 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/true_talk_manager.h b/engines/titanic/true_talk/true_talk_manager.h new file mode 100644 index 0000000000..8a8895917a --- /dev/null +++ b/engines/titanic/true_talk/true_talk_manager.h @@ -0,0 +1,245 @@ +/* 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_TRUE_TALK_MANAGER_H +#define TITANIC_TRUE_TALK_MANAGER_H + +#include "titanic/messages/messages.h" +#include "titanic/support/simple_file.h" +#include "titanic/true_talk/dialogue_file.h" +#include "titanic/true_talk/title_engine.h" +#include "titanic/true_talk/tt_quotes.h" +#include "titanic/true_talk/tt_quotes_tree.h" +#include "titanic/true_talk/tt_scripts.h" +#include "titanic/true_talk/tt_talker.h" + +namespace Titanic { + +class CGameManager; +class CGameState; +class CTreeItem; +class CViewItem; +class CTrueTalkManager; +class CTrueTalkNPC; + +class CTrueTalkManager { +private: + CGameManager *_gameManager; + STtitleEngine _titleEngine; + TTscripts _scripts; + int _currentCharId; + CDialogueFile *_dialogueFile; + int _dialogueId; + int _field18; + TTtalkerList _talkers; +private: + /** + * Loads the statics for the class + */ + static void loadStatics(SimpleFile *file); + + /** + * Saves the statics associated with the class + */ + static void saveStatics(SimpleFile *file); + + /** + * Loads an NPC from file + */ + void loadNPC(SimpleFile *file, int charId); + + /** + * Saves the specified NPC to file + */ + void saveNPC(SimpleFile *file, int charId) const; + + /** + * Gets the script associated with an NPC game object + */ + TTnpcScript *getNpcScript(CTrueTalkNPC *npc) const; + + /** + * Gets the script associated with the current room + */ + TTroomScript *getRoomScript() const; + + /** + * Loads assets for the current character, if it's changed + */ + void loadAssets(CTrueTalkNPC *npc, int charId); + + void setDialogue(CTrueTalkNPC *npc, TTroomScript *roomScript, CViewItem *view); + + /** + * Read in text from the dialogue file + */ + CString readDialogueString(); + + /** + * Read in the sound from the dialogue file + */ + int readDialogSound(); + + /** + * Triggers animation for the NPC + */ + void triggerNPC(CTrueTalkNPC *npc); + + /** + * Plays speech specified by the manager's indexes array + */ + void playSpeech(TTtalker *talker, TTroomScript *roomScript, CViewItem *view, bool isParrot); + + /** + * Called when a talker finishes + */ + static void talkerEnd(TTtalker *talker); + + /** + * Return the game state + */ + CGameState *getGameState() const; +public: + static int _v1; + static int _v2; + static int _v3; + static bool _v4; + static bool _v5; + static int _v6; + static int _v7; + static bool _v8; + static int _v9; + static bool _v10; + static int _v11[41]; + static CTrueTalkNPC *_currentNPC; + + static void setFlags(int index, int val); +public: + TTquotes _quotes; + TTquotesTree _quotesTree; +public: + /** + * Get a specified state value from the currently set NPC + */ + static int getStateValue(int stateNum); + + /** + * Trigger an NPC action + */ + static bool triggerAction(int action, int param); +public: + CTrueTalkManager(CGameManager *owner); + ~CTrueTalkManager(); + + /** + * Save the data for the class to file + */ + void save(SimpleFile *file) const; + + /** + * Load the data for the class from file + */ + void load(SimpleFile *file); + + /** + * Clear the manager + */ + void clear(); + + /** + * Called when a game is about to be loaded + */ + void preLoad(); + + /** + * Called when loading a game is complete + */ + void postLoad() {} + + /** + * Called when a game is about to be saved + */ + void preSave() {} + + /** + * Called when a game has finished being saved + */ + void postSave() {} + + /** + * Returns the scripts for the manager + */ + TTscripts &getScripts() { return _scripts; } + + /** + * Remove any completed talkers + */ + void removeCompleted(); + + /** + * Return the game manager + */ + CGameManager *getGameManager() const; + + void update2(); + + /** + * Start a TrueTalk conversation + */ + void start(CTrueTalkNPC *npc, uint id, CViewItem *view); + + /** + * Start a TrueTalk conversation + */ + void start3(CTrueTalkNPC *npc, CViewItem *view); + + /** + * Start a TrueTalk conversation + */ + void start4(CTrueTalkNPC *npc, CViewItem *view); + + /** + * Return a TrueTalk talker/script + */ + TTnpcScript *getTalker(const CString &name) const; + + /** + * Process player's input + */ + void processInput(CTrueTalkNPC *npc, CTextInputMsg *msg, CViewItem *view); + + /** + * Gets the script associated with a specific room + */ + TTroomScript *getRoomScript(int roomId) const; + + /** + * Get the player's passenger class + */ + int getPassengerClass() const; + + int getState14() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TRUE_TALK_MANAGER_H */ diff --git a/engines/titanic/true_talk/tt_action.cpp b/engines/titanic/true_talk/tt_action.cpp new file mode 100644 index 0000000000..5bf91c71df --- /dev/null +++ b/engines/titanic/true_talk/tt_action.cpp @@ -0,0 +1,69 @@ +/* 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/true_talk/tt_action.h" + +namespace Titanic { + +bool TTaction::_staticFlag; + +TTaction::TTaction(const TTstring &str, WordClass wordClass, int val2, int val3, int val4) : + TTmajorWord(str, wordClass, val2, val3), _field30(val4) { +} + +TTaction::TTaction(const TTaction *src) : TTmajorWord(src) { + if (src->getStatus()) { + _field30 = 0; + _status = SS_5; + } else { + _field30 = src->_field30; + } +} + +int TTaction::load(SimpleFile *file) { + int val; + + if (!TTword::load(file, WC_ACTION) && file->scanf("%d", &val)) { + _field30 = val; + return 0; + } else { + return 8; + } +} + +TTword *TTaction::copy() const { + TTaction *returnWordP = new TTaction(this); + returnWordP->_status = _status; + if (!_status) { + _staticFlag = false; + return returnWordP; + } else if (_status == SS_13 && !_staticFlag) { + _staticFlag = true; + delete returnWordP; + return copy(); + } else { + delete returnWordP; + return nullptr; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_action.h b/engines/titanic/true_talk/tt_action.h new file mode 100644 index 0000000000..29e2bc4e4a --- /dev/null +++ b/engines/titanic/true_talk/tt_action.h @@ -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. + * + */ + +#ifndef TITANIC_TT_ACTION_H +#define TITANIC_TT_ACTION_H + +#include "titanic/true_talk/tt_major_word.h" + +namespace Titanic { + +class TTaction : public TTmajorWord { +private: + static bool _staticFlag; +protected: + int _field30; +public: + TTaction(const TTstring &str, WordClass wordClass, int val2, int val3, int val4); + TTaction(const TTaction *src); + + /** + * Load the word + */ + int load(SimpleFile *file); + + void setVal(int val) { _field30 = val; } + int getVal() const { return _field30; } + + /** + * Creates a copy of the word + */ + virtual TTword *copy() const; + + virtual bool proc12(int val) const { return _field30 == val; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_ACTION_H */ diff --git a/engines/titanic/true_talk/tt_adj.cpp b/engines/titanic/true_talk/tt_adj.cpp new file mode 100644 index 0000000000..a14784798f --- /dev/null +++ b/engines/titanic/true_talk/tt_adj.cpp @@ -0,0 +1,84 @@ +/* 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/true_talk/tt_adj.h" + +namespace Titanic { + +bool TTadj::_staticFlag; + +TTadj::TTadj(TTstring &str, WordClass wordClass, int val2, int val3, int val4) : + TTmajorWord(str, wordClass, val2, val3) { + if (val4 >= 0 && val4 <= 9) { + _val = val4; + } else { + _val = 0; + _status = SS_5; + } +} + +TTadj::TTadj(const TTadj *src) : TTmajorWord(src) { + if (src->getStatus()) { + _val = 0; + _status = SS_5; + } else { + _val = src->_val; + } +} + +int TTadj::load(SimpleFile *file) { + int val; + + if (!TTword::load(file, WC_ADJECTIVE) && file->scanf("%d", &val)) { + _val = val; + return 0; + } else { + return 8; + } +} + +int TTadj::adjFn1(int val) { + if (_val < 0 || _val > 9) { + return SS_4; + } else { + _val = val; + return SS_VALID; + } +} + +TTword *TTadj::copy() const { + TTadj *returnWordP = new TTadj(this); + returnWordP->_status = _status; + if (!_status) { + _staticFlag = false; + return returnWordP; + } else if (_status == SS_13 && !_staticFlag) { + _staticFlag = true; + delete returnWordP; + return copy(); + } else { + delete returnWordP; + return nullptr; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_adj.h b/engines/titanic/true_talk/tt_adj.h new file mode 100644 index 0000000000..1dec8a77d2 --- /dev/null +++ b/engines/titanic/true_talk/tt_adj.h @@ -0,0 +1,67 @@ +/* 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_TT_ADJ_H +#define TITANIC_TT_ADJ_H + +#include "titanic/true_talk/tt_major_word.h" + +namespace Titanic { + +class TTadj : public TTmajorWord { +private: + static bool _staticFlag; +protected: + int _val; +public: + TTadj(TTstring &str, WordClass wordClass, int val2, int val3, int val4); + TTadj(const TTadj *src); + + /** + * Load the word + */ + int load(SimpleFile *file); + + int adjFn1(int val); + + /** + * Creates a copy of the word + */ + virtual TTword *copy() const; + + virtual bool proc14(int val) const { return _val == val; } + virtual int proc15() const { return _val; } + virtual bool proc16() const { return _val >= 7; } + virtual bool proc17() const { return _val <= 3; } + virtual bool proc18() const { return _val > 3 && _val < 7; } + + /** + * Dumps data associated with the word to file + */ + virtual int save(SimpleFile *file) const { + return saveData(file, _val); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_ADJ_H */ diff --git a/engines/titanic/true_talk/tt_concept.cpp b/engines/titanic/true_talk/tt_concept.cpp new file mode 100644 index 0000000000..c614e14dae --- /dev/null +++ b/engines/titanic/true_talk/tt_concept.cpp @@ -0,0 +1,308 @@ +/* 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/true_talk/tt_concept.h" +#include "titanic/true_talk/tt_script_base.h" +#include "titanic/true_talk/tt_word.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTconcept::TTconcept() : _string1(" "), _string2(" "), + _scriptP(nullptr), _wordP(nullptr) { + if (setStatus()) + setScriptType(ST_UNKNOWN_SCRIPT); + else + reset(); +} + +TTconcept::TTconcept(TTscriptBase *script, ScriptType scriptType) : + _string1(" "), _string2(" "), _wordP(nullptr), _scriptP(nullptr) { + if (!script->getStatus()) { + setScriptType(scriptType); + _scriptP = script; + + if (scriptType == ST_UNKNOWN_SCRIPT && script->_id == 1) + _scriptType = ST_ROOM_SCRIPT; + } + + if (_status) + reset(); +} + +TTconcept::TTconcept(TTword *word, ScriptType scriptType) : + _string1(" "), _string2(" "), _wordP(nullptr), _scriptP(nullptr) { + + if (!word || !setStatus() || word->getStatus()) { + _status = SS_5; + } else { + _status = initializeWordRef(word); + if (!_status) + setScriptType(scriptType); + } + + if (_status) + reset(); +} + +TTconcept::TTconcept(TTconcept &src) : + _string1(src._string1), _string2(src._string2), + _wordP(nullptr), _scriptP(nullptr) { + + if (src.getStatus()) { + _status = SS_5; + } else { + if (setStatus()) { + _status = SS_VALID; + _scriptP = src._scriptP; + + if (src._wordP) { + _status = initializeWordRef(src._wordP); + initialize(src); + } + } + } + + if (_status) + reset(); +} + +TTconcept::~TTconcept() { + if (_word2P) { + _word2P->deleteSiblings(); + delete _word2P; + } + delete _wordP; + + if (_flag) + g_vm->_exeResources._owner->setParserConcept(this, nullptr); +} + +void TTconcept::deleteSiblings() { + for (TTconcept *currP = _nextP, *nextP; currP; currP = nextP) { + nextP = currP->_nextP; + delete currP; + } + + _nextP = nullptr; +} + +bool TTconcept::setStatus() { + if (_string1.isValid() && _string2.isValid()) { + _status = SS_VALID; + return true; + } else { + _status = SS_11; + return false; + } +} + +void TTconcept::setScriptType(ScriptType scriptType) { + _nextP = nullptr; + _field14 = 0; + _scriptType = scriptType; + _field1C = -1; + _field20 = 0; + _word2P = nullptr; + _field30 = 0; + _field34 = 0; + _flag = false; + _status = 0; +} + +int TTconcept::initializeWordRef(TTword *word) { + delete _wordP; + _wordP = word; + return 0; +} + +void TTconcept::reset() { + delete _wordP; + _wordP = nullptr; + _scriptP = nullptr; + + int oldStatus = _status; + setScriptType(ST_UNKNOWN_SCRIPT); + _status = oldStatus; +} + +bool TTconcept::compareTo(const char *str) const { + return this != nullptr && _wordP != nullptr && + _wordP->compareTo(str); +} + +bool TTconcept::compareTo(TTword *word) const { + if (_wordP && _wordP->compareTo(word->_text)) + return true; + + if (_scriptP && _scriptP->getId() == 1 && word->comparePronounTo(1)) + return true; + + return false; +} + +void TTconcept::initialize(TTconcept &src) { + _nextP = src._nextP; + _field14 = src._field14; + _scriptType = src._scriptType; + _field1C = src._field1C; + _field20 = src._field20; + + if (src._word2P) { + _word2P = src._word2P->copyWords(); + if (src._word2P->getChainStatus()) + _status = 11; + } else { + _word2P = nullptr; + } + + _field30 = src._field30; + _field34 = src._field34; + + if (src._flag) { + g_vm->_exeResources._owner->setParserConcept(this, &src); + src.setFlag(true); + _flag = true; + } + + _status = src._status; +} + +void TTconcept::copyFrom(TTconcept *src) { + if (this != src) { + if (src->getStatus()) { + _status = SS_5; + } else { + _string1 = src->_string1; + _string2 = src->_string2; + + if (setStatus()) { + _scriptP = src->_scriptP; + if (src->_wordP) { + _status = initializeWordRef(src->_wordP); + initialize(*src); + } else { + _wordP = nullptr; + initialize(*src); + } + } + } + } + + if (_status) + reset(); +} + +int TTconcept::setOwner(TTconcept *src) { + if (this) { + if (src->_wordP) { + TTword *newWord = src->_wordP->copy(); + return setOwner(newWord, 1); + } + } + + return 0; +} + +int TTconcept::setOwner(TTword *src, bool dontDup) { + TTword *word = dontDup ? src : src->copy(); + + if (word) { + if (!_word2P) { + _word2P = word; + } else { + // Add word to end of word list + TTword *tailP = _word2P; + while (tailP->_nextP) + tailP = tailP->_nextP; + + tailP->_nextP = word; + } + } + + return 0; +} + +bool TTconcept::checkWordId1() const { + return (_wordP && (_wordP->_id == 200 || _wordP->_id == 201 || + _wordP->_id == 602 || _wordP->_id == 607)) || + (_scriptP && _scriptP->_id <= 2); +} + +bool TTconcept::checkWordId2() const { + return (_wordP && _wordP->_id == 204) || (_scriptP && _scriptP->getId() == 3); +} + +bool TTconcept::checkWordId3() const { + return isWordClass(WC_ABSTRACT) || isWordClass(WC_ADJECTIVE) || + (isWordClass(WC_ADVERB) && getWordId() != 910); +} + +bool TTconcept::checkWordClass() const { + return !_scriptP && _wordP && (_wordP->_wordClass == WC_THING || _wordP->_wordClass == WC_PRONOUN); +} + +const TTstring TTconcept::getText() { + if (_scriptP) + return _scriptP->getText(); + else if (_wordP) + return _wordP->getText(); + else + return TTstring(); +} + +TTconcept *TTconcept::findByWordId(int id) { + for (TTconcept *conceptP = this; conceptP; conceptP = conceptP->_nextP) { + if (conceptP->_wordP && conceptP->_wordP->_id == id) + return conceptP; + } + + return nullptr; +} + +TTconcept *TTconcept::findByWordClass(WordClass wordClass) { + for (TTconcept *conceptP = this; conceptP; conceptP = conceptP->_nextP) { + if (conceptP->_wordP && conceptP->_wordP->_wordClass == wordClass) + return conceptP; + } + + return nullptr; +} + +TTconcept *TTconcept::findBy20(int val) { + for (TTconcept *conceptP = this; conceptP; conceptP = conceptP->_nextP) { + if (conceptP->_field20 == val) + return conceptP; + } + + return nullptr; +} + +bool TTconcept::isWordId(int id) const { + return this && _wordP && _wordP->_id == id; +} + +int TTconcept::getWordId() const { + return this && _wordP ? _wordP->_id : 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_concept.h b/engines/titanic/true_talk/tt_concept.h new file mode 100644 index 0000000000..88afb6f28b --- /dev/null +++ b/engines/titanic/true_talk/tt_concept.h @@ -0,0 +1,172 @@ +/* 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_TT_CONCEPT_H +#define TITANIC_TT_CONCEPT_H + +#include "titanic/true_talk/tt_string.h" +#include "titanic/true_talk/tt_word.h" + +namespace Titanic { + +enum ScriptType { ST_UNKNOWN_SCRIPT = 0, ST_ROOM_SCRIPT = 1, ST_NPC_SCRIPT = 2 }; + +class TTscriptBase; +class TTword; + +class TTconcept { +private: + TTstring _string1; + int _field1C; + TTword *_word2P; + int _field30; + bool _flag; + int _status; +private: + /** + * Sets the status of the concept + */ + bool setStatus(); + + /** + * Sets the script type and resets other fields + */ + void setScriptType(ScriptType scriptType); + + /** + * Sets up the concept for a word reference + */ + int initializeWordRef(TTword *word); + + /** + * Resets the concept + */ + void reset(); + + /** + * Initialize inner data for the concept from a given source concept + */ + void initialize(TTconcept &src); +public: + TTconcept *_nextP; + TTscriptBase *_scriptP; + TTword *_wordP; + int _scriptType; + int _field14; + int _field20; + int _field34; + TTstring _string2; +public: + TTconcept(); + TTconcept(TTscriptBase *script, ScriptType scriptType); + TTconcept(TTword *word, ScriptType scriptType = ST_UNKNOWN_SCRIPT); + TTconcept(TTconcept &src); + ~TTconcept(); + + /** + * Destroys any attached sibling concepts to the given concept + */ + void deleteSiblings(); + + /** + * Copies data from a source concept + */ + void copyFrom(TTconcept *src); + + /** + * Compares the name of the associated word, if any, to the passed string + */ + bool compareTo(const char *str) const; + + /** + * Compares the concept to the specified word + */ + bool compareTo(TTword *word) const; + + /** + * Set an owner for the concept + */ + int setOwner(TTconcept *src); + + /** + * Set an owner for the concept + */ + int setOwner(TTword *src, bool dontDup); + + /** + * Return the status of the concept + */ + int getStatus() const { return _status; } + + /** + * True true if the concept is valid + */ + bool isValid() const { return _status == SS_VALID; } + + /** + * Returns true if the word is of the specified class + */ + bool isWordClass(WordClass wordClass) const { + return _wordP && _wordP->isClass(wordClass); + } + + void setFlag(bool val) { _flag = val; } + void set1C(int val) { _field1C = val; } + int get20() const { return _field20; } + int getState() const { return _field34; } + + bool checkWordId1() const; + bool checkWordId2() const; + bool checkWordId3() const; + bool checkWordClass() const; + + /** + * Return text assocaited with the concept's word or script + */ + const TTstring getText(); + + /** + * Find a word by Id + */ + TTconcept *findByWordId(int id); + + /** + * Find a word by it's class + */ + TTconcept *findByWordClass(WordClass wordClass); + + TTconcept *findBy20(int val); + + /** + * Returns true if the concept has a word with a given Id + */ + bool isWordId(int id) const; + + /** + * If a word is associated, return it's Id + */ + int getWordId() const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_CONCEPT_H */ diff --git a/engines/titanic/true_talk/tt_concept_node.cpp b/engines/titanic/true_talk/tt_concept_node.cpp new file mode 100644 index 0000000000..454ca59971 --- /dev/null +++ b/engines/titanic/true_talk/tt_concept_node.cpp @@ -0,0 +1,165 @@ +/* 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/true_talk/tt_concept_node.h" +#include "titanic/true_talk/script_handler.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTconceptNode::TTconceptNode() : _concept0P(_concepts[0]), _concept1P(_concepts[1]), + _concept2P(_concepts[2]), _concept3P(_concepts[3]), _concept4P(_concepts[4]), + _concept5P(_concepts[5]), _field18(0), _field1C(0), _nextP(nullptr), _status(0) { +} + +TTconceptNode::TTconceptNode(const TTconceptNode &src) : _concept0P(_concepts[0]), _concept1P(_concepts[1]), + _concept2P(_concepts[2]), _concept3P(_concepts[3]), _concept4P(_concepts[4]), + _concept5P(_concepts[5]), _field18(0), _field1C(0), _nextP(nullptr), _status(0) { + if (src._status) { + _status = SS_5; + } else { + for (int idx = 0; idx < 6; ++idx) { + if (src._concepts[idx]) { + _concepts[idx] = new TTconcept(*src._concepts[idx]); + if (!_concepts[idx]->isValid()) + _status = SS_11; + } + } + + _field18 = src._field18; + _field1C = src._field1C; + _nextP = src._nextP; + } +} + +void TTconceptNode::deleteSiblings() { + // Iterate through the linked chain of nodes, deleting each in turn + for (TTconceptNode *curP = _nextP, *nextP = nullptr; nextP; curP = nextP) { + nextP = curP->_nextP; + delete curP; + } + + _nextP = nullptr; +} + +TTconcept **TTconceptNode::setConcept(int conceptIndex, TTconcept *src) { + TTconcept **conceptPP = nullptr; + switch (conceptIndex) { + case 1: + conceptPP = &_concept1P; + break; + case 2: + conceptPP = &_concept2P; + break; + case 3: + conceptPP = &_concept3P; + break; + case 4: + conceptPP = &_concept4P; + break; + case 5: + conceptPP = &_concept5P; + break; + default: + break; + } + + bool isPronoun = false; + StringArray &pronouns = g_vm->_scriptHandler->_parser._pronouns; + for (uint idx = 0; idx < pronouns.size() && !isPronoun; ++idx) { + isPronoun = pronouns[idx] == src->getText(); + } + + CScriptHandler &scrHandler = *g_vm->_exeResources._owner; + if (!isPronoun) { + switch (conceptIndex) { + case 0: + delete scrHandler._concept2P; + scrHandler._concept2P = new TTconcept(*src); + break; + + case 1: + delete scrHandler._concept4P; + scrHandler._concept4P = new TTconcept(*src); + break; + + case 2: + delete scrHandler._concept1P; + scrHandler._concept1P = new TTconcept(*src); + break; + + default: + break; + } + } + + return conceptPP; +} + +int TTconceptNode::replaceConcept(int mode, int conceptIndex, TTconcept *concept) { + TTconcept **conceptPP = setConcept(conceptIndex, concept); + + if (mode == 0 || (mode == 1 && !*conceptPP)) { + if (!concept || !concept->isValid()) + return SS_5; + + if (mode == 0 && *conceptPP) { + delete *conceptPP; + } + + *conceptPP = new TTconcept(*concept); + return (*conceptPP)->isValid() ? SS_VALID : SS_11; + } else { + return SS_1; + } +} + +int TTconceptNode::changeConcept(int mode, TTconcept **conceptPP, int conceptIndex) { + TTconcept **newConceptPP = setConcept(conceptIndex, *conceptPP); + + if (mode == 0 || (mode == 1 && !*newConceptPP)) { + if (!*conceptPP) + return SS_5; + + delete *newConceptPP; + *newConceptPP = new TTconcept(**conceptPP); + return SS_VALID; + } else { + return SS_1; + } +} + +bool TTconceptNode::createConcept(int mode, int conceptIndex, TTword *word) { + TTconcept *newConcept = new TTconcept(word, ST_UNKNOWN_SCRIPT); + TTconcept **conceptPP = setConcept(conceptIndex, newConcept); + + if (mode == 0 || (mode == 1 && !*conceptPP)) { + delete *conceptPP; + *conceptPP = newConcept; + return false; + } else { + delete newConcept; + return true; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_concept_node.h b/engines/titanic/true_talk/tt_concept_node.h new file mode 100644 index 0000000000..9a1c3a9912 --- /dev/null +++ b/engines/titanic/true_talk/tt_concept_node.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_TT_CONCEPT_NODE_H +#define TITANIC_TT_CONCEPT_NODE_H + +#include "titanic/true_talk/tt_concept.h" + +namespace Titanic { + +class TTconceptNode { +public: + TTconcept *_concepts[6]; + TTconcept *&_concept0P; + TTconcept *&_concept1P; + TTconcept *&_concept2P; + TTconcept *&_concept3P; + TTconcept *&_concept4P; + TTconcept *&_concept5P; + int _field18; + int _field1C; + TTconceptNode *_nextP; + int _status; +public: + TTconceptNode(); + TTconceptNode(const TTconceptNode &src); + + /** + * Delete any sibling chain attached to this node + */ + void deleteSiblings(); + + void set18(int val) { _field18 = val; } + int get18() const { return _field18; } + + /** + * Returns true if the node is valid + */ + bool isValid() const { return _status == SS_VALID; } + + TTconcept **setConcept(int conceptIndex, TTconcept *src); + int replaceConcept(int mode, int conceptIndex, TTconcept *concept); + int changeConcept(int mode, TTconcept **conceptPP, int conceptIndex); + bool createConcept(int mode, int conceptIndex, TTword *word); + + int concept1WordId() const { + return _concept1P ? _concept1P->getWordId() : 0; + } + int concept5WordId() const { + return _concept5P ? _concept5P->getWordId() : 0; + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_CONCEPT_NODE_H */ diff --git a/engines/titanic/true_talk/tt_hist.cpp b/engines/titanic/true_talk/tt_hist.cpp new file mode 100644 index 0000000000..fae9ae6286 --- /dev/null +++ b/engines/titanic/true_talk/tt_hist.cpp @@ -0,0 +1,36 @@ +/* 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/true_talk/tt_hist.h" +#include "titanic/true_talk/tt_sentence.h" + +namespace Titanic { + +TThist::TThist(TTsentence *sentence) : _status(0) { + _sentence = new TTsentence(sentence); +} + +TThist::~TThist() { + delete _sentence; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_hist.h b/engines/titanic/true_talk/tt_hist.h new file mode 100644 index 0000000000..f67a0387c5 --- /dev/null +++ b/engines/titanic/true_talk/tt_hist.h @@ -0,0 +1,47 @@ +/* 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_TT_HIST_H +#define TITANIC_TT_HIST_H + +namespace Titanic { + +class TTsentence; + +class TThist { +protected: + int _field0; + TTsentence *_sentence; + int _status; +public: + TThist(TTsentence *sentence); + virtual ~TThist(); +}; + +class TTscriptHist : public TThist { +public: + TTscriptHist(TTsentence *sentence) : TThist(sentence) {} +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_HIST_H */ diff --git a/engines/titanic/true_talk/tt_major_word.cpp b/engines/titanic/true_talk/tt_major_word.cpp new file mode 100644 index 0000000000..18a56a40be --- /dev/null +++ b/engines/titanic/true_talk/tt_major_word.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/true_talk/tt_major_word.h" + +namespace Titanic { + +bool TTmajorWord::_staticFlag; + +TTmajorWord::TTmajorWord(const TTstring &str, WordClass wordClass, int val2, int val3) : + TTword(str, wordClass, val2), _field2C(val3) { +} + +TTmajorWord::TTmajorWord(const TTmajorWord *src) : TTword(src) { + if (src->getStatus()) { + _field2C = 0; + _status = SS_5; + } else { + _field2C = src->_field2C; + } +} + +int TTmajorWord::saveData(SimpleFile *file, int val) const { + int result = TTword::save(file); + if (!result) { + file->writeFormat("%1.0d", val); + file->writeFormat("%c", '\n'); + if (_synP) + result = _synP->save(file); + } + + return result; +} + +TTword *TTmajorWord::copy() const { + TTmajorWord *returnWordP = new TTmajorWord(this); + returnWordP->_status = _status; + if (!_status) { + _staticFlag = false; + return returnWordP; + } else if (_status == SS_13 && !_staticFlag) { + _staticFlag = true; + delete returnWordP; + return copy(); + } else { + delete returnWordP; + return nullptr; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_major_word.h b/engines/titanic/true_talk/tt_major_word.h new file mode 100644 index 0000000000..c9a708abfb --- /dev/null +++ b/engines/titanic/true_talk/tt_major_word.h @@ -0,0 +1,54 @@ +/* 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_TT_MAJOR_WORD_H +#define TITANIC_TT_MAJOR_WORD_H + +#include "titanic/true_talk/tt_word.h" + +namespace Titanic { + +class TTmajorWord : public TTword { +private: + static bool _staticFlag; +protected: + int _field2C; +protected: + /** + * Dumps data for the word to a file + */ + int saveData(SimpleFile *file, int val) const; +public: + TTmajorWord(const TTstring &str, WordClass wordClass, int val2, int val3); + TTmajorWord(const TTmajorWord *src); + + /** + * Creates a copy of the word + */ + virtual TTword *copy() const; + + virtual bool proc2(int val) const { return _field2C == val; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_MAJOR_WORD_H */ diff --git a/engines/titanic/true_talk/tt_node.cpp b/engines/titanic/true_talk/tt_node.cpp new file mode 100644 index 0000000000..cbbb1dd756 --- /dev/null +++ b/engines/titanic/true_talk/tt_node.cpp @@ -0,0 +1,89 @@ +/* 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/true_talk/tt_node.h" + +namespace Titanic { + +TTnode::TTnode() : _priorP(nullptr), _nextP(nullptr) { +} + +TTnode::~TTnode() { + detach(); +} + +void TTnode::addToTail(TTnode *newNode) { + TTnode *tail = getTail(); + tail->_nextP = newNode; + newNode->_priorP = this; +} + +void TTnode::addToHead(TTnode *newNode) { + TTnode *head = getHead(); + head->_priorP = newNode; + newNode->_nextP = head; +} + +void TTnode::detach() { + if (_priorP) + _priorP->_nextP = _nextP; + + if (_nextP) + _nextP->_priorP = _priorP; +} + +void TTnode::deleteSiblings() { + // Detach current node from prior one, if there is one + if (_priorP) + _priorP->_nextP = nullptr; + + // Iterate through the linked chain of nodes, deleting each in turn + for (TTnode *curP = _nextP, *nextP = nullptr; nextP; curP = nextP) { + nextP = curP->_nextP; + delete curP; + } +} + +TTnode *TTnode::getHead() { + if (_priorP == nullptr) + return this; + + TTnode *node = _priorP; + while (node->_priorP) + node = node->_priorP; + + return node; +} + +TTnode *TTnode::getTail() { + if (_nextP == nullptr) + return this; + + TTnode *node = _nextP; + while (node->_nextP) + node = node->_nextP; + + return node; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_node.h b/engines/titanic/true_talk/tt_node.h new file mode 100644 index 0000000000..36d44288fd --- /dev/null +++ b/engines/titanic/true_talk/tt_node.h @@ -0,0 +1,69 @@ +/* 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_TT_NODE_H +#define TITANIC_TT_NODE_H + +namespace Titanic { + +class TTnode { +public: + TTnode *_priorP; + TTnode *_nextP; +public: + TTnode(); + virtual ~TTnode(); + + /** + * Adds a new node at the beginning of the linked list + */ + void addToHead(TTnode *newNode); + + /** + * Links the passed node to this node as a linked list + */ + void addToTail(TTnode *newNode); + + /** + * Detaches a node from any predecessor and/or successor + */ + void detach(); + + /** + * Delete any sibling chain attached to this node + */ + void deleteSiblings(); + + /** + * Returns the first node at the beginning of a linked list of nodes + */ + TTnode *getHead(); + + /** + * Returns the final node at the end of the linked list of nodes + */ + TTnode *getTail(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_NODE_H */ diff --git a/engines/titanic/true_talk/tt_npc_script.cpp b/engines/titanic/true_talk/tt_npc_script.cpp new file mode 100644 index 0000000000..61c3b0e00c --- /dev/null +++ b/engines/titanic/true_talk/tt_npc_script.cpp @@ -0,0 +1,1009 @@ +/* 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/algorithm.h" +#include "common/textconsole.h" +#include "titanic/messages/messages.h" +#include "titanic/pet_control/pet_control.h" +#include "titanic/true_talk/tt_npc_script.h" +#include "titanic/true_talk/tt_sentence.h" +#include "titanic/true_talk/true_talk_manager.h" +#include "titanic/game_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTsentenceEntries *TTnpcScript::_defaultEntries; + +static const char *const ITEMS[] = { + "chicken", "napkin", "parrot", "moth", "fuse", "eye", "nose", "ear", "mouth", + "auditorycenter", "visioncenter", "olfactorycenter", "speechcenter", "stick", + "longstick", "bomb", "lemon", "puree", "television", "hammer", nullptr +}; + +struct ItemRec { + const char *const _name; + uint _id; +}; +static const ItemRec ARRAY1[] = { + { ITEMS[0], 290138 }, + { ITEMS[1], 290139 }, + { ITEMS[2], 290141 }, + { ITEMS[3], 290142 }, + { ITEMS[4], 290153 }, + { ITEMS[5], 290158 }, + { ITEMS[6], 290159 }, + { ITEMS[7], 290160 }, + { ITEMS[8], 290161 }, + { ITEMS[9], 290162 }, + { ITEMS[10], 290163 }, + { ITEMS[11], 290164 }, + { ITEMS[12], 290165 }, + { ITEMS[13], 290166 }, + { ITEMS[14], 290166 }, + { ITEMS[15], 290178 }, + { ITEMS[16], 290174 }, + { ITEMS[17], 290175 }, + { ITEMS[18], 290176 }, + { ITEMS[19], 290179 }, + { nullptr, 0 } +}; +static const uint ARRAY2[] = { + 290167, 290178, 290183, 290144, 290148, 290151, 290154, 290156, 290158, 290159, 290160, 290161, + 290162, 290163, 290164, 290165, 290177, 290181, 0 +}; +static const uint RANDOM1[] = { + 290184, 290185, 290187, 290188, 290190, 290191, 290193, 290195, 290196, 290197, 290198, 290199, + 290202, 290205, 0 +}; +static const uint RANDOM2[] = { + 290186, 290187, 290188, 290190, 290191, 290193, 290194, 290195, 290196, 290197, 290198, 290199, + 290200, 290201, 290202, 290204, 290205, 0 +}; +static const uint RANDOM3[] = { + 290188, 290190, 290192, 290194, 290197, 290200, 290201, 290202, 290204, 290205, 0 +}; +static const uint RANDOM4[] = { + 290206, 290207, 290209, 290210, 290211, 290212, 290216, 290217, 290218, 290219, 290222, 290223, 0 +}; +static const uint RANDOM5[] = { + 290208, 290209, 290210, 290211, 290212, 290214, 290215, 290216, 290217, 290218, 290219, 290221, + 290222, 290223, 0 +}; +static const uint RANDOM6[] = { + 290210, 290211, 290213, 290214, 290215, 290220, 290221, 290222, 290223, 0 +}; +static const uint RANDOM7[] = { + 290225, 290226, 290228, 290229, 290230, 290232, 290231, 290235, 290236, 290237, 290238, 290241, 0 +}; +static const uint RANDOM8[] = { + 290227, 290228, 290229, 290230, 290231, 290232, 290233, 290234, 290235, 290236, 290237, 290238, + 290240, 290241, 0 +}; +static const uint RANDOM9[] = { + 290228, 290229, 290230, 290232, 290233, 290234, 290239, 290240, 290241, 0 +}; + +/*------------------------------------------------------------------------*/ + +TTnpcData::TTnpcData() { + Common::fill(&_array[0], &_array[136], 0); +} + +void TTnpcData::resetFlags() { + Common::fill(&_array[20], &_array[136], 0); +} + +/*------------------------------------------------------------------------*/ + +TTnpcScriptBase::TTnpcScriptBase(int charId_, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTscriptBase(0, charClass, v2, charName, v3, v4, v5, v6, v7), + _charId(charId_), _field54(0), _val2(val2) { +} + +/*------------------------------------------------------------------------*/ + +void TTnpcScript::init() { + _defaultEntries = new TTsentenceEntries(); + _defaultEntries->load("Sentences/Default"); +} + +void TTnpcScript::deinit() { + delete _defaultEntries; + _defaultEntries = nullptr; +} + +TTnpcScript::TTnpcScript(int charId_, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) : + TTnpcScriptBase(charId_, charClass, v2, charName, v3, val2, v4, v5, v6, v7), + _entryCount(0), _field68(0), _field6C(0), _rangeResetCtr(0), + _currentDialNum(0), _dialDelta(0), _field7C(0), _itemStringP(nullptr), _field2CC(false) { + CTrueTalkManager::_v2 = 0; + Common::fill(&_dialValues[0], &_dialValues[DIALS_ARRAY_COUNT], 0); + + if (!CTrueTalkManager::_v10) { + Common::fill(&CTrueTalkManager::_v11[0], &CTrueTalkManager::_v11[41], 0); + CTrueTalkManager::_v10 = true; + } + + resetFlags(); +} + +void TTnpcScript::loadResponses(const char *name, int valuesPerResponse) { + _valuesPerResponse = valuesPerResponse; + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + TTnpcScriptResponse sr; + sr._tag = r->readUint32LE(); + for (int idx = 0; idx < valuesPerResponse; ++idx) + sr._values[idx] = r->readUint32LE(); + + _responses.push_back(sr); + } + + delete r; +} + +void TTnpcScript::loadRanges(const char *name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + + while (r->pos() < r->size()) { + Common::Array<uint> values; + uint id = r->readUint32LE(); + bool isRandom = r->readByte(); + bool isSequential = r->readByte(); + + uint v; + do { + v = r->readUint32LE(); + values.push_back(v); + } while (v); + + addRange(id, values, isRandom, isSequential); + } + + delete r; +} + +void TTnpcScript::resetFlags() { + _data.resetFlags(); + _field2CC = false; +} + +void TTnpcScript::setupDials(int dial1, int dial2, int dial3) { + _dialValues[0] = dial1; + _dialValues[1] = dial2; + _dialValues[2] = dial3; + _currentDialNum = getRandomNumber(3) - 1; + _dialDelta = getRandomNumber(5) + 6; + + if (_dialValues[0] > 70) + _dialDelta = -_dialDelta; +} + +void TTnpcScript::addResponse(int id) { + if (id > 200000) + id = getDialogueId(id); + + handleWord(id); + TTscriptBase::addResponse(id); +} + +int TTnpcScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) { + for (uint idx = 0; idx < _responses.size(); ++idx) { + const TTnpcScriptResponse &response = _responses[idx]; + + if (response._tag == tag) { + if (_valuesPerResponse == 1) { + selectResponse(response._values[0]); + } else { + int valIndex = getRandomNumber(response.size()) - 1; + uint diagId = getDialogueId(response._values[valIndex]); + addResponse(diagId); + } + + applyResponse(); + return 2; + } + } + + return 1; +} + +int TTnpcScript::process(const TTroomScript *roomScript, const TTsentence *sentence) { + return processEntries(&_entries, _entryCount, roomScript, sentence); +} + +int TTnpcScript::proc8() const { + return 0; +} + +int TTnpcScript::proc11() const { + return 2; +} + +int TTnpcScript::proc12() const { + return 1; +} + +void TTnpcScript::selectResponse(int id) { + if (id >= 200000 && id <= 290264) + id = getDialogueId(id); + + addResponse(id); +} + +bool TTnpcScript::handleWord(uint id) const { + if (_words.empty()) + return false; + + for (uint idx = 0; idx < _words.size(); ++idx) { + const TTwordEntry &we = _words[idx]; + if (we._id == id) { + TTstring str(we._text); + g_vm->_scriptHandler->handleWord(&str); + return true; + } + } + + g_vm->_scriptHandler->handleWord(nullptr); + return true; +} + +int TTnpcScript::handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder) { + if (_quotes.empty()) + return 1; + + + int loopCounter = 0; + for (uint idx = 0; idx < _quotes.size() && loopCounter < 2; ++idx) { + const TThandleQuoteEntry *qe = &_quotes[idx]; + + if (!qe->_index) { + // End of list; start at beginning again + ++loopCounter; + idx = 0; + qe = &_quotes[0]; + } + + if (qe->_index == val && ( + (tagId == 0 && loopCounter == 2) || + (qe->_tagId < MKTAG('A', 'A', 'A', 'A')) || + (qe->_tagId == tagId) + )) { + uint foundTagId = qe->_tagId; + if (foundTagId > 0 && foundTagId < 100) { + if (!tagId) + foundTagId >>= 1; + if (getRandomNumber(100) < foundTagId) + return 1; + } + + uint dialogueId = qe->_dialogueId; + if (dialogueId >= _quotes._rangeStart && dialogueId <= _quotes._rangeEnd) { + dialogueId -= _quotes._rangeStart; + if (dialogueId > 3) + error("Invalid dialogue index in BarbotScript"); + + const int RANDOM_LIMITS[4] = { 30, 50, 70, 60 }; + int rangeLimit = RANDOM_LIMITS[dialogueId]; + int dialRegion = getDialRegion(0); + + if (dialRegion != 1) { + rangeLimit = MAX(rangeLimit - 20, 20); + } + + dialogueId = (((int)remainder + 25) % 100) >= rangeLimit + ? _quotes._tag1 : _quotes._tag2; + } + + addResponse(getDialogueId(dialogueId)); + applyResponse(); + return 2; + } + } + + return 1; + +} + +uint TTnpcScript::getRangeValue(uint id) { + TTscriptRange *range = findRange(id); + if (!range) + return 0; + + switch (range->_mode) { + case SF_RANDOM: { + uint count = range->_values.size(); + + uint index = getRandomNumber(count) - 1; + if (count > 1 && range->_values[index] == range->_priorIndex) { + for (int retry = 0; retry < 8 && index != range->_priorIndex; ++retry) + index = getRandomNumber(count) - 1; + } + + range->_priorIndex = index; + return range->_values[index]; + } + + case SF_SEQUENTIAL: { + // Get the next value from the array sequentially + int val = range->_values[range->_priorIndex]; + if (!val) { + // Reached end of array, so reset back to start + range->_priorIndex = 1; + val = range->_values[1]; + } + + ++range->_priorIndex; + return val; + } + + default: + if (range->_values[range->_priorIndex]) + return range->_values[range->_priorIndex++]; + + range->_priorIndex = 1; + ++_rangeResetCtr; + return range->_values[0]; + } +} + +void TTnpcScript::resetRange(int id) { + TTscriptRange *range = findRange(id); + if (range && range->_mode != SF_RANDOM) + range->_priorIndex = 0; +} + +int TTnpcScript::updateState(uint oldId, uint newId, int index) { + return newId; +} + +int TTnpcScript::preResponse(uint id) { + return 0; +} + +const TTscriptMapping *TTnpcScript::getMapping(int index) { + if (index >= 0 && index < (int)_mappings.size()) + return &_mappings[index]; + return nullptr; +} + +int TTnpcScript::doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence) { + return 0; +} + +void TTnpcScript::save(SimpleFile *file) { + file->writeNumber(charId()); + saveBody(file); + + file->writeNumber(4); + file->writeNumber(_rangeResetCtr); + file->writeNumber(_currentDialNum); + file->writeNumber(_dialDelta); + file->writeNumber(_field7C); + + file->writeNumber(10); + for (int idx = 0; idx < 10; ++idx) + file->writeNumber(_data[idx]); +} + +void TTnpcScript::load(SimpleFile *file) { + loadBody(file); + + int count = file->readNumber(); + _rangeResetCtr = file->readNumber(); + _currentDialNum = file->readNumber(); + _dialDelta = file->readNumber(); + _field7C = file->readNumber(); + + for (int idx = count; idx > 4; --idx) + file->readNumber(); + + count = file->readNumber(); + for (int idx = 0; idx < count; ++idx) { + int v = file->readNumber(); + if (idx < 10) + _data[idx] = v; + } +} + +void TTnpcScript::saveBody(SimpleFile *file) { + int count = proc31(); + file->writeNumber(count); + + if (count > 0) { + for (uint idx = 0; idx < _ranges.size(); ++idx) { + const TTscriptRange &item = _ranges[idx]; + if (item._mode == SF_RANDOM && item._priorIndex) { + file->writeNumber(item._id); + file->writeNumber(item._priorIndex); + } + } + } +} + +void TTnpcScript::loadBody(SimpleFile *file) { + int count = file->readNumber(); + preLoad(); + + for (int index = 0; index < count; index += 2) { + int id = file->readNumber(); + int val = file->readNumber(); + + for (uint idx = 0; idx < _ranges.size(); ++idx) { + TTscriptRange &item = _ranges[idx]; + if (item._id == (uint)id) { + item._priorIndex = val; + break; + } + } + } +} + +int TTnpcScript::proc31() const { + int count = 0; + for (uint idx = 0; idx < _ranges.size(); ++idx) { + const TTscriptRange &item = _ranges[idx]; + if (item._mode != SF_RANDOM && item._priorIndex) + ++count; + } + + return count * 2; +} + +void TTnpcScript::setDialRegion(int dialNum, int region) { + if (dialNum < DIALS_ARRAY_COUNT) + _dialValues[dialNum] = region * 100; + + if (g_vm->_trueTalkManager) { + CPetControl *petControl = getPetControl(g_vm->_trueTalkManager->getGameManager()); + if (petControl) + petControl->playSound(1); + } +} + +void TTnpcScript::setDial(int dialNum, int value) { + if (dialNum < DIALS_ARRAY_COUNT) { + int oldRegion = getDialRegion(dialNum); + + int newRegion = 1; + if (value < 50) + newRegion = 0; + else if (value > 150) + newRegion = 2; + + if (oldRegion == newRegion) + setDialRegion(dialNum, newRegion); + + _dialValues[dialNum] = value; + } + + if (g_vm->_trueTalkManager) { + CPetControl *petControl = getPetControl(g_vm->_trueTalkManager->getGameManager()); + if (petControl) + petControl->convResetDials(); + } +} + +int TTnpcScript::getDialRegion(int dialNum) const { + if (dialNum < DIALS_ARRAY_COUNT) { + int value = _dialValues[dialNum]; + if (value < 50) + return 0; + else if (value > 150) + return 2; + else + return 1; + } else { + return 0; + } +} + +int TTnpcScript::getDialLevel(uint dialNum, bool randomizeFlag) { + int result = _dialValues[dialNum]; + if (randomizeFlag) { + bool lowFlag = result <= 50; + result = CLIP(result + (int)getRandomNumber(18) - 9, 0, 100); + + if (lowFlag) { + result = MIN(result, 46); + } else { + result = MAX(result, 54); + } + } + + return result; +} + +bool TTnpcScript::randomResponse(uint index) { + return false; +} + +uint TTnpcScript::translateId(uint id) const { + for (uint idx = 0; idx < _tagMappings.size(); ++idx) { + if (_tagMappings[idx]._src == id) + return _tagMappings[idx]._dest; + } + + return 0; +} + +void TTnpcScript::preLoad() { + for (uint idx = 0; idx < _ranges.size(); ++idx) + _ranges[idx]._priorIndex = 0; +} + +int TTnpcScript::getRoom54(int roomId) { + TTroomScript *room = g_vm->_trueTalkManager->getRoomScript(roomId); + return room ? room->_field54 : 0; +} + +int TTnpcScript::getValue(int testNum) const { + switch (testNum) { + case 0: + return CTrueTalkManager::_v2; + + case 1: + if (g_vm->_trueTalkManager) + CTrueTalkManager::_v3 = g_vm->_trueTalkManager->getPassengerClass(); + return CTrueTalkManager::_v3; + + case 2: + return CTrueTalkManager::_v4; + + case 3: + return CTrueTalkManager::_v5 != 0; + + case 4: + if (g_vm->_trueTalkManager) { + switch (g_vm->_trueTalkManager->getState14()) { + case 1: + CTrueTalkManager::_v6 = 3; + break; + case 2: + CTrueTalkManager::_v6 = 0; + break; + case 3: + CTrueTalkManager::_v6 = 1; + break; + default: + CTrueTalkManager::_v6 = 2; + break; + } + } + return CTrueTalkManager::_v6; + + case 5: + return CTrueTalkManager::_v7; + + case 6: + return CTrueTalkManager::_v8 != 0; + + case 7: + return !!getRoom54(123); + + default: + return CTrueTalkManager::_v11[testNum]; + } +} + +uint TTnpcScript::getRandomNumber(int max) const { + return 1 + g_vm->getRandomNumber(max - 1); +} + +uint TTnpcScript::getDialogueId(uint tagId) { + if (tagId < 200000) + return tagId; + + // Perform any script specific translation + uint origId = tagId; + if (tagId >= 290000 && tagId <= 290263) + tagId = translateId(tagId); + if (!tagId) + return 0; + + if (!_field2CC) { + _field2CC = true; + int val = translateByArray(tagId); + if (val > 0) { + if (randomResponse(val)) + return 4; + } + } + + uint oldTagId = tagId; + tagId = getRangeValue(tagId); + if (tagId != oldTagId) + tagId = getRangeValue(tagId); + + oldTagId = getDialsBitset(); + uint newId = updateState(origId, tagId, oldTagId); + if (!newId) + return 0; + + int idx = 0; + const TTscriptMapping *tableP; + for (;;) { + tableP = getMapping(idx++); + if (!tableP) + return 0; + + if (tableP->_id == newId) + break; + } + uint newVal = tableP->_values[oldTagId]; + + // First slot dialogue Ids + idx = 0; + int *arrP = _data.getSlot(0); + while (idx < 4 && arrP[idx]) + ++idx; + + if (idx == 4) + return newVal; + arrP[idx] = origId; + + // Second slot dialogue Ids + idx = 0; + arrP = _data.getSlot(1); + while (idx < 4 && arrP[idx]) + ++idx; + + if (idx == 4) + return newVal; + arrP[idx] = newVal; + + return newVal; +} + +int TTnpcScript::translateByArray(int id) { + for (uint idx = 1, arrIndex = 35; idx < 15; ++idx, arrIndex += 8) { + if (_data[idx - 1] == id && _data[idx] == 0) + return idx; + } + + return -1; +} + +CPetControl *TTnpcScript::getPetControl(CGameManager *gameManager) { + if (gameManager && gameManager->_project) + return gameManager->_project->getPetControl(); + return nullptr; +} + +int TTnpcScript::processEntries(const TTsentenceEntries *entries, uint entryCount, const TTroomScript *roomScript, const TTsentence *sentence) { + if (!entries) + return SS_1; + if (!entryCount) + // No count specified, so use entire list + entryCount = entries->size(); + int entryId = _field2C; + + for (uint loopCtr = 0; loopCtr < 2; ++loopCtr) { + for (uint entryCtr = 0; entryCtr < entryCount; ++entryCtr) { + const TTsentenceEntry &entry = (*entries)[entryCtr]; + if (entry._field4 != entryId && (loopCtr == 0 || entry._field4)) + continue; + + bool flag; + if (entry._fieldC || entry._string10.empty()) { + flag = sentence->fn1(entry._string8, entry._fieldC, + entry._string14, entry._string18, entry._string1C, + entry._field20, entry._field28, 0, nullptr); + } else { + flag = sentence->fn3(entry._string8, entry._string10, + entry._string14, entry._string18, entry._string1C, + entry._string24, entry._field28, 0, nullptr); + } + + if (flag) { + if (entry._field2C) { + bool flag2 = true; + if (entry._field2C & 0x1000000) + flag2 = sentence->isConcept34(1); + + if (entry._field2C & 0x2000000) + flag2 = sentence->isConcept34(0) || sentence->isConcept34(4); + + if (!flag2) { + flag = false; + } else { + int result = doSentenceEntry(entry._field2C & 0xFFFFFF, &entry._field0, + roomScript, sentence); + if (result == 2) + return 2; + flag = !result; + } + } + + if (flag) { + int dialogueId = getDialogueId(entry._field0); + int id; + if (!dialogueId) + return 1; + else if (dialogueId == 4) + return 2; + addResponse(dialogueId); + + id = preResponse(dialogueId); + if (id) + addResponse(getDialogueId(id)); + applyResponse(); + + if (entry._field30) + postResponse(entry._field30, &entry, roomScript, sentence); + + return 2; + } + } + } + } + + return 1; +} + +bool TTnpcScript::defaultProcess(const TTroomScript *roomScript, const TTsentence *sentence) { + uint remainder; + TTtreeResult results[32]; + const TTstring &line = sentence->_normalizedLine; + + uint tagId = g_vm->_trueTalkManager->_quotes.find(line.c_str()); + int val = g_vm->_trueTalkManager->_quotesTree.search(line.c_str(), TREE_1, results, tagId, &remainder); + + if (val > 0) { + if (!handleQuote(roomScript, sentence, val, tagId, remainder)) + return true; + } + + if (tagId) { + if (chooseResponse(roomScript, sentence, tagId) == 2) + return true; + } + + return false; +} + +void TTnpcScript::addRange(uint id, const Common::Array<uint> &values, bool isRandom, bool isSequential) { + _ranges.push_back(TTscriptRange(id, values, isRandom, isSequential)); +} + +TTscriptRange *TTnpcScript::findRange(uint id) { + for (uint idx = 0; idx < _ranges.size(); ++idx) { + if (_ranges[idx]._id == id) + return &_ranges[idx]; + } + + return nullptr; +} + +void TTnpcScript::checkItems(const TTroomScript *roomScript, const TTsentence *sentence) { + _field2CC = 0; + ++CTrueTalkManager::_v2; + + if (sentence) { + if (!_itemStringP || getRandomNumber(100) > 80) { + for (const char *const *strP = &ITEMS[0]; *strP; ++strP) { + if (sentence->localWord(*strP)) { + _itemStringP = *strP; + break; + } + } + } + + if (sentence->localWord("bomb")) + _field7C = 1; + } +} + +bool TTnpcScript::addRandomResponse(bool flag) { + if (getValue(1) > 3) + return false; + + const uint *data; + if (flag) { + if (getValue(1) == 2) + data = RANDOM8; + else if (getValue(1) == 1) + data = RANDOM7; + else + data = RANDOM9; + } else if (getRandomBit()) { + if (getValue(1) == 2) + data = RANDOM2; + else if (getValue(1) == 1) + data = RANDOM1; + else + data = RANDOM3; + } else { + if (getValue(1) == 2) + data = RANDOM5; + else if (getValue(1) == 1) + data = RANDOM4; + else + data = RANDOM6; + } + + // Pick a random entry + uint count = 0; + while (data[count]) + ++count; + uint id = data[getRandomNumber(count - 1)]; + + if (id == 290188 && getRoom54(101)) + id = 290189; + else if (id == 290202 && getRoom54(123)) + id = 290203; + + if (!id) + return false; + id = getDialogueId(id); + if (id == 4) + return true; + if (!id) + return false; + + if (flag) + addResponse(getDialogueId(290224)); + + addResponse(id); + applyResponse(); + return true; +} + +void TTnpcScript::updateCurrentDial(bool changeDial) { + int dialLevel = CLIP(getDialLevel(_currentDialNum) + _dialDelta, 0, 100); + setDial(_currentDialNum, dialLevel); + + bool edgeFlag = false; + if (_dialDelta < 0) { + if (dialLevel < 10 || getRandomNumber(100) > 93) + edgeFlag = true; + } else { + if (dialLevel > 90 || getRandomNumber(100) > 93) + edgeFlag = true; + } + + if (edgeFlag) { + if (changeDial) + _currentDialNum = getRandomNumber(3); + + _dialDelta = getRandomNumber(12) + 3; + dialLevel = getDialLevel(_currentDialNum, false); + if (dialLevel > 50) + _dialDelta = -_dialDelta; + } +} + +bool TTnpcScript::fn10(bool flag) { + if (_itemStringP) { + for (const ItemRec *ir = ARRAY1; ir->_id; ++ir) { + if (!strcmp(ir->_name, _itemStringP)) { + _itemStringP = nullptr; + uint id = getDialogueId(ir->_id); + if (id == 4) { + return true; + } else if (id != 0) { + addResponse(id); + applyResponse(); + return true; + } + break; + } + } + + _itemStringP = nullptr; + } + + if (flag && getRandomNumber(100) > 60) { + int val = getRandomNumber(18) - 1; + + if (val == 0 && !getRoom54(101) && !getRoom54(132)) + val = -1; + else if ((val == 1 && !_field7C) || val == 2) + val = -1; + + if (val >= 0) { + val = getDialogueId(ARRAY2[val]); + if (val == 4) { + return true; + } else { + addResponse(val); + applyResponse(); + return true; + } + } + } + + return false; +} + +bool TTnpcScript::getStateValue() const { + if (!CTrueTalkManager::_currentNPC) + return false; + + CGameObject *bomb; + if (CTrueTalkManager::_currentNPC->find("Bomb", &bomb, FIND_GLOBAL) && bomb) { + CTrueTalkGetStateValueMsg stateMsg(10, -1000); + stateMsg.execute(bomb); + if (stateMsg._stateVal) + return true; + } + + return false; +} + +bool TTnpcScript::sentence2C(const TTsentence *sentence) { + return sentence->_field2C >= 2 && sentence->_field2C <= 7; +} + +void TTnpcScript::getAssignedRoom(int *roomNum, int *floorNum, int *elevatorNum) const { + if (roomNum) + *roomNum = 5; + if (floorNum) + *floorNum = 40; + if (elevatorNum) + *elevatorNum = 3; + + CGameManager *gameManager = g_vm->_trueTalkManager->getGameManager(); + CPetControl *petControl = getPetControl(gameManager); + if (petControl) { + if (roomNum) + *roomNum = petControl->getAssignedRoomNum(); + if (floorNum) + *floorNum = petControl->getAssignedFloorNum(); + if (elevatorNum) + *elevatorNum = petControl->getAssignedElevatorNum(); + } + + if (floorNum) + *floorNum = CLIP(*floorNum, 1, 42); + if (roomNum) + *roomNum = CLIP(*roomNum, 1, 18); + if (elevatorNum) + *elevatorNum = CLIP(*elevatorNum, 1, 4); +} + +void TTnpcScript::setResponseFromArray(int index, int id) { + if (index >= 0 && index <= 15) { + deleteResponses(); + if (id) + addResponse(getDialogueId(id)); + + // Add any loaded responses + int *vals = _data.getSlot(index + 1); + for (int idx = 0; idx < 4; ++idx) { + if (vals[idx]) + addResponse(vals[idx]); + } + applyResponse(); + + // Clear out the values used + if (index) + Common::fill(vals, vals + 4, 0); + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_npc_script.h b/engines/titanic/true_talk/tt_npc_script.h new file mode 100644 index 0000000000..b9afdfad8a --- /dev/null +++ b/engines/titanic/true_talk/tt_npc_script.h @@ -0,0 +1,355 @@ +/* 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_TT_NPC_SCRIPT_H +#define TITANIC_TT_NPC_SCRIPT_H + +#include "titanic/support/simple_file.h" +#include "titanic/true_talk/tt_script_base.h" +#include "titanic/true_talk/script_support.h" + +namespace Titanic { + +#define DIALS_ARRAY_COUNT 10 + +class CGameManager; +class CPetControl; +class TTroomScript; + +struct TTnpcData { +private: + int _array[136]; +public: + TTnpcData(); + int &operator[](int idx) { return _array[idx]; } + int *getSlot(int idx) { return &_array[16 + idx * 4]; } + void resetFlags(); +}; + +class TTnpcScriptBase : public TTscriptBase { +protected: + int _field54; + int _val2; +public: + int _charId; +public: + TTnpcScriptBase(int charId, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, + int v5, int v6, int v7); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) = 0; + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence) = 0; + + virtual int proc8() const = 0; + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(uint id) = 0; + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id) = 0; + + virtual int proc11() const = 0; + virtual int proc12() const = 0; + + int charId() const { return _charId; } +}; + +class TTnpcScript : public TTnpcScriptBase { +private: + int translateByArray(int id); +protected: + static TTsentenceEntries *_defaultEntries; +protected: + Common::Array<TTnpcScriptResponse> _responses; + int _valuesPerResponse; + Common::Array<TTscriptRange> _ranges; + TTscriptMappings _mappings; + TTsentenceEntries _entries; + TTtagMappings _tagMappings; + TTwordEntries _words; + TThandleQuoteEntries _quotes; + int _entryCount; + int _field68; + int _field6C; + int _rangeResetCtr; + int _currentDialNum; + int _dialDelta; + int _field7C; + const char *_itemStringP; + int _dialValues[DIALS_ARRAY_COUNT]; + TTnpcData _data; + bool _field2CC; +protected: + /** + * Loads response data for the NPC from the given resource + */ + void loadResponses(const char *name, int valuesPerResponse = 1); + + /** + * Load ranges data for the NPC from the given resource + */ + void loadRanges(const char *name); + + /** + * Reset script flags + */ + void resetFlags(); + + /** + * Setup dials + */ + void setupDials(int dial1, int dial2, int dial3); + + static int getRoom54(int roomId); + + /** + * Perform test on various state values + */ + int getValue(int testNum) const; + + /** + * Gets a random number between 1 and a given max + */ + uint getRandomNumber(int max) const; + + /** + * Gets a random number of 0 or 1 + */ + uint getRandomBit() const { + return getRandomNumber(2) - 1; + } + + /** + * Returns a dialogue Id by script tag value Id + */ + uint getDialogueId(uint tagId); + + /** + * Returns a pointer to the PET control + */ + static CPetControl *getPetControl(CGameManager *gameManager); + + /** + * Adds a new item to the list of number ranges + */ + void addRange(uint id, const Common::Array<uint> &values, bool isRandom, bool isSequential); + + /** + * Finds an entry in the list of prevoiusly registered number ranges + */ + TTscriptRange *findRange(uint id); + + /** + * Scans through a list of sentence entries for a matching standardized response + */ + int processEntries(const TTsentenceEntries *entries, uint entryCount, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Scans through a list of sentence entries for a matching standardized response + */ + int processEntries(const TTroomScript *roomScript, const TTsentence *sentence) { + return processEntries(&_entries, _entryCount, roomScript, sentence); + } + + bool defaultProcess(const TTroomScript *roomScript, const TTsentence *sentence); + + void checkItems(const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Adds a random conversation response + */ + bool addRandomResponse(bool flag); + + /** + * Updates the current dial with the given delta + */ + void updateCurrentDial(bool changeDial); + + bool fn10(bool flag); + + static bool sentence2C(const TTsentence *sentence); + + /** + * Gets the True Talk state value + */ + bool getStateValue() const; + + /** + * Gets the assigned room's room, floor, and elevator number + */ + void getAssignedRoom(int *roomNum, int *floorNum, int *elevatorNum) const; + + /** + * Uses a porition of the state _array to set up a new response + */ + void setResponseFromArray(int index, int id); +public: + static void init(); + static void deinit(); +public: + TTnpcScript(int charId, const char *charClass, int v2, + const char *charName, int v3, int val2, int v4, + int v5, int v6, int v7); + + virtual void addResponse(int id); + + /** + * Chooses and adds a conversation response based on a specified tag Id. + * This default implementation does a lookup into a list of known tags, + * and chooses a random dialogue Id from the available ones for that tag + */ + virtual int chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag); + + /** + * Does NPC specific processing of the parsed sentence + */ + virtual int process(const TTroomScript *roomScript, const TTsentence *sentence); + + virtual int proc8() const; + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(uint id) { + return SCR_2; + } + + /** + * Called when the script/id changes + */ + virtual ScriptChangedResult scriptChanged(const TTroomScript *roomScript, uint id) { + return SCR_2; + } + + virtual int proc11() const; + virtual int proc12() const; + + /** + * Translate a passed Id to a dialogue Id if necessary, + * and adds it to the response + */ + virtual void selectResponse(int id); + + /** + * Handles scanning the word list for a given Id, and if + * found adds it to the sentence concept list + */ + virtual bool handleWord(uint id) const; + + virtual int handleQuote(const TTroomScript *roomScript, const TTsentence *sentence, + uint val, uint tagId, uint remainder); + + /** + * Given an Id for a previously registered set of random number values, + * picks one of the array values and returns it.. depending on flags, + * either a random value, or each value in turn + */ + virtual uint getRangeValue(uint id); + + /** + * Resets the prior used index for the specified range + */ + virtual void resetRange(int id); + + /** + * Handles updating NPC state based on specified dialogue Ids and dial positions + */ + virtual int updateState(uint oldId, uint newId, int index); + + /** + * Handles getting a pre-response + */ + virtual int preResponse(uint id); + + /** + * Returns a bitset of the dials being off or not + */ + virtual uint getDialsBitset() const { return 0; } + + virtual const TTscriptMapping *getMapping(int index); + virtual int doSentenceEntry(int val1, const int *srcIdP, const TTroomScript *roomScript, const TTsentence *sentence); + + /** + * Handles any post-response NPC processing + */ + virtual void postResponse(int v1, const TTsentenceEntry *entry, const TTroomScript *roomScript, const TTsentence *sentence) {} + + virtual void save(SimpleFile *file); + virtual void load(SimpleFile *file); + virtual void saveBody(SimpleFile *file); + virtual void loadBody(SimpleFile *file); + virtual int proc31() const; + + /** + * Sets a given dial to be pointing in a specified region (0 to 2) + */ + virtual void setDialRegion(int dialNum, int region); + + /** + * Sets the value for an NPC's dial + */ + virtual void setDial(int dialNum, int value); + + /** + * Returns a dial's region number + */ + virtual int getDialRegion(int dialNum) const; + + /** + * Gets the value for a dial + * @param dialNum Dial number + * @param randomizeFlag If set, introduces a slight random variance so that + * the displayed dial will oscillate randomly around it's real level + */ + virtual int getDialLevel(uint dialNum, bool randomizeFlag = true); + + /** + * Handles a randomzied response + */ + virtual bool randomResponse(uint index); + + virtual uint translateId(uint id) const; + + void preLoad(); + + /** + * Called with the script and id changes + */ + ScriptChangedResult notifyScript(TTroomScript *roomScript, int id) { + return scriptChanged(roomScript, id); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_NPC_SCRIPT_H */ diff --git a/engines/titanic/true_talk/tt_parser.cpp b/engines/titanic/true_talk/tt_parser.cpp new file mode 100644 index 0000000000..1d9c199054 --- /dev/null +++ b/engines/titanic/true_talk/tt_parser.cpp @@ -0,0 +1,1713 @@ +/* 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/true_talk/tt_parser.h" +#include "titanic/true_talk/script_handler.h" +#include "titanic/true_talk/tt_action.h" +#include "titanic/true_talk/tt_concept.h" +#include "titanic/true_talk/tt_picture.h" +#include "titanic/true_talk/tt_sentence.h" +#include "titanic/true_talk/tt_word.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTparser::TTparser(CScriptHandler *owner) : _owner(owner), _sentenceConcept(nullptr), + _sentence(nullptr), _fieldC(0), _field10(0), _field14(0), + _currentWordP(nullptr), _nodesP(nullptr), _conceptP(nullptr) { + loadArrays(); +} + +TTparser::~TTparser() { + if (_nodesP) { + _nodesP->deleteSiblings(); + delete _nodesP; + } + + if (_conceptP) { + _conceptP->deleteSiblings(); + delete _conceptP; + } + + delete _currentWordP; +} + +void TTparser::loadArray(StringArray &arr, const CString &name) { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource(name); + while (r->pos() < r->size()) + arr.push_back(readStringFromStream(r)); + delete r; +} + +void TTparser::loadArrays() { + loadArray(_replacements1, "TEXT/REPLACEMENTS1"); + loadArray(_replacements2, "TEXT/REPLACEMENTS2"); + loadArray(_replacements3, "TEXT/REPLACEMENTS3"); + loadArray(_phrases, "TEXT/PHRASES"); + loadArray(_pronouns, "TEXT/PRONOUNS"); + + Common::SeekableReadStream *r = g_vm->_filesManager->getResource("TEXT/NUMBERS"); + while (r->pos() < r->size()) { + NumberEntry ne; + ne._text = readStringFromStream(r); + ne._value = r->readSint32LE(); + ne._flags = r->readUint32LE(); + _numbers.push_back(ne); + } + delete r; +} + +int TTparser::preprocess(TTsentence *sentence) { + _sentence = sentence; + if (normalize(sentence)) + return 0; + + // Scan for and replace common slang and contractions with verbose versions + searchAndReplace(sentence->_normalizedLine, _replacements1); + searchAndReplace(sentence->_normalizedLine, _replacements2); + + // Check entire normalized line against common phrases to replace + for (uint idx = 0; idx < _phrases.size(); idx += 2) { + if (!_phrases[idx].compareTo(sentence->_normalizedLine)) + sentence->_normalizedLine = _phrases[idx + 1]; + } + + // Do a further search and replace of roman numerals to decimal + searchAndReplace(sentence->_normalizedLine, _replacements3); + + // Replace any roman numerals, spelled out words, etc. with decimal numbers + CTrueTalkManager::_v1 = -1000; + int idx = 0; + do { + idx = replaceNumbers(sentence->_normalizedLine, idx); + } while (idx >= 0); + + if (CTrueTalkManager::_v1 == -1000 && !sentence->_normalizedLine.empty()) { + // Scan the text for any numeric digits + for (const char *strP = sentence->_normalizedLine.c_str(); *strP; ++strP) { + if (Common::isDigit(*strP)) { + // Found digit, so convert it and any following ones + CTrueTalkManager::_v1 = atoi(strP); + break; + } + } + } + + return 0; +} + +int TTparser::normalize(TTsentence *sentence) { + TTstring *destLine = new TTstring(); + const TTstring &srcLine = sentence->_initialLine; + int srcSize = srcLine.size(); + int savedIndex = 0; + int counter1 = 0; + int commandVal; + + for (int index = 0; index < srcSize; ++index) { + char c = srcLine[index]; + if (Common::isLower(c)) { + (*destLine) += c; + } else if (Common::isSpace(c)) { + if (!destLine->empty() && destLine->lastChar() != ' ') + (*destLine) += ' '; + } else if (Common::isUpper(c)) { + (*destLine) += toupper(c); + } else if (Common::isDigit(c)) { + if (c == '0' && isEmoticon(srcLine, index)) { + sentence->set38(10); + } else { + // Iterate through all the digits of the number + (*destLine) += c; + while (Common::isDigit(srcLine[index + 1])) + (*destLine) += srcLine[++index]; + } + } else if (Common::isPunct(c)) { + bool flag = false; + switch (c) { + case '!': + sentence->set38(3); + break; + + case '\'': + if (!normalizeContraction(srcLine, index, *destLine)) + flag = true; + break; + + case '.': + sentence->set38(1); + break; + + case ':': + commandVal = isEmoticon(srcLine, index); + if (commandVal) { + sentence->set38(commandVal); + index += 2; + } else { + flag = true; + } + break; + + case ';': + commandVal = isEmoticon(srcLine, index); + if (commandVal == 6) { + sentence->set38(7); + index += 2; + } else if (commandVal != 0) { + sentence->set38(commandVal); + index += 2; + } + break; + + case '<': + ++index; + commandVal = isEmoticon(srcLine, index); + if (commandVal == 6) { + sentence->set38(12); + } else { + --index; + flag = true; + } + break; + + case '>': + ++index; + commandVal = isEmoticon(srcLine, index); + if (commandVal == 6 || commandVal == 9) { + sentence->set38(11); + } else { + --index; + flag = true; + } + break; + + case '?': + sentence->set38(2); + break; + + default: + flag = true; + break; + } + + if (flag && (!savedIndex || (index - savedIndex) == 1)) + ++counter1; + + savedIndex = index; + } + } + + if (counter1 >= 4) + sentence->set38(4); + + // Remove any trailing spaces + while (destLine->hasSuffix(" ")) + destLine->deleteLastChar(); + + // Copy out the normalized line + sentence->_normalizedLine = *destLine; + delete destLine; + + return 0; +} + +int TTparser::isEmoticon(const TTstring &str, int &index) { + if (str[index] != ':' && str[index] != ';') + return 0; + + if (str[index + 1] != '-') + return 0; + + index += 2; + switch (str[index]) { + case '(': + case '<': + return 8; + + case ')': + case '>': + return 6; + + case 'P': + case 'p': + return 9; + + default: + return 5; + } +} + +bool TTparser::normalizeContraction(const TTstring &srcLine, int srcIndex, TTstring &destLine) { + int startIndex = srcIndex + 1; + switch (srcLine[startIndex]) { + case 'd': + srcIndex += 2; + if (srcLine.compareAt(srcIndex, " a ") || srcLine.compareAt(srcIndex, " the ")) { + destLine += " had"; + } else { + destLine += " would"; + } + + srcIndex = startIndex; + break; + + case 'l': + if (srcLine[srcIndex + 2] == 'l') { + // 'll ending + destLine += " will"; + srcIndex = startIndex; + } + break; + + case 'm': + // 'm ending + destLine += " am"; + srcIndex = startIndex; + break; + + case 'r': + // 're ending + if (srcLine[srcIndex + 2] == 'e') { + destLine += " are"; + srcIndex = startIndex; + } + break; + + case 's': + destLine += "s*"; + srcIndex = startIndex; + break; + + case 't': + if (srcLine[srcIndex - 1] == 'n' && srcIndex >= 3) { + if (srcLine[srcIndex - 3] == 'c' && srcLine[srcIndex - 2] == 'a' && + (srcIndex == 3 || srcLine[srcIndex - 4])) { + // can't -> can not + destLine += 'n'; + } else if (srcLine[srcIndex - 3] == 'w' && srcLine[srcIndex - 2] == 'o' && + (srcIndex == 3 || srcLine[srcIndex - 4])) { + // won't -> will not + destLine.deleteLastChar(); + destLine.deleteLastChar(); + destLine += "ill"; + } else if (srcLine[srcIndex - 3] == 'a' && srcLine[srcIndex - 2] == 'i' && + (srcIndex == 3 || srcLine[srcIndex - 4])) { + // ain't -> am not + destLine.deleteLastChar(); + destLine.deleteLastChar(); + destLine += "m"; + } else if (srcLine.hasSuffix(" sha") || + (srcIndex == 4 && srcLine.hasSuffix("sha"))) { + // shan't -> shall not + destLine.deleteLastChar(); + destLine += "ll"; + } + + destLine += " not"; + } + break; + + case 'v': + // 've ending + if (srcLine[startIndex + 2] == 'e') { + destLine += " have"; + srcIndex = startIndex; + } + break; + + default: + break; + } + + return false; +} + +void TTparser::searchAndReplace(TTstring &line, const StringArray &strings) { + int charIndex = 0; + while (charIndex >= 0) + charIndex = searchAndReplace(line, charIndex, strings); +} + +int TTparser::searchAndReplace(TTstring &line, int startIndex, const StringArray &strings) { + int lineSize = line.size(); + if (startIndex >= lineSize) + return -1; + + for (uint idx = 0; idx < strings.size(); idx += 2) { + const CString &origStr = strings[idx]; + const CString &replacementStr = strings[idx + 1]; + + if (!strncmp(line.c_str() + startIndex, origStr.c_str(), strings[idx].size())) { + // Ensure that that a space follows the match, or the end of string, + // so the end of the string doesn't match on parts of larger words + char c = line[startIndex + strings[idx].size()]; + if (c == ' ' || c == '\0') { + // Replace the text in the line with it's replacement + line = CString(line.c_str(), line.c_str() + startIndex) + replacementStr + + CString(line.c_str() + startIndex + origStr.size()); + + startIndex += replacementStr.size(); + break; + } + } + } + + // Skip to the end of the current word + while (startIndex < lineSize && line[startIndex] != ' ') + ++startIndex; + if (startIndex == lineSize) + return -1; + + // ..and all spaces following it until the start of the next word + while (startIndex < lineSize && line[startIndex] == ' ') + ++startIndex; + if (startIndex == lineSize) + return -1; + + // Return index of the start of the next word + return startIndex; +} + +int TTparser::replaceNumbers(TTstring &line, int startIndex) { + int index = startIndex; + const NumberEntry *numEntry = replaceNumbers2(line, &index); + if (!numEntry || !(numEntry->_flags & NF_2)) + return index; + + bool flag1 = false, flag2 = false, flag3 = false; + int total = 0, factor = 0; + + do { + if (numEntry->_flags & NF_1) { + flag2 = true; + if (numEntry->_flags & NF_8) + flag1 = true; + + if (numEntry->_flags & NF_4) { + flag3 = true; + factor *= numEntry->_value; + } + + if (numEntry->_flags & NF_2) { + if (flag3) { + total += factor; + factor = 0; + } + + factor += numEntry->_value; + } + } + } while (replaceNumbers2(line, &index)); + + if (!flag2) + return index; + + if (index >= 0) { + if (line[index - 1] != ' ') + return index; + } + + total += factor; + CTrueTalkManager::_v1 = total; + if (flag1) + total = -total; + + CString numStr = CString::format("%d", total); + line = CString(line.c_str(), line.c_str() + startIndex) + numStr + + CString(line.c_str() + index); + return index; +} + +const NumberEntry *TTparser::replaceNumbers2(TTstring &line, int *startIndex) { + int lineSize = line.size(); + int index = *startIndex; + if (index < 0 || index >= lineSize) { + *startIndex = -1; + return nullptr; + } + + NumberEntry *numEntry = nullptr; + + for (uint idx = 0; idx < _numbers.size(); ++idx) { + NumberEntry &ne = _numbers[idx]; + if (!strncmp(line.c_str() + index, ne._text.c_str(), ne._text.size())) { + if ((ne._flags & NF_10) || (index + (int)ne._text.size()) >= lineSize || + line[index + ne._text.size()] == ' ') { + *startIndex += ne._text.size(); + numEntry = ≠ + break; + } + } + } + + if (!numEntry || !(numEntry->_flags & NF_10)) { + // Skip to end of current word + while (*startIndex < lineSize && !Common::isSpace(line[*startIndex])) + ++*startIndex; + } + + // Skip over following spaces until start of following word is reached + while (*startIndex < lineSize && Common::isSpace(line[*startIndex])) + ++*startIndex; + + if (*startIndex >= lineSize) + *startIndex = -1; + + return numEntry; +} + +int TTparser::findFrames(TTsentence *sentence) { + _sentenceConcept = &sentence->_sentenceConcept; + _sentence = sentence; + + TTstring *line = sentence->_normalizedLine.copy(); + TTstring wordString; + int status = 0; + for (int ctr = 1; !status; ++ctr) { + // Keep stripping words off the start of the passed input + wordString = line->tokenize(" \n"); + if (wordString.empty()) + break; + + TTword *srcWord = nullptr; + TTword *word = _owner->_vocab->getWord(wordString, &word); + sentence->storeVocabHit(srcWord); + + if (!word && ctr == 1) { + word = new TTword(wordString, WC_UNKNOWN, 0); + } + + for (TTword *currP = word; currP && !status; currP = currP->_nextP) + status = processRequests(currP); + + word->deleteSiblings(); + delete word; + } + + if (!status) { + status = checkForAction(); + } + + delete line; + return status; +} + +int TTparser::loadRequests(TTword *word) { + int status = 0; + + if (word->_tag != MKTAG('Z', 'Z', 'Z', 'T')) + addNode(word->_tag); + + switch (word->_wordClass) { + case WC_UNKNOWN: + break; + + case WC_ACTION: + if (word->_id != 0x70 && word->_id != 0x71) + addNode(1); + addNode(17); + + switch (word->_id) { + case 101: + case 110: + addNode(5); + addNode(4); + break; + + case 102: + addNode(4); + break; + + case 103: + case 111: + addNode(8); + addNode(7); + addNode(5); + addNode(4); + break; + + case 104: + case 107: + addNode(15); + addNode(5); + addNode(4); + break; + + case 106: + addNode(7); + addNode(4); + break; + + case 108: + addNode(5); + addNode(4); + addNode(23); + break; + + case 112: + case 113: + addNode(13); + addNode(5); + break; + + default: + break; + } + + if (_sentenceConcept) { + if (_sentenceConcept->get18() == 0 || _sentenceConcept->get18() == 2) { + TTaction *action = static_cast<TTaction *>(word); + _sentenceConcept->set18(action->getVal()); + } + } + break; + + case WC_THING: + if (word->checkTag() && _sentence->_field58 > 0) + _sentence->_field58--; + addNode(14); + break; + + case WC_ABSTRACT: + switch (word->_id) { + case 300: + addNode(14); + status = 1; + break; + + case 306: + addNode(23); + addNode(4); + break; + + case 307: + case 308: + addNode(23); + break; + + default: + break; + } + + if (status != 1) { + addToConceptList(word); + addNode(14); + } + break; + + case WC_ARTICLE: + addNode(2); + status = 1; + break; + + case WC_CONJUNCTION: + if (_sentence->check2C()) { + _sentenceConcept->_field1C = 1; + _sentenceConcept = _sentenceConcept->addSibling(); + delete this; + } else { + addNode(23); + } + break; + + case WC_PRONOUN: + status = fn2(word); + break; + + case WC_PREPOSITION: + switch (word->_id) { + case 700: + addNode(6); + addNode(5); + break; + case 701: + addNode(11); + break; + case 702: + status = 1; + break; + case 703: + addNode(9); + break; + case 704: + addNode(10); + break; + default: + break; + } + + case WC_ADJECTIVE: + if (word->_id == 304) { + // Nothing + } else if (word->_id == 801) { + addNode(22); + } else { + if (word->proc16()) + _sentence->_field58++; + if (word->proc17()) + _sentence->_field58++; + } + break; + + case WC_ADVERB: + switch (word->_id) { + case 900: + case 901: + case 902: + case 904: + if (_sentence->_field2C == 9) { + _sentenceConcept->_field1C = 1; + _sentenceConcept = _sentenceConcept->addSibling(); + addNode(1); + } + else { + addNode(23); + addNode(13); + addNode(1); + } + break; + + case 905: + case 907: + case 908: + case 909: + addNode(23); + break; + + case 906: + addNode(23); + status = 1; + break; + + case 910: + addNode(4); + addNode(24); + addNode(23); + addNode(14); + status = 1; + break; + + default: + break; + } + + if (word->_id == 906) { + addNode(14); + status = 1; + } + break; + + default: + break; + } + + return status; +} + +int TTparser::considerRequests(TTword *word) { + if (!_nodesP || !word) + return 0; + + TTconcept *concept = nullptr; + int status = 0; + bool flag = false; + bool modifierFlag = false; + int seekVal = 0; + + for (TTparserNode *nodeP = _nodesP; nodeP; ) { + switch (nodeP->_tag) { + case CHECK_COMMAND_FORM: + if (_sentenceConcept->_concept1P && _sentence->_field2C == 1 && + !_sentenceConcept->_concept0P) { + concept = new TTconcept(_sentence->_npcScript, ST_NPC_SCRIPT); + _sentenceConcept->_concept0P = concept; + _sentenceConcept->_field18 = 3; + } + + flag = true; + break; + + case EXPECT_THING: + if (!word->_wordClass) { + word->_wordClass = WC_THING; + addToConceptList(word); + addNode(14); + } + + flag = true; + break; + + case OBJECT_IS_TO: + flag = resetConcept(&_sentenceConcept->_concept2P, 3); + break; + + case SEEK_ACTOR: + case MKTAG('S', 'A', 'C', 'T'): + if (!_sentenceConcept->_concept0P) { + flag = filterConcepts(5, 0); + } else if (_sentenceConcept->_concept0P->compareTo("?") && + _sentenceConcept->_concept1P->isWordId(113) && + word->_wordClass == WC_THING) { + TTconcept *oldConcept = _sentenceConcept->_concept0P; + _sentenceConcept->_concept0P = nullptr; + flag = filterConcepts(5, 2); + if (flag) + delete oldConcept; + } else { + flag = true; + } + break; + + case SEEK_OBJECT: + if (_sentenceConcept->_concept2P && _sentenceConcept->_concept2P->compareTo(word)) { + flag = true; + } else if (!_sentenceConcept->_concept2P) { + if (filterConcepts(5, 2) && _sentenceConcept->_concept2P->checkWordId1()) + addNode(5); + } else if (word->_wordClass == WC_THING && _sentence->fn2(2, TTstring("?"), _sentenceConcept)) { + TTconcept *oldConcept = _sentenceConcept->_concept2P; + flag = filterConcepts(5, 2); + _sentenceConcept->_concept2P->_field20 = oldConcept->get20(); + if (flag) + delete oldConcept; + } else if (!_sentenceConcept->_concept3P && + (!_sentenceConcept->_concept1P || (_sentenceConcept->_concept1P->getWordId() && + _sentenceConcept->_concept1P->getWordId() == 112)) && + _sentenceConcept->_concept2P->checkWordId1() && + (word->_wordClass == WC_THING || word->_wordClass == WC_PRONOUN)) { + _sentenceConcept->changeConcept(0, &_sentenceConcept->_concept2P, 3); + + if (_conceptP && _conceptP->isWordId(word->_id)) { + status = _sentenceConcept->replaceConcept(0, 2, _conceptP); + removeConcept(_conceptP); + } else { + status = _sentenceConcept->createConcept(0, 2, word); + } + + if (!status && !_sentenceConcept->_concept4P && _sentenceConcept->_concept0P) { + TTconcept *oldConcept = _sentenceConcept->_concept2P; + flag = filterConcepts(5, 2); + _sentenceConcept->_concept2P->_field20 = oldConcept->get20(); + if (flag) + delete oldConcept; + } else { + flag = true; + } + } + break; + + case SEEK_OBJECT_OVERRIDE: + if ((word->_wordClass == WC_THING || word->_wordClass == WC_PRONOUN) && + _sentence->fn2(2, TTstring("thePlayer"), _sentenceConcept) && + !_sentenceConcept->_concept3P) { + _sentenceConcept->_concept3P = _sentenceConcept->_concept2P; + _sentenceConcept->_concept2P = nullptr; + + flag = filterConcepts(5, 2); + if (!flag) { + status = _sentenceConcept->createConcept(0, 2, word); + } + } + break; + + case SEEK_TO: + if (!_sentenceConcept->_concept3P) { + if (!filterConcepts(8, 3)) + flag = filterConcepts(3, 3); + } else { + flag = true; + } + break; + + case SEEK_FROM: + if (!_sentenceConcept->_concept4P) { + if (!filterConcepts(8, 4)) + flag = filterConcepts(3, 3); + } else { + flag = true; + } + break; + + case SEEK_TO_OVERRIDE: + if (word->_wordClass == WC_ACTION) { + status = _sentenceConcept->createConcept(0, 1, word); + if (!status) { + seekVal = _sentenceConcept->_field18; + _sentenceConcept->_field18 = 4; + flag = true; + } + } else if (word->_id == 703) { + if (_sentenceConcept->_concept2P) { + delete _sentenceConcept->_concept2P; + _sentenceConcept->_concept2P = nullptr; + } + + if (_sentenceConcept->_concept4P || !_sentenceConcept->_concept0P) { + addNode(7); + } else { + _sentenceConcept->changeConcept(1, &_sentenceConcept->_concept0P, 4); + concept = nullptr; + addNode(7); + } + } else { + flag = true; + } + break; + + case SEEK_FROM_OVERRIDE: + if (_sentenceConcept->_concept4P) { + delete _sentenceConcept->_concept4P; + _sentenceConcept->_concept4P = nullptr; + } + + addNode(8); + flag = true; + break; + + case SEEK_LOCATION: + addNode(5); + _sentenceConcept->createConcept(0, 5, word); + flag = true; + break; + + case SEEK_OWNERSHIP: + if (word->_id == 601) { + if (_conceptP->findByWordClass(WC_THING)) + status = _conceptP->setOwner(word, false); + + flag = true; + } + break; + + case SEEK_STATE: + if (_sentenceConcept->_concept5P) { + if (_sentenceConcept->_concept5P->findByWordId(306) || + _sentenceConcept->_concept5P->findByWordId(904)) { + TTconcept *oldConcept = _sentenceConcept->_concept5P; + _sentenceConcept->_concept5P = nullptr; + flag = filterConcepts(9, 5); + if (flag) + delete oldConcept; + } else { + flag = true; + } + } else { + flag = filterConcepts(9, 5); + if (!flag && word->_wordClass == WC_ADVERB) { + status = _sentenceConcept->createConcept(1, 5, word); + flag = true; + } + } + break; + + case SEEK_MODIFIERS: + if (!modifierFlag) { + bool tempFlag = false; + + switch (word->_wordClass) { + case WC_ACTION: + status = processModifiers(1, word); + break; + case WC_THING: + status = processModifiers(2, word); + break; + case WC_ABSTRACT: + if (word->_id != 300) { + status = processModifiers(3, word); + } else if (!_conceptP->findByWordClass(WC_THING)) { + status = processModifiers(3, word); + } else { + word->_id = atoi(word->_text.c_str()); + } + break; + case WC_PRONOUN: + if (word->_id != 602) + addToConceptList(word); + break; + case WC_ADJECTIVE: { + TTconcept *conceptP = _conceptP->findByWordClass(WC_THING); + if (conceptP) { + conceptP->_string2 += ' '; + conceptP->_string2 += word->getText(); + } else { + status = processModifiers(8, word); + } + break; + } + case WC_ADVERB: + if (word->_id == 906) { + for (TTconcept *currP = _conceptP; currP; currP = currP->_nextP) { + if (_sentence->isFrameSlotClass(1, WC_ACTION) || + _sentence->isFrameSlotClass(1, WC_THING)) + currP->_field34 = 1; + } + } else { + TTconcept *conceptP = _conceptP->findByWordClass(WC_ACTION); + + if (conceptP) { + conceptP->_string2 += ' '; + conceptP->_string2 += word->getText(); + } else { + tempFlag = true; + } + } + break; + default: + addToConceptList(word); + status = 0; + break; + } + + if (tempFlag) + status = _sentenceConcept->createConcept(1, 5, word); + + modifierFlag = true; + flag = true; + } + break; + + case SEEK_NEW_FRAME: + if (word->_wordClass == WC_ACTION && word->_id != 104 && word->_id != 107) { + if (concept && (_sentenceConcept->_concept5P || _sentenceConcept->_concept2P)) { + TTsentenceConcept *oldNode = _sentenceConcept; + oldNode->_field1C = 2; + _sentenceConcept = oldNode->addSibling(); + concept = nullptr; + + _sentenceConcept->_concept1P = oldNode->_concept1P; + _sentenceConcept->_concept5P = oldNode->_concept5P; + _sentenceConcept->_concept2P = oldNode->_concept2P; + + if (seekVal) { + seekVal = 0; + + _sentenceConcept->_field18 = oldNode->_field18; + oldNode->_field18 = seekVal; + } + } + + flag = true; + } + break; + + case SEEK_STATE_OBJECT: + if (!_sentenceConcept->_concept5P) { + addToConceptList(word); + } else if (_sentenceConcept->concept5WordId() == 113 || + _sentenceConcept->concept5WordId() == 112) { + _sentenceConcept->createConcept(1, 2, word); + } else { + addToConceptList(word); + } + + flag = true; + break; + + case SET_ACTION: + if (_sentence->fn4(1, 104, _sentenceConcept) || + _sentence->fn4(1, 107, _sentenceConcept)) { + concept = _sentenceConcept->_concept1P; + _sentenceConcept->_concept1P = nullptr; + addNode(15); + } + + if (_sentence->check2C() && word->_id == 113) + addNode(4); + + if (word->_wordClass == WC_ACTION) + _sentenceConcept->createConcept(0, 1, word); + + flag = true; + break; + + case ACTOR_IS_TO: + _sentenceConcept->changeConcept(1, &_sentenceConcept->_concept0P, 3); + flag = true; + break; + + case ACTOR_IS_FROM: + _sentenceConcept->changeConcept(1, &_sentenceConcept->_concept0P, 4); + break; + + case ACTOR_IS_OBJECT: + flag = resetConcept(&_sentenceConcept->_concept0P, 2); + break; + + case WORD_TYPE_IS_SENTENCE_TYPE: + if (_sentence->_field2C == 1 || _sentence->_field2C == 10) { + for (TTword *wordP = _currentWordP; wordP; wordP = wordP->_nextP) { + if (wordP->_id == 906) { + _sentence->_field2C = 12; + flag = true; + break; + } + } + + TTpicture *newPictP; + TTconcept *newConceptP; + switch (word->_id) { + case 108: + _sentence->_field2C = 8; + break; + case 113: + if (!_sentenceConcept->_concept3P) + _sentence->_field2C = 22; + break; + case 304: + _sentence->_field2C = 25; + break; + case 305: + _sentence->_field2C = 24; + break; + case 306: + _sentence->_field2C = 7; + break; + case 501: + _sentence->_field2C = 9; + break; + case 900: + _sentence->_field2C = 5; + break; + case 901: + _sentence->_field2C = 4; + break; + case 904: + _sentence->_field2C = 6; + break; + case 905: + _sentence->_field2C = 11; + break; + case 906: + _sentence->_field2C = 12; + break; + case 907: + _sentence->_field2C = 13; + break; + case 908: + _sentence->_field2C = 2; + if (!_sentenceConcept->_concept0P) { + newPictP = new TTpicture(TTstring("?"), WC_THING, 0, 0, 0, 0, 0); + newConceptP = new TTconcept(newPictP); + + _sentenceConcept->_concept0P = newConceptP; + delete newPictP; + addNode(4); + } + break; + case 909: + _sentence->_field2C = 3; + newPictP = new TTpicture(TTstring("?"), WC_THING, 0, 0, 0, 0, 0); + newConceptP = new TTconcept(newPictP); + + _sentenceConcept->_concept2P = newConceptP; + delete newPictP; + addNode(4); + break; + + default: + break; + } + } + + flag = true; + break; + + case COMPLEX_VERB: + if (word->_wordClass == WC_ACTION) { + flag = true; + } else if (!_sentenceConcept->_concept1P) { + TTstring wordStr = word->getText(); + if (wordStr == "do" || wordStr == "doing" || wordStr == "does" || wordStr == "done") { + TTaction *verbP = new TTaction(TTstring("do"), WC_ACTION, 112, 0, + _sentenceConcept->get18()); + status = _sentenceConcept->createConcept(1, 1, verbP); + delete verbP; + } + + flag = true; + } + break; + + case MKTAG('C', 'O', 'M', 'E'): + addNode(7); + addNode(5); + addNode(21); + + if (!_sentence->_field2C) + _sentence->_field2C = 15; + break; + + case MKTAG('C', 'U', 'R', 'S'): + case MKTAG('S', 'E', 'X', 'X'): + if (_sentence->_field58 > 1) + _sentence->_field58--; + flag = true; + break; + + case MKTAG('E', 'X', 'I', 'T'): + addNode(8); + addNode(5); + addNode(21); + + if (!_sentence->_field2C) + _sentence->_field2C = 14; + break; + + case MKTAG('F', 'A', 'R', 'R'): + if (_conceptP->findBy20(0)) + _conceptP->_field20 = 2; + break; + + case MKTAG('F', 'U', 'T', 'R'): + _sentenceConcept->_field18 = 3; + break; + + case MKTAG('G', 'O', 'G', 'O'): + addNode(7); + addNode(5); + addNode(21); + + if (_sentence->_field2C == 1) + _sentence->_field2C = 14; + + flag = true; + break; + + case MKTAG('H', 'E', 'L', 'P'): + if (_sentence->_field2C == 1) + _sentence->_field2C = 18; + + flag = true; + break; + + case MKTAG('L', 'O', 'C', 'F'): + status = _sentenceConcept->createConcept(1, 5, word); + if (!status) + _sentenceConcept->_concept5P->_field20 = 2; + + flag = true; + break; + + case MKTAG('L', 'O', 'C', 'N'): + status = _sentenceConcept->createConcept(1, 5, word); + if (!status) + _sentenceConcept->_concept5P->_field20 = 1; + + flag = true; + break; + + case MKTAG('N', 'E', 'A', 'R'): + if (_conceptP->findBy20(0)) { + _conceptP->_field20 = 1; + } else { + TTpicture *newPictP = new TTpicture(TTstring("?"), WC_THING, 0, 0, 0, 0, 0); + status = addToConceptList(newPictP); + _conceptP->_field20 = 1; + if (!status) + delete newPictP; + } + + flag = true; + break; + + case MKTAG('P', 'A', 'S', 'T'): + _sentenceConcept->_field18 = 1; + flag = true; + break; + + case MKTAG('P', 'L', 'E', 'Z'): + if (_sentence->_field58 < 10) + _sentence->_field58++; + break; + + case MKTAG('P', 'R', 'E', 'Z'): + _sentenceConcept->_field18 = 2; + flag = true; + break; + + case MKTAG('S', 'A', 'A', 'O'): + addNode(5); + addNode(4); + flag = true; + break; + + case MKTAG('S', 'S', 'T', 'A'): + addNode(13); + addNode(5); + flag = true; + break; + + case MKTAG('T', 'E', 'A', 'C'): + if (_sentence->_field2C == 1) + _sentence->_field2C = 10; + + flag = true; + break; + + case MKTAG('V', 'O', 'B', 'J'): + status = _sentenceConcept->createConcept(1, 2, word); + flag = true; + break; + + default: + flag = true; + break; + } + + TTparserNode *nextP = static_cast<TTparserNode *>(nodeP->_nextP); + if (flag) + delete nodeP; + nodeP = nextP; + } + + delete concept; + return status; +} + +int TTparser::processRequests(TTword *word) { + int status = loadRequests(word); + switch (status) { + case 0: + status = considerRequests(word); + + // Iterate through the words + while (_currentWordP) { + considerRequests(_currentWordP); + TTword *nextP = _currentWordP->_nextP; + + delete _currentWordP; + _currentWordP = nextP; + } + break; + + case 1: { + TTword *newWord = new TTword(word); + newWord->_nextP = nullptr; + + // Add word to word chain + if (_currentWordP) { + // Add at end of existing chain + for (word = _currentWordP; word->_nextP; word = word->_nextP) + ; + word->_nextP = newWord; + } else { + // First word, so set as head + _currentWordP = newWord; + } + break; + } + + default: + warning("unexpected return from consider requests"); + break; + } + + return status; +} + +int TTparser::addToConceptList(TTword *word) { + TTconcept *concept = new TTconcept(word, ST_UNKNOWN_SCRIPT); + addConcept(concept); + return 0; +} + +void TTparser::addNode(uint tag) { + TTparserNode *newNode = new TTparserNode(tag); + if (_nodesP) + _nodesP->addToHead(newNode); + _nodesP = newNode; +} + +int TTparser::addConcept(TTconcept *concept) { + if (!concept) + return SS_5; + + if (_conceptP) + concept->_nextP = _conceptP; + _conceptP = concept; + + return SS_VALID; +} + +void TTparser::removeConcept(TTconcept *concept) { + // If no concept passed, exit immediately + if (!concept) + return; + + if (_conceptP == concept) { + // Concept specified is the ver ystart of the linked list, so reset head pointer + _conceptP = _conceptP->_nextP; + } else { + // Scan through the linked list, looking for the specific concept + for (TTconcept *currP = _conceptP; currP; currP = currP->_nextP) { + if (currP->_nextP == concept) { + // Found match, so unlink the next link from the chain + currP->_nextP = currP->_nextP->_nextP; + break; + } + } + } + + // FInally, delete the concept + concept->_nextP = nullptr; + delete concept; +} + +void TTparser::removeNode(TTparserNode *node) { + if (!node->_priorP) + // Node is the head of the chain, so reset parser's nodes pointer + _nodesP = static_cast<TTparserNode *>(node->_nextP); + + delete node; +} + +int TTparser::checkForAction() { + int status = SS_VALID; + bool flag = false; + bool actionFlag = false; + + if (_conceptP && _currentWordP) { + // Firstly we need to get the next word to process, and remove it from + // the list pointed to by _currentWordP + TTword *word = _currentWordP; + if (word->_nextP) { + // Chain of words, so we need to find the last word of the chain, + // and set the last-but-one's _nextP to nullptr to detach the last one + TTword *prior = nullptr; + for (word = word->_nextP; word->_nextP; word = word->_nextP) { + prior = word; + } + + if (prior) + prior->_nextP = nullptr; + } else { + // No chain, so singular word can simply be removed + _currentWordP = nullptr; + if (word->_id == 906 && _sentence->_field2C == 1) + _sentence->_field2C = 12; + } + + if (word->_text == "do" || word->_text == "doing" || word->_text == "does" || + word->_text == "done") { + TTstring doStr("do"); + TTaction *action = new TTaction(doStr, WC_ACTION, 112, 0, _sentenceConcept->get18()); + + if (!action->isValid()) { + status = SS_4; + } else { + // Have the new action replace the old word instance + delete word; + word = action; + actionFlag = true; + } + } + + addToConceptList(word); + delete word; + flag = true; + } + + // Handle any remaining words + while (_currentWordP) { + int result = considerRequests(_currentWordP); + if (result > 1) { + status = result; + } else { + // Delete the top of the word chain + TTword *wordP = _currentWordP; + _currentWordP = _currentWordP->_nextP; + delete wordP; + } + } + + if (flag && _conceptP) { + if (actionFlag && (!_sentenceConcept->_concept1P || _sentenceConcept->_concept1P->isWordId(113))) { + _sentenceConcept->replaceConcept(0, 1, _conceptP); + } else if (!_sentenceConcept->_concept5P) { + _sentenceConcept->replaceConcept(1, 5, _conceptP); + } else if (_sentenceConcept->_concept5P->isWordId(904)) { + _sentenceConcept->replaceConcept(0, 5, _conceptP); + } + + removeConcept(_conceptP); + } + + if (_sentence->fn2(3, TTstring("thePlayer"), _sentenceConcept) && !flag) { + if (_sentenceConcept->concept1WordId() == 101) { + _sentence->_field2C = 16; + } else if (_sentence->_field2C != 18 && _sentenceConcept->concept1WordId() == 102) { + if (_sentence->fn2(0, TTstring("targetNpc"), _sentenceConcept)) + _sentence->_field2C = 15; + } + } + + if (_sentence->fn2(2, TTstring("thePlayer"), _sentenceConcept) && + _sentenceConcept->concept1WordId() == 101 && flag) + _sentence->_field2C = 17; + + if (!_sentenceConcept->_concept0P && !_sentenceConcept->_concept1P && + !_sentenceConcept->_concept2P && !_sentenceConcept->_concept5P && !flag) { + if (_conceptP) + filterConcepts(5, 2); + + if (!_sentenceConcept->_concept2P && _sentence->_field2C == 1) + _sentence->_field2C = 0; + } + + if (_sentence->_field58 < 5 && _sentence->_field2C == 1 && !flag) + _sentence->_field2C = 19; + + for (TTconceptNode *nodeP = &_sentence->_sentenceConcept; nodeP; nodeP = nodeP->_nextP) { + if (nodeP->_field18 == 0 && nodeP->_concept1P) { + nodeP->_field18 = _sentence->concept18(nodeP); + } else if (nodeP->_field18 == 4 && !_sentenceConcept->_concept0P) { + if (_sentenceConcept->_concept3P) { + _sentenceConcept->_concept0P = _sentenceConcept->_concept3P; + _sentenceConcept->_concept3P = nullptr; + } else if (_sentenceConcept->_concept2P) { + _sentenceConcept->_concept0P = _sentenceConcept->_concept2P; + _sentenceConcept->_concept2P = nullptr; + } + } + } + + if (_sentence->_field2C == 1 && _sentenceConcept->_concept5P && + _sentenceConcept->_concept2P) { + if (_sentence->fn4(1, 113, nullptr)) { + if (_sentence->fn2(2, TTstring("targetNpc"), nullptr)) { + _sentence->_field2C = 20; + } else if (_sentence->fn2(2, TTstring("thePlayer"), nullptr)) { + _sentence->_field2C = 21; + } else { + _sentence->_field2C = 22; + } + } + } else if (!_sentenceConcept->_concept0P && !_sentenceConcept->_concept1P && + !_sentenceConcept->_concept2P && !_sentenceConcept->_concept5P) { + if (_conceptP) + filterConcepts(5, 2); + + if (!_sentenceConcept->_concept2P && _sentence->_field2C == 1) + _sentence->_field2C = 0; + } + + return status; +} + +int TTparser::fn2(TTword *word) { + switch (word->_id) { + case 600: + addNode(13); + return 0; + + case 601: + addNode(12); + return 1; + + case 602: + case 607: + return checkReferent(static_cast<TTpronoun *>(word)); + + case 608: + return 1; + + default: + return 0; + } +} + +int TTparser::checkReferent(TTpronoun *pronoun) { + TTconcept *concept; + + switch (pronoun->getVal()) { + case 0: + return 0; + + case 1: + concept = new TTconcept(_owner->_script, ST_ROOM_SCRIPT); + break; + + case 2: + concept = new TTconcept(_sentence->_npcScript, ST_NPC_SCRIPT); + break; + + default: + concept = new TTconcept(pronoun, (ScriptType)pronoun->getVal()); + break; + } + + addConcept(concept); + return 0; +} + +void TTparser::conceptChanged(TTconcept *newConcept, TTconcept *oldConcept) { + if (!oldConcept && newConcept != _currentConceptP) + _currentConceptP = nullptr; + else if (oldConcept && oldConcept == _currentConceptP) + _currentConceptP = newConcept; +} + +bool TTparser::checkConcept2(TTconcept *concept, int conceptMode) { + switch (conceptMode) { + case 3: + return concept->checkWordId2(); + + case 5: + return concept->checkWordClass(); + + case 8: + return concept->checkWordId1(); + + case 9: + if (!concept->checkWordId3() && _sentenceConcept->_concept2P) { + if (!_sentenceConcept->_concept2P->checkWordId2() || !concept->checkWordId2()) { + return _sentenceConcept->_concept2P->checkWordClass() && + concept->checkWordClass(); + } + } + break; + + default: + break; + } + + return false; +} + +int TTparser::filterConcepts(int conceptMode, int conceptIndex) { + int result = 0; + + for (TTconcept *currP = _conceptP; currP && !result; currP = currP->_nextP) { + if (checkConcept2(currP, conceptMode)) { + TTconcept **ptrPP = _sentenceConcept->setConcept(conceptIndex, currP); + TTconcept *newConcept = new TTconcept(*currP); + *ptrPP = newConcept; + + if (newConcept->isValid()) { + removeConcept(currP); + (*ptrPP)->_nextP = nullptr; + result = 1; + } else { + result = -2; + } + } + } + + return result; +} + +bool TTparser::resetConcept(TTconcept **conceptPP, int conceptIndex) { + TTconcept **ptrPP = _sentenceConcept->setConcept(conceptIndex, nullptr); + + if (!*ptrPP) + return 0; + + int result = _sentenceConcept->changeConcept(1, conceptPP, conceptIndex); + if (*conceptPP) + _sentenceConcept->setConcept(conceptIndex, *conceptPP); + + return !result; +} + +int TTparser::processModifiers(int modifier, TTword *word) { + TTconcept *newConcept = new TTconcept(word, ST_UNKNOWN_SCRIPT); + + // Cycles through each word + for (TTword *currP = _currentWordP; currP != word; currP = _currentWordP) { + if ((modifier == 2 && currP->_wordClass == WC_ADJECTIVE) || + (modifier == 1 && currP->_wordClass == WC_ADVERB)) { + newConcept->_string2 += ' '; + newConcept->_string2 += _currentWordP->getText(); + } else if (word->_id == 113 && currP->_wordClass == WC_ADJECTIVE) { + addToConceptList(currP); + addNode(13); + } + + if (modifier == 2 || modifier == 3) { + switch (_currentWordP->_id) { + case 94: + _currentConceptP->setOwner(newConcept); + if (_currentWordP) { + _currentWordP->deleteSiblings(); + delete _currentWordP; + _currentWordP = nullptr; + } + + delete newConcept; + newConcept = nullptr; + break; + + case 204: + newConcept->_field34 = 1; + if (_sentence->_field2C == 1) + _sentence->_field2C = 12; + newConcept->_field14 = 1; + break; + + case 300: + newConcept->set1C(atoi(_currentWordP->_text.c_str())); + break; + + case 400: + newConcept->_field14 = 2; + break; + + case 401: + newConcept->_field14 = 1; + break; + + case 601: + newConcept->setOwner(_currentWordP, false); + break; + + case 608: + if (_currentWordP->comparePronounTo(10)) { + newConcept->_field20 = 1; + } else if (_currentWordP->comparePronounTo(11)) { + newConcept->_field20 = 2; + } + + default: + break; + } + } + + if (_currentWordP) { + // Detaches word and deletes it + TTword *wordP = _currentWordP; + _currentWordP = wordP->_nextP; + + wordP->_nextP = nullptr; + delete wordP; + } + } + + if (newConcept) { + newConcept->setFlag(true); + _currentConceptP = newConcept; + addConcept(newConcept); + } + + return 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_parser.h b/engines/titanic/true_talk/tt_parser.h new file mode 100644 index 0000000000..201de7eb0e --- /dev/null +++ b/engines/titanic/true_talk/tt_parser.h @@ -0,0 +1,208 @@ +/* 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_TT_PARSER_H +#define TITANIC_TT_PARSER_H + +#include "titanic/true_talk/tt_node.h" +#include "titanic/true_talk/tt_pronoun.h" +#include "titanic/true_talk/tt_sentence.h" +#include "titanic/true_talk/tt_string.h" + +namespace Titanic { + +enum NumberFlag { NF_1 = 1, NF_2 = 2, NF_4 = 4, NF_8 = 8, NF_10 = 0x10 }; + +enum ParserAction { + NO_ACTION = 0, CHECK_COMMAND_FORM, EXPECT_THING, OBJECT_IS_TO, + SEEK_ACTOR, SEEK_OBJECT, SEEK_OBJECT_OVERRIDE, SEEK_TO, + SEEK_FROM, SEEK_TO_OVERRIDE, SEEK_FROM_OVERRIDE, SEEK_LOCATION, + SEEK_OWNERSHIP, SEEK_STATE, SEEK_MODIFIERS, SEEK_NEW_FRAME, + SEEK_STATE_OBJECT, SET_ACTION, SET_COLOR, ACTOR_IS_TO, + ACTOR_IS_FROM, ACTOR_IS_OBJECT, STATE_IDENTITY, + WORD_TYPE_IS_SENTENCE_TYPE, COMPLEX_VERB +}; + +class CScriptHandler; +class TTconcept; + +struct NumberEntry { + CString _text; + int _value; + int _flags; + + NumberEntry() : _value(0), _flags(0) {} + NumberEntry(const CString &text, int value, int flags) : + _text(text), _value(value), _flags(flags) {} +}; +typedef Common::Array<NumberEntry> NumberArray; + +class TTparserNode : public TTnode { +public: + uint _tag; +public: + TTparserNode() : TTnode(), _tag(0) {} + TTparserNode(uint tag) : TTnode(), _tag(tag) {} +}; + +class TTparser { +private: + StringArray _replacements1; + StringArray _replacements2; + StringArray _replacements3; + StringArray _phrases; + NumberArray _numbers; + TTparserNode *_nodesP; + TTconcept *_conceptP; + TTconcept *_currentConceptP; +private: + /** + * Load the data for a given array resource + */ + void loadArray(StringArray &arr, const CString &name); + + /** + * Loads the various replacement string data arrays + */ + void loadArrays(); + + /** + * Normalizes a passed input, taking care of things like removing extra + * spaces and lowercasing everything + */ + int normalize(TTsentence *sentence); + + /** + * Submethod called by normalize to handle expanding contacted word pairs + * like can't, should've, and so on. + */ + bool normalizeContraction(const TTstring &srcLine, int srcIndex, TTstring &destLine); + + /** + * Checks for what is likely special developer cheat codes + */ + static int isEmoticon(const TTstring &str, int &index); + + /** + * Checks if any word within a passed line has an entry in the list of replacements, + * and if found, replaces it with it's equivalent replacement string + * @param line Line to check + * @param strings List of strings to check for. Strings come in pairs, with the + * first being the string to match, and the second the replacement + */ + static void searchAndReplace(TTstring &line, const StringArray &strings); + + /** + * Checks the string starting at a given index for any word in the passed string array, + * and if found, replaces it in the line with it's replacement + * @param line Line to check + * @param startIndex Starting index in the start to check + * @param strings List of strings to check for. Strings come in pairs, with the + * first being the string to match, and the second the replacement + * @returns Index of the start of the following word + */ + static int searchAndReplace(TTstring &line, int startIndex, const StringArray &strings); + + /** + * Checks the string starting at a given index for a number representation + * such as roman numericals, spelled out numbers, etc. and replaces it with + * a plain decimal representation. + * @param line Line to check + * @param startIndex Starting index in the start to check + * @returns Index of the start of the following word, or -1 if at end of line + */ + int replaceNumbers(TTstring &line, int startIndex); + + /** + * Checks the string starting at a given index for a number representation + * such as roman numericals, spelled out numbers, etc. and replaces it with + * a plain decimal representation. + * @param line Line to check + * @param startIndex Starting index in the start to check + * @returns Pointer to matching number entry, if match occurred + */ + const NumberEntry *replaceNumbers2(TTstring &line, int *startIndex); + + int loadRequests(TTword *word); + int considerRequests(TTword *word); + int processRequests(TTword *word); + + int addToConceptList(TTword *word); + int checkReferent(TTpronoun *pronoun); + + /** + * Creates a new parser node, and adds it to the parser's list + */ + void addNode(uint tag); + + /** + * Add a concept node + */ + int addConcept(TTconcept *concept); + + /** + * Detaches a concept from the main concept list if prseent, then deletes it + */ + void removeConcept(TTconcept *concept); + + /** + * Detaches a node from the main node list + */ + void removeNode(TTparserNode *node); + + int processModifiers(int modifier, TTword *word); + + int checkForAction(); + int fn2(TTword *word); + bool checkConcept2(TTconcept *concept, int conceptMode); + int filterConcepts(int conceptMode, int conceptIndex); + bool resetConcept(TTconcept **conceptPP, int conceptIndex); +public: + CScriptHandler *_owner; + TTsentenceConcept *_sentenceConcept; + TTsentence *_sentence; + int _fieldC; + int _field10; + int _field14; + TTword *_currentWordP; + StringArray _pronouns; +public: + TTparser(CScriptHandler *owner); + ~TTparser(); + + /** + * Preprocesses the passed input text, to handle things like lowercasing + * all the words, and replcaing common slang with their full equivalents + */ + int preprocess(TTsentence *sentence); + + int findFrames(TTsentence *sentence); + + /** + * Called when a concept is copied from one to another + */ + void conceptChanged(TTconcept *newConcept, TTconcept *oldConcept); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_PARSER_H */ diff --git a/engines/titanic/true_talk/tt_picture.cpp b/engines/titanic/true_talk/tt_picture.cpp new file mode 100644 index 0000000000..4b04b8825b --- /dev/null +++ b/engines/titanic/true_talk/tt_picture.cpp @@ -0,0 +1,102 @@ +/* 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/true_talk/tt_picture.h" + +namespace Titanic { + +bool TTpicture::_staticFlag; + +TTpicture::TTpicture(const TTstring &str, WordClass wordClass, int val2, int val3, int val4, int val5, int val6) : + TTmajorWord(str, wordClass, val2, val4), _tag(val3), _field30(val5), _field3C(val6), + _field38(0) { +} + +TTpicture::TTpicture(const TTpicture *src) : TTmajorWord(src) { + if (getStatus()) { + _tag = 0; + _field30 = 0; + _field38 = 0; + _field3C = 0; + _status = SS_5; + } else { + _tag = src->_tag; + _field30 = src->_field30; + _field38 = src->_field38; + _field3C = src->_field3C; + } +} + +int TTpicture::load(SimpleFile *file) { + CString str; + int val1, val2; + + if (!TTword::load(file, WC_THING) && file->scanf("%s %d %d", &str, &val1, &val2)) { + _tag = readNumber(str.c_str()); + _field30 = val1; + _field3C = val2; + return 0; + } else { + return 3; + } +} + +TTword *TTpicture::copy() const { + TTpicture *returnWordP = new TTpicture(this); + returnWordP->_status = _status; + if (!_status) { + _staticFlag = false; + return returnWordP; + } else if (_status == SS_13 && !_staticFlag) { + _staticFlag = true; + delete returnWordP; + return copy(); + } else { + delete returnWordP; + return nullptr; + } +} + +bool TTpicture::checkTag() const { + return _tag == MKTAG('S', 'E', 'X', 'X') || + _tag == MKTAG('E', 'X', 'C', 'R') || + _tag == MKTAG('P', 'P', 'R', 'T') || + _tag == MKTAG('B', 'L', 'A', 'S'); +} + +bool TTpicture::compareTagTo(uint tag) const { + return _tag == tag; +} + +uint TTpicture::getTag() const { + return _tag; +} + +bool TTpicture::proc9(int val) const { + return _field3C == val; +} + +int TTpicture::proc10() const { + return _field3C; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_picture.h b/engines/titanic/true_talk/tt_picture.h new file mode 100644 index 0000000000..18cb88278f --- /dev/null +++ b/engines/titanic/true_talk/tt_picture.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_TT_PICTURE_H +#define TITANIC_TT_PICTURE_H + +#include "titanic/true_talk/tt_major_word.h" + +namespace Titanic { + +class TTpicture : public TTmajorWord { +private: + static bool _staticFlag; +protected: + int _field30; + uint _tag; + int _field38; + int _field3C; +public: + TTpicture(const TTstring &str, WordClass wordClass, int val2, int val3, int val4, int val5, int val6); + TTpicture(const TTpicture *src); + + /** + * Load the word + */ + int load(SimpleFile *file); + + /** + * Creates a copy of the word + */ + virtual TTword *copy() const; + + /** + * Checks whether the word's tag is a known type + */ + virtual bool checkTag() const; + + /** + * Compare the word's tag to a given tag value + */ + virtual bool compareTagTo(uint tag) const; + + /** + * Return the tag associated with the word + */ + virtual uint getTag() const; + + virtual bool proc9(int val) const; + virtual int proc10() const; + +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_PICTURE_H */ diff --git a/engines/titanic/true_talk/tt_pronoun.cpp b/engines/titanic/true_talk/tt_pronoun.cpp new file mode 100644 index 0000000000..3ef48314e6 --- /dev/null +++ b/engines/titanic/true_talk/tt_pronoun.cpp @@ -0,0 +1,73 @@ +/* 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/true_talk/tt_pronoun.h" + +namespace Titanic { + +bool TTpronoun::_staticFlag; + +TTpronoun::TTpronoun(TTstring &str, WordClass wordClass, int val2, int val3, int val4) : + TTmajorWord(str, wordClass, val2, val3), _field30(val4) { +} + +TTpronoun::TTpronoun(const TTpronoun *src) : TTmajorWord(src) { + if (src->getStatus()) { + _field30 = 0; + _status = SS_5; + } else { + _field30 = src->_field30; + } +} + +int TTpronoun::load(SimpleFile *file) { + int val; + + if (!TTword::load(file, WC_PRONOUN) && file->scanf("%d", &val)) { + if (val >= 0 && val <= 12) { + _field30 = val; + return 0; + } else { + return 5; + } + } else { + return 8; + } +} + +TTword *TTpronoun::copy() const { + TTpronoun *returnWordP = new TTpronoun(this); + returnWordP->_status = _status; + if (!_status) { + _staticFlag = false; + return returnWordP; + } else if (_status == SS_13 && !_staticFlag) { + _staticFlag = true; + delete returnWordP; + return copy(); + } else { + delete returnWordP; + return nullptr; + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_pronoun.h b/engines/titanic/true_talk/tt_pronoun.h new file mode 100644 index 0000000000..ccc077152c --- /dev/null +++ b/engines/titanic/true_talk/tt_pronoun.h @@ -0,0 +1,65 @@ +/* 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_TT_PRONOUN_H +#define TITANIC_TT_PRONOUN_H + +#include "titanic/true_talk/tt_major_word.h" + +namespace Titanic { + +class TTpronoun : public TTmajorWord { +private: + static bool _staticFlag; +protected: + int _field30; +public: + TTpronoun(TTstring &str, WordClass wordClass, int val2, int val3, int val4); + TTpronoun(const TTpronoun *src); + + /** + * Load the word + */ + int load(SimpleFile *file); + + int getVal() const { return _field30; } + + /** + * Creates a copy of the word + */ + virtual TTword *copy() const; + + virtual bool comparePronounTo(int val) const { + return _field30 == val; + } + + /** + * Dumps data associated with the word to file + */ + virtual int save(SimpleFile *file) const { + return saveData(file, _field30); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_WORD_H */ diff --git a/engines/titanic/true_talk/tt_quotes.cpp b/engines/titanic/true_talk/tt_quotes.cpp new file mode 100644 index 0000000000..c690ac8780 --- /dev/null +++ b/engines/titanic/true_talk/tt_quotes.cpp @@ -0,0 +1,145 @@ +/* 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/algorithm.h" +#include "titanic/true_talk/tt_quotes.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTquotes::TTquotes() : _loaded(false), _dataP(nullptr), _dataSize(0), + _field544(0) { + Common::fill(&_tags[0], &_tags[256], 0); +} + +TTquotes::~TTquotes() { + delete[] _dataP; +} + +void TTquotes::load() { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource("TEXT/JRQUOTES.TXT"); + size_t size = r->readUint32LE(); + _loaded = true; + + _dataSize = _field544 = size; + _dataP = new char[size + 0x10]; + + for (int idx = 0; idx < 256; ++idx) + _tags[idx] = r->readUint32LE(); + + for (int charIdx = 0; charIdx < 26; ++charIdx) { + TTquotesLetter &letter = _alphabet[charIdx]; + int count = r->readUint32LE(); + + // Load the list of entries for the given letter + letter._entries.resize(count); + for (int idx = 0; idx < count; ++idx) { + letter._entries[idx]._tagIndex = r->readByte(); + letter._entries[idx]._maxSize = r->readByte(); + letter._entries[idx]._strP = _dataP + r->readUint32LE(); + } + } + + // Read in buffer and then decode it + r->read((byte *)_dataP, _dataSize); + for (size_t idx = 0; idx < _dataSize; idx += 4) + WRITE_LE_UINT32((byte *)_dataP + idx, READ_LE_UINT32((const byte *)_dataP + idx) ^ 0xA55A5AA5); + + delete r; +} + +int TTquotes::find(const char *str) const { + if (!str || !*str) + return 0; + + // Find start and end of string + const char *startP = str, *endP = str; + while (*endP) + ++endP; + + do { + int tagId = find(startP, endP); + if (tagId) + return tagId; + + // Move to next following space or end of string + while (*startP && *startP != ' ') + ++startP; + // If it's a space, then move past it to start of next word + while (*startP && *startP == ' ') + ++startP; + + } while (*startP); + + // No match + return 0; +} + +int TTquotes::find(const char *startP, const char *endP) const { + int size = endP - startP; + if (size < 3) + return 0; + + uint index = MIN((uint)(*startP - 'a'), (uint)25); + const TTquotesLetter &letter = _alphabet[index]; + if (letter._entries.empty()) + // No entries for the letter, so exit immediately + return 0; + + int maxSize = size + 4; + + for (uint idx = 0; idx < letter._entries.size(); ++idx) { + const TTquotesEntry &entry = letter._entries[idx]; + if (entry._maxSize > maxSize) + continue; + + const char *srcP = startP; + const char *destP = entry._strP; + int srcIndex = index != 25 ? 1 : 0, destIndex = 0; + if (*destP) { + do { + if (!srcP[srcIndex]) { + break; + } else if (srcP[srcIndex] == '*') { + ++srcIndex; + } else if (destP[destIndex] == '-') { + ++destIndex; + if (srcP[srcIndex] == ' ') + ++srcIndex; + } else if (srcP[srcIndex] != destP[destIndex]) { + break; + } else { + ++destIndex; + ++srcIndex; + } + } while (destP[destIndex]); + + if (!destP[destIndex] && (srcP[srcIndex] <= '*' || + (srcP[srcIndex] == 's' && srcP[srcIndex + 1] <= '*'))) + return _tags[entry._tagIndex]; + } + } + + return 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_quotes.h b/engines/titanic/true_talk/tt_quotes.h new file mode 100644 index 0000000000..5958c9ebcf --- /dev/null +++ b/engines/titanic/true_talk/tt_quotes.h @@ -0,0 +1,77 @@ +/* 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_TT_QUOTES_H +#define TITANIC_TT_QUOTES_H + +#include "common/scummsys.h" +#include "common/stream.h" +#include "titanic/support/string.h" + +namespace Titanic { + +class TTquotes { + struct TTquotesEntry { + byte _tagIndex, _maxSize; + const char *_strP; + TTquotesEntry() : _tagIndex(0), _maxSize(0), _strP(nullptr) {} + }; + struct TTquotesLetter { + Common::Array<TTquotesEntry> _entries; + int _field4; + int _field8; + + TTquotesLetter() : _field4(0), _field8(0) {} + }; +private: + TTquotesLetter _alphabet[26]; + uint _tags[256]; + char *_dataP; + size_t _dataSize; + int _field544; +private: + /** + * Test whether a substring contains one of the quotes, + * and if so, returns the 4-character tag Id associated with it + */ + int find(const char *startP, const char *endP) const; +public: + bool _loaded; +public: + TTquotes(); + ~TTquotes(); + + /** + * Load quotes data resource + */ + void load(); + + /** + * Test whether a passed string contains one of the quotes, + * and if so, returns the 4-character tag Id associated with it + */ + int find(const char *str) const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_QUOTES_H */ diff --git a/engines/titanic/true_talk/tt_quotes_tree.cpp b/engines/titanic/true_talk/tt_quotes_tree.cpp new file mode 100644 index 0000000000..1f073b83f2 --- /dev/null +++ b/engines/titanic/true_talk/tt_quotes_tree.cpp @@ -0,0 +1,214 @@ +/* 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/algorithm.h" +#include "titanic/true_talk/tt_quotes_tree.h" +#include "titanic/titanic.h" + +namespace Titanic { + +/** + * Specifies the starting index for each of the three main trees + */ +static uint TABLE_INDEXES[3] = { 922, 1015, 1018 }; + +void TTquotesTree::load() { + Common::SeekableReadStream *r = g_vm->_filesManager->getResource("TEXT/TREE"); + + for (int idx = 0; idx < QUOTES_TREE_COUNT; ++idx) { + TTquotesTreeEntry &rec = _entries[idx]; + assert(r->pos() < r->size()); + + rec._id = r->readUint32LE(); + if (rec._id == 0) { + // Nothing needed + } else { + byte type = r->readByte(); + if (type == 0) { + // Index to sub-table + rec._subTable = &_entries[0] + r->readUint32LE(); + } else { + // Read in string for entry + char c; + while ((c = r->readByte()) != '\0') + rec._string += c; + } + } + } + + assert(r->pos() == r->size()); + delete r; +} + +int TTquotesTree::search(const char *str, QuoteTreeNum treeNum, + TTtreeResult *buffer, uint tagId, uint *remainder) { + const TTquotesTreeEntry *bTree = &_entries[TABLE_INDEXES[treeNum]]; + if (!search1(&str, bTree, buffer, tagId) || !buffer->_treeItemP) + return -1; + + if (remainder) { + while (*str) { + if (*str >= 'a' && *str != 's') + *remainder += *str; + } + } + + return buffer->_treeItemP->_id & 0xffffff; +} + +bool TTquotesTree::search1(const char **str, const TTquotesTreeEntry *bTree, + TTtreeResult *buffer, uint tagId) { + buffer->_treeItemP = nullptr; + (buffer + 1)->_treeItemP = nullptr; + + const char *strP = *str; + bool flag = false; + + for (uint mode = bTree->_id >> 24; mode != 0; + ++bTree, mode = bTree->_id >> 24) { + + switch (mode) { + case 1: + if (compareWord(str, bTree->_string.c_str())) + flag = true; + break; + + case 2: + compareWord(str, bTree->_string.c_str()); + break; + + case 5: + if (READ_LE_UINT32(bTree->_string.c_str()) == tagId) + flag = true; + break; + + case 7: + if (search1(str, bTree->_subTable, buffer + 1, tagId)) + flag = true; + break; + + case 8: + if (search2(str, bTree->_subTable, buffer + 1, tagId)) + flag = true; + break; + + default: + break; + } + + if (flag) { + buffer->_treeItemP = bTree; + return true; + } + } + + *str = strP; + return false; +} + +bool TTquotesTree::search2(const char **str, const TTquotesTreeEntry *bTree, + TTtreeResult *buffer, uint tagId) { + buffer->_treeItemP = bTree; + (buffer + 1)->_treeItemP = nullptr; + + const char *strP = *str; + bool flag = false; + for (uint mode = bTree->_id >> 24; mode != 0; + ++bTree, mode = bTree->_id >> 24) { + switch (mode) { + case 0: + return true; + + case 1: + if (compareWord(str, bTree->_string.c_str())) + flag = true; + break; + + case 2: + compareWord(str, bTree->_string.c_str()); + break; + + case 5: + if (READ_LE_UINT32(bTree->_string.c_str()) == tagId) + flag = true; + break; + + case 7: + if (search1(str, bTree->_subTable, buffer + 1, tagId)) + flag = true; + break; + + case 8: + if (search2(str, bTree->_subTable, buffer + 1, tagId)) + flag = true; + break; + + default: + break; + } + + if (flag) { + buffer->_treeItemP = nullptr; + *str = strP; + return false; + } + } + + return true; +} + +bool TTquotesTree::compareWord(const char **str, const char *refStr) { + // Skip over any spaces + const char *strP = *str; + while (*strP && *strP == ' ') + ++strP; + *str = strP; + + // Compare against the reference string + while (*strP && *refStr && *refStr != '*') { + if (*refStr == '-') { + if (*strP == ' ') + ++strP; + } else if (*strP == *refStr) { + ++strP; + } else { + return false; + } + } + + if (*refStr && *refStr != '*') + return false; + if (!*refStr && *strP && *strP != ' ') + return false; + + if (*refStr == '*') { + // Skip over to the end of the word + while (*strP && *strP != ' ') + ++strP; + } + + // Pass out the new updated string position + *str = strP; + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_quotes_tree.h b/engines/titanic/true_talk/tt_quotes_tree.h new file mode 100644 index 0000000000..d7ca798ae8 --- /dev/null +++ b/engines/titanic/true_talk/tt_quotes_tree.h @@ -0,0 +1,84 @@ +/* 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_TT_QUOTES_TREE_H +#define TITANIC_TT_QUOTES_TREE_H + +#include "common/scummsys.h" +#include "common/stream.h" +#include "titanic/support/string.h" + +namespace Titanic { + +#define QUOTES_TREE_COUNT 1022 + +enum QuoteTreeNum { TREE_1 = 0, TREE_2 = 1, TREE_3 = 2 }; + +struct TTquotesTreeEntry { + uint _id; + TTquotesTreeEntry *_subTable; + CString _string; + + TTquotesTreeEntry() : _id(0), _subTable(nullptr) {} +}; + +class TTtreeResult { +public: + int _id; + const TTquotesTreeEntry *_treeItemP; +public: + TTtreeResult() : _id(0), _treeItemP(nullptr) {} +}; + +class TTquotesTree { +private: + TTquotesTreeEntry _entries[QUOTES_TREE_COUNT]; +private: + /** + * First inner search method + */ + bool search1(const char **str, const TTquotesTreeEntry *bTree, + TTtreeResult *buffer, uint tagId); + + /** + * Second inner search method + */ + bool search2(const char **str, const TTquotesTreeEntry *bTree, + TTtreeResult *buffer, uint tagId); + + /** + * Compare the current word in the string against a specified word + */ + bool compareWord(const char **str, const char *refStr); +public: + /** + * Load data for the quotes tree + */ + void load(); + + int search(const char *str, QuoteTreeNum treeNum, + TTtreeResult *buffer, uint tagId, uint *remainder); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_QUOTES_TREE_H */ diff --git a/engines/titanic/true_talk/tt_response.cpp b/engines/titanic/true_talk/tt_response.cpp new file mode 100644 index 0000000000..f007f98f97 --- /dev/null +++ b/engines/titanic/true_talk/tt_response.cpp @@ -0,0 +1,71 @@ +/* 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/true_talk/tt_response.h" + +namespace Titanic { + +TTresponse::TTresponse(const TTstring &src) : _field0(0), _text(src), + _dialogueId(0), _nextP(nullptr), _linkP(nullptr) { +} + +TTresponse::TTresponse(int dialogueId, int val2) : _field0(val2), _text(" "), + _dialogueId(dialogueId), _nextP(nullptr), _linkP(nullptr) { +} + +TTresponse::TTresponse(const TTresponse *src) : _field0(src->_field0), + _text(src->_text), _dialogueId(src->_dialogueId), _nextP(src->_nextP), + _linkP(src->_linkP) { +} + +TTresponse::~TTresponse() { + // Iterate through destroying any successive linked response items + TTresponse *nextP; + for (TTresponse *currP = _nextP; currP; currP = nextP) { + // Get the following response and detach it from the current one, + // so that when the current is destroyed, it will only destroy itself + nextP = currP->_nextP; + currP->_nextP = nullptr; + delete currP; + } +} + +TTresponse *TTresponse::copyChain() const { + TTresponse *returnResponseP = new TTresponse(this); + + for (TTresponse *srcP = _nextP, *destP = returnResponseP; + srcP; srcP = srcP->_nextP, destP = destP->_nextP) { + destP->_nextP = new TTresponse(*srcP); + } + + return returnResponseP; +} + +void TTresponse::addLink(TTresponse *item) { + TTresponse *currP = this; + while (currP->_linkP) + currP = currP->_linkP; + + currP->_linkP = item; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_response.h b/engines/titanic/true_talk/tt_response.h new file mode 100644 index 0000000000..d39d18c193 --- /dev/null +++ b/engines/titanic/true_talk/tt_response.h @@ -0,0 +1,66 @@ +/* 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_TT_RESPONSE_H +#define TITANIC_TT_RESPONSE_H + +#include "titanic/true_talk/tt_string.h" +namespace Titanic { + +class TTsentence; + +class TTresponse { +private: + int _field0; + TTstring _text; + int _dialogueId; + TTresponse *_nextP; + TTresponse *_linkP; +public: + TTresponse(const TTstring &src); + TTresponse(int val1, int val2); + TTresponse(const TTresponse *src); + virtual ~TTresponse(); + + /** + * Makes a copy of the chain of responses + */ + TTresponse *copyChain() const; + + TTresponse *getLink() const { return _linkP; } + + void addLink(TTresponse *item); + + /** + * Get the dialogue Id for the response + */ + int getDialogueId() const { return _dialogueId; } + + /** + * Return the next response item, if present + */ + TTresponse *getNext() const { return _nextP; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_RESPONSE_H */ diff --git a/engines/titanic/true_talk/tt_room_script.cpp b/engines/titanic/true_talk/tt_room_script.cpp new file mode 100644 index 0000000000..b8fbca7d39 --- /dev/null +++ b/engines/titanic/true_talk/tt_room_script.cpp @@ -0,0 +1,60 @@ +/* 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/true_talk/tt_room_script.h" + +namespace Titanic { + +TTroomScriptBase::TTroomScriptBase(int scriptId, + const char *charClass, const char *charName, + int v3, int v4, int v5, int v6, int v2, int v7) : _scriptId(scriptId), + TTscriptBase(3, charClass, v2, charName, v3, v4, v5, v6, v7) { +} + +/*------------------------------------------------------------------------*/ + +TTroomScript::TTroomScript(int scriptId) : + TTroomScriptBase(scriptId, "", "", 0, -1, -1, -1, 0, 0) { +} + +bool TTroomScript::proc8() const { + return false; +} + +void TTroomScript::proc9(int v) { + if (v == 1) + _field54 = 1; +} + +ScriptChangedResult TTroomScript::scriptChanged(TTscriptBase *npcScript, int id) { + if (id == 1) + _field54 = 1; + + return SCR_1; +} + +bool TTroomScript::proc11() const { + return true; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_room_script.h b/engines/titanic/true_talk/tt_room_script.h new file mode 100644 index 0000000000..39a50ac30d --- /dev/null +++ b/engines/titanic/true_talk/tt_room_script.h @@ -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. + * + */ + +#ifndef TITANIC_TT_ROOM_SCRIPT_H +#define TITANIC_TT_ROOM_SCRIPT_H + +#include "titanic/true_talk/tt_script_base.h" + +namespace Titanic { + +class TTnpcScript; +class TTsentence; + +class TTroomScriptBase : public TTscriptBase { +public: + uint _scriptId; +public: + TTroomScriptBase(int scriptId, const char *charClass, const char *charName, + int v3, int v4, int v5, int v6, int v2, int v7); + + /** + * Returns true if a response can be made + */ + virtual bool canRespond(TTnpcScript *npcScript, TTsentence *sentence, int val) const = 0; + + /** + * Returns true if further sentence processing is allowed + */ + virtual bool canProcess(TTnpcScript *npcScript, TTsentence *sentence) const = 0; + + virtual bool proc8() const = 0; + virtual void proc9(int v) = 0; + + /** + * Called when the script changes + */ + virtual ScriptChangedResult scriptChanged(TTscriptBase *npcScript, int id) = 0; + + virtual bool proc11() const = 0; +}; + + +class TTroomScript : public TTroomScriptBase { +public: + int _field54; +public: + TTroomScript(int scriptId); + + /** + * Returns true if a response can be made + */ + virtual bool canRespond(TTnpcScript *npcScript, TTsentence *sentence, int val) const { + return true; + } + + /** + * Returns true if further sentence processing is allowed + */ + virtual bool canProcess(TTnpcScript *npcScript, TTsentence *sentence) const { + return true; + } + + virtual bool proc8() const; + + virtual void proc9(int v); + + /** + * Called when the script changes + */ + virtual ScriptChangedResult scriptChanged(TTscriptBase *npcScript, int id); + + virtual bool proc11() const; + + /** + * Called with the new script and id + */ + ScriptChangedResult notifyScript(TTscriptBase *npcScript, int id) { + return scriptChanged(npcScript, id); + } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_ROOM_SCRIPT_H */ diff --git a/engines/titanic/true_talk/tt_script_base.cpp b/engines/titanic/true_talk/tt_script_base.cpp new file mode 100644 index 0000000000..4109134501 --- /dev/null +++ b/engines/titanic/true_talk/tt_script_base.cpp @@ -0,0 +1,156 @@ +/* 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/true_talk/tt_script_base.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTscriptBase::TTscriptBase(int scriptId, const char *charClass, int state, + const char *charName, int v3, int v4, int v5, int v6, int v7) : + _charName(charName), _charClass(charClass), _status(0), + _nodesP(nullptr), _id(0), _hist1P(nullptr), + _field20(0), _field24(0), _field28(0), _field2C(0), + _field30(0), _state(0), _hist2P(nullptr), _field3C(0), + _respHeadP(nullptr), _respTailP(nullptr), _oldResponseP(nullptr) { + if (!isValid()) { + if (!v7 || !getStatus()) { + _id = scriptId; + _field20 = v3; + _field24 = v4; + _field28 = v5; + _field2C = v6; + _field30 = v7; + _state = state; + } else { + _status = 5; + } + } + + if (_status) + reset(); +} + +TTscriptBase::~TTscriptBase() { + deleteResponses(); + delete _oldResponseP; + + delete _hist1P; + delete _hist2P; + + if (_nodesP) { + _nodesP->deleteSiblings(); + delete _nodesP; + } +} + +bool TTscriptBase::isValid() { + bool result = !_charName.isValid() && !_charClass.isValid(); + _status = result ? 0 : 11; + return result; +} + +void TTscriptBase::reset() { + _nodesP = nullptr; + _id = 4; + _hist1P = nullptr; + _field20 = 0; + _field24 = -1; + _field28 = -1; + _field2C = -1; + _field30 = 0; + _state = 0; + _hist2P = nullptr; + _field3C = 0; + _respHeadP = nullptr; + _respTailP = nullptr; + _oldResponseP = nullptr; +} + +int TTscriptBase::scriptPreprocess(TTsentence *sentence) { + delete _hist1P; + _hist1P = new TTscriptHist(sentence); + + return _hist1P ? SS_VALID : SS_7; +} + +void TTscriptBase::addResponse(const TTstring &str) { + appendResponse2(-1, nullptr, str); +} + +void TTscriptBase::addResponse(int id) { + appendResponse(-1, nullptr, id); +} + +void TTscriptBase::applyResponse() { + delete _oldResponseP; + _oldResponseP = nullptr; + + if (_respHeadP) { + g_vm->_scriptHandler->setResponse(this, _respHeadP); + _oldResponseP = _respHeadP->copyChain(); + TTresponse *oldRespP = _respHeadP; + _respHeadP = _respHeadP->getLink(); + _respTailP = nullptr; + + delete oldRespP; + } +} + +void TTscriptBase::deleteResponses() { + while (_respTailP) { + _respHeadP = _respTailP; + _respTailP = _respHeadP->getLink(); + delete _respHeadP; + } +} + +void TTscriptBase::appendResponse(int val1, int *val2, int val3) { + if (!val2 || val1 <= *val2) { + if (_respHeadP) { + _respHeadP = new TTresponse(_respHeadP); + } else { + _respHeadP = new TTresponse(val3, 3); + if (_respTailP) + _respTailP->addLink(_respHeadP); + else + _respTailP = _respHeadP; + } + } +} + +void TTscriptBase::appendResponse(int val1, int *val2, const TTstring &str) { + if (!val2 || val1 <= *val2) { + if (_respHeadP) { + _respHeadP = new TTresponse(str); + } else { + _respHeadP = new TTresponse(str); + if (_respTailP) + _respTailP->addLink(_respHeadP); + else + _respTailP = _respHeadP; + } + } +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_script_base.h b/engines/titanic/true_talk/tt_script_base.h new file mode 100644 index 0000000000..c489dcb0a7 --- /dev/null +++ b/engines/titanic/true_talk/tt_script_base.h @@ -0,0 +1,131 @@ +/* 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_TT_SCRIPT_BASE_H +#define TITANIC_TT_SCRIPT_BASE_H + +#include "titanic/true_talk/tt_string.h" +#include "titanic/true_talk/tt_hist.h" +#include "titanic/true_talk/tt_node.h" +#include "titanic/true_talk/tt_response.h" + +namespace Titanic { + +enum ScriptChangedResult { + SCR_0 = 0, SCR_1 = 1, SCR_2 = 2, SCR_3 = 3, SCR_4 = 4, SCR_5 = 5 +}; + +class TTsentence; + +class TTscriptBase { +private: + void reset(); +protected: + TTnode *_nodesP; + TThist *_hist1P; + TTstring _charName, _charClass; + int _field20; + int _field24; + int _field28; + int _field2C; + int _field30; + int _state; + TThist *_hist2P; + int _field3C; + TTresponse *_respHeadP; + TTresponse *_respTailP; + TTresponse *_oldResponseP; + int _status; +protected: + /** + * Delete any responses set up for the script + */ + void deleteResponses(); + + /** + * Creates and appends a new response to the script + */ + void appendResponse(int val1, int *val2, int val3); + + void appendResponse(int val1, int *val2, const TTstring &str); + + void appendResponse2(int val1, int *val2, const TTstring &str) { + appendResponse(val1, val2, str); + } + + /** + * Set the script state + */ + void setState(int state) { _state = state; } + + /** + * Get the current state + */ + int getState() const { return _state; } +public: + int _id; +public: + TTscriptBase(int scriptId, const char *charClass, int v2, const char *charName, + int v3, int v4, int v5, int v6, int v7); + virtual ~TTscriptBase(); + + virtual void addResponse(const TTstring &str); + + virtual void addResponse(int id); + + /** + * Passes on the list of dialogue Ids stored in the response(s) + * to the title engine for later display in the PET + */ + virtual void applyResponse(); + + /** + * Returns true if the script is in a valid state + */ + bool isValid(); + + /** + * Return the Id of the script + */ + int getId() const { return _id; } + + /** + * Return the status + */ + int getStatus() const { return _status; } + + /** + * Return the script text + */ + const TTstring getText() { return _charClass; } + + /** + * Gets passed a newly created input wrapper during conversation text processing + */ + int scriptPreprocess(TTsentence *sentence); + +}; + + +} // End of namespace Titanic + +#endif /* TITANIC_TT_SCRIPT_BASE_H */ diff --git a/engines/titanic/true_talk/tt_scripts.cpp b/engines/titanic/true_talk/tt_scripts.cpp new file mode 100644 index 0000000000..f8ea65a475 --- /dev/null +++ b/engines/titanic/true_talk/tt_scripts.cpp @@ -0,0 +1,97 @@ +/* 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/true_talk/tt_scripts.h" +#include "titanic/true_talk/title_engine.h" +#include "titanic/true_talk/barbot_script.h" +#include "titanic/true_talk/bellbot_script.h" +#include "titanic/true_talk/deskbot_script.h" +#include "titanic/true_talk/doorbot_script.h" +#include "titanic/true_talk/liftbot_script.h" +#include "titanic/true_talk/maitred_script.h" +#include "titanic/true_talk/parrot_script.h" +#include "titanic/true_talk/succubus_script.h" + +namespace Titanic { + +TTnpcScript *TTnpcScriptList::findById(int charId) const { + for (TTnpcScriptList::const_iterator i = begin(); i != end(); ++i) { + const TTnpcScriptListItem *item = *i; + if (item->_npcScript->_charId == charId) + return item->_npcScript; + } + + return nullptr; +} + +/*------------------------------------------------------------------------*/ + +TTroomScript *TTroomScriptList::findById(uint scriptId) const { + for (TTroomScriptList::const_iterator i = begin(); i != end(); ++i) { + const TTroomScriptListItem *item = *i; + if (item->_item->_scriptId == scriptId) + return item->_item; + } + + return nullptr; +} + +/*------------------------------------------------------------------------*/ + +TTscripts::TTscripts(CTitleEngine *titleEngine) : + _titleEngine(titleEngine), _field24(0), _field28(0) { + // Load room scripts + for (int scriptNum = 100; scriptNum < 133; ++scriptNum) + addScript(new TTroomScript(scriptNum)); + + // Load npc scripts + addScript(new DoorbotScript(104, "Doorbot", 0, "Fentible", 11, 1, -1, -1, -1, 0), 100); + addScript(new BellbotScript(101, "Bellbot", 0, "Krage", 8, 1), 110); + addScript(new LiftbotScript(105, "LiftBot", 0, "Nobby", 11, 1, -1, -1, -1, 0), 103); + addScript(new DeskbotScript(103, "DeskBot", 0, "Marsinta", 11, 2), 110); + addScript(new BarbotScript(100, "Barbot", 0, "Fortillian", 9, 1, -1, -1, -1, 0), 112); + addScript(new ParrotScript(107, "Parrot", 0, "The Parrot", 5, 1, -1, -1, -1, 0), 111); + addScript(new MaitreDScript(112, "MaitreDBot", 0, "Dastrogaaar", 8, 1), 132); + addScript(new SuccUBusScript(111, "Succubus", 0, "Shorbert", 9, 1, -1, -1, -1, 0), 110); +} + +void TTscripts::addScript(TTnpcScript *script, int scriptId) { + // Find the room script this is associated with + TTroomScript *roomScript = getRoomScript(scriptId); + assert(roomScript); + + _npcScripts.push_back(new TTnpcScriptListItem(script, roomScript)); +} + +void TTscripts::addScript(TTroomScript *script) { + _roomScripts.push_back(new TTroomScriptListItem(script)); +} + +TTroomScript *TTscripts::getRoomScript(int scriptId) const { + return _roomScripts.findById(scriptId); +} + +TTnpcScript *TTscripts::getNpcScript(int charId) const { + return _npcScripts.findById(charId); +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_scripts.h b/engines/titanic/true_talk/tt_scripts.h new file mode 100644 index 0000000000..734d86256f --- /dev/null +++ b/engines/titanic/true_talk/tt_scripts.h @@ -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. + * + */ + +#ifndef TITANIC_TT_SCRIPTS_H +#define TITANIC_TT_SCRIPTS_H + +#include "titanic/core/list.h" +#include "titanic/true_talk/tt_npc_script.h" +#include "titanic/true_talk/tt_room_script.h" + +namespace Titanic { + +class CTitleEngine; + +class TTnpcScriptListItem : public ListItem { +public: + TTnpcScript *_npcScript; + TTroomScript *_roomScript; +public: + TTnpcScriptListItem() : _npcScript(nullptr), _roomScript(nullptr) {} + TTnpcScriptListItem(TTnpcScript *script, TTroomScript *roomScript) : + _npcScript(script), _roomScript(roomScript) {} + virtual ~TTnpcScriptListItem() { delete _npcScript; } +}; + +PTR_LIST_ITEM(TTroomScript); + +class TTnpcScriptList : public List<TTnpcScriptListItem> { +public: + TTnpcScript *findById(int charId) const; +}; + +class TTroomScriptList : public List<TTroomScriptListItem> { +public: + TTroomScript *findById(uint scriptId) const; +}; + +class TTscripts { +private: + TTnpcScriptList _npcScripts; + TTroomScriptList _roomScripts; + CTitleEngine *_titleEngine; + int _field24; + int _field28; +private: + /** + * Add a named script to the named scripts list + */ + void addScript(TTnpcScript *script, int charId); + + /** + * Add an unnamed script to the unnamed scripts list + */ + void addScript(TTroomScript *script); +public: + TTscripts(CTitleEngine *titleEngine); + + /** + * Return a pointer to the specified room script + */ + TTroomScript *getRoomScript(int scriptId) const; + + /** + * Return a pointer to the specified character script + */ + TTnpcScript *getNpcScript(int charId) const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_CHARACTERS_H */ diff --git a/engines/titanic/true_talk/tt_sentence.cpp b/engines/titanic/true_talk/tt_sentence.cpp new file mode 100644 index 0000000000..9588ee021e --- /dev/null +++ b/engines/titanic/true_talk/tt_sentence.cpp @@ -0,0 +1,347 @@ +/* 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/true_talk/tt_sentence.h" +#include "titanic/true_talk/tt_concept.h" +#include "titanic/true_talk/script_handler.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTsentenceConcept *TTsentenceConcept::addSibling() { + if (this == nullptr || _nextP != nullptr) + // This should never happen + return nullptr; + + TTsentenceConcept *nextP = new TTsentenceConcept(); + _nextP = nextP; + return nextP; +} + +/*------------------------------------------------------------------------*/ + +TTsentence::TTsentence(int inputCtr, const TTstring &line, CScriptHandler *owner, + TTroomScript *roomScript, TTnpcScript *npcScript) : + _owner(owner), _field2C(1), _inputCtr(inputCtr), _field34(0), + _field38(0), _initialLine(line), _nodesP(nullptr), _roomScript(roomScript), + _npcScript(npcScript), _field58(0), _field5C(0) { + _status = _initialLine.isValid() && _normalizedLine.isValid() ? SS_11: SS_VALID; +} + +TTsentence::TTsentence(const TTsentence *src) : _sentenceConcept(src->_sentenceConcept), + _initialLine(src->_initialLine), _normalizedLine(src->_normalizedLine) { + copyFrom(*src); +} + +TTsentence::~TTsentence() { + _sentenceConcept.deleteSiblings(); + + if (_nodesP) { + _nodesP->deleteSiblings(); + delete _nodesP; + } +} + +void TTsentence::copyFrom(const TTsentence &src) { + if (!src.getStatus()) + _status = SS_5; + else if (!src._initialLine.isValid() || !src._normalizedLine.isValid()) + _status = SS_11; + else + _status = SS_VALID; + + _inputCtr = src._inputCtr; + _owner = src._owner; + _roomScript = src._roomScript; + _npcScript = src._npcScript; + _field58 = src._field58; + _field5C = src._field5C; + _field34 = src._field34; + _field38 = src._field38; + _field2C = src._field2C; + _nodesP = nullptr; + + if (src._nodesP) { + // Source has processed nodes, so duplicate them + for (TTsentenceNode *node = src._nodesP; node; + node = static_cast<TTsentenceNode *>(node->_nextP)) { + TTsentenceNode *newNode = new TTsentenceNode(node->_wordP); + if (_nodesP) + _nodesP->addToTail(newNode); + else + _nodesP = newNode; + } + } +} + +int TTsentence::storeVocabHit(TTword *word) { + if (!word) + return 0; + + TTsentenceNode *node = new TTsentenceNode(word); + if (_nodesP) { + _nodesP->addToTail(node); + } else { + _nodesP = node; + } + + return 0; +} + +bool TTsentence::fn1(const CString &str, int wordId1, const CString &str1, const CString &str2, + const CString &str3, int wordId2, int val1, int val2, const TTconceptNode *node) const { + if (node) + node = &_sentenceConcept; + + if (!node && !node) + return false; + if (val1 && !is18(val1, node)) + return false; + if (!str.empty() && !fn2(0, str, node)) + return false; + if (wordId1 && !fn4(1, wordId1, node)) + return false; + if (!str1.empty() && !fn2(2, str1, node)) + return false; + if (!str2.empty() && !fn2(3, str2, node)) + return false; + if (!str3.empty() && !fn2(4, str3, node)) + return false; + if (wordId2 && !fn4(5, wordId2, node)) + return false; + if (val2 && !is1C(val2, node)) + return false; + + return true; +} + +bool TTsentence::fn3(const CString &str1, const CString &str2, const CString &str3, + const CString &str4, const CString &str5, const CString &str6, + int val1, int val2, const TTconceptNode *node) const { + if (!node) + node = &_sentenceConcept; + + if (val1 && !is18(val1, node)) + return false; + if (!str1.empty() && !fn2(0, str1, node)) + return false; + if (!str2.empty() && !fn2(1, str2, node)) + return false; + if (!str3.empty() && !fn2(2, str3, node)) + return false; + if (!str4.empty() && !fn2(3, str4, node)) + return false; + if (!str5.empty() && !fn2(4, str5, node)) + return false; + if (!str6.empty() && !fn2(5, str6, node)) + return false; + if (!val2 && !is1C(val2, node)) + return false; + + return true; +} + +bool TTsentence::fn2(int slotIndex, const TTstring &str, const TTconceptNode *node) const { + if (!node) + node = &_sentenceConcept; + TTconcept *concept = getFrameSlot(slotIndex, node); + + if (!concept) + return str == "isEmpty"; + + bool abortFlag = false; + switch (concept->_scriptType) { + case 1: + if (str == "thePlayer") + abortFlag = 1; + break; + + case 2: + if (str == "targetNpc") + abortFlag = 1; + break; + + case 3: + if (str == "otherNpc") + abortFlag = 1; + break; + + default: + break; + } + + TTstring conceptText = concept->getText(); + if (abortFlag || str == conceptText || concept->compareTo(str)) { + delete concept; + return true; + } + + if (slotIndex == 1 && g_vm->_exeResources._owner->_concept4P) { + if (str == g_vm->_exeResources._owner->_concept4P->getText() && + conceptText == "do") + goto exit; + } + + if (g_vm->_exeResources._owner->_concept2P && (slotIndex == 0 || + slotIndex == 3 || slotIndex == 4)) { + if (str == g_vm->_exeResources._owner->_concept2P->getText() && + (conceptText == "it" || conceptText == "he" || conceptText == "she" || + conceptText == "him" || conceptText == "her" || conceptText == "them" || + conceptText == "they")) + goto exit; + } + + if (g_vm->_exeResources._owner->_concept1P && (slotIndex == 0 || + slotIndex == 2 || slotIndex == 3 || slotIndex == 4 || slotIndex == 5)) { + if (str == g_vm->_exeResources._owner->_concept2P->getText() && + (conceptText == "it" || conceptText == "that" || conceptText == "he" || + conceptText == "she" || conceptText == "him" || conceptText == "her" || + conceptText == "them" || conceptText == "they" || conceptText == "those" || + conceptText == "1" || conceptText == "thing")) + goto exit; + } + + if (g_vm->_exeResources._owner->_concept1P && (slotIndex == 0 || slotIndex == 2)) { + if (conceptText == "?" && str == g_vm->_exeResources._owner->_concept2P->getText()) { + delete concept; + concept = getFrameSlot(5, node); + conceptText = concept->getText(); + + if (conceptText == "it" || conceptText == "that" || conceptText == "he" || + conceptText == "she" || conceptText == "him" || conceptText == "her" || + conceptText == "them" || conceptText == "they" || conceptText == "those" || + conceptText == "1" || conceptText == "thing") + abortFlag = true; + } + } + +exit: + delete concept; + return abortFlag; +} + +bool TTsentence::fn4(int mode, int wordId, const TTconceptNode *node) const { + if (!node) + node = &_sentenceConcept; + + switch (mode) { + case 1: + return node->_concept1P && node->_concept1P->getWordId() == wordId; + + case 5: + return node->_concept5P && node->_concept5P->getWordId() == wordId; + + default: + return false; + } +} + +TTconcept *TTsentence::getFrameEntry(int slotIndex, const TTconceptNode *conceptNode) const { + if (!conceptNode) + conceptNode = &_sentenceConcept; + + return conceptNode->_concepts[slotIndex]; +} + +TTconcept *TTsentence::getFrameSlot(int slotIndex, const TTconceptNode *conceptNode) const { + TTconcept *newConcept = new TTconcept(); + TTconcept *concept = getFrameEntry(slotIndex, conceptNode); + newConcept->copyFrom(concept); + + if (!newConcept->isValid()) { + delete newConcept; + newConcept = nullptr; + } + + return newConcept; +} + +bool TTsentence::isFrameSlotClass(int slotIndex, WordClass wordClass, const TTconceptNode *conceptNode) const { + TTconcept *concept = getFrameEntry(slotIndex, conceptNode); + if (concept && concept->_wordP) { + return concept->_wordP->isClass(wordClass); + } else { + return false; + } +} + +int TTsentence::is18(int val, const TTconceptNode *node) const { + if (!node) + node = &_sentenceConcept; + return node->_field18 == val; +} + +int TTsentence::is1C(int val, const TTconceptNode *node) const { + if (!node) + node = &_sentenceConcept; + return node->_field1C == val; +} + +bool TTsentence::isConcept34(int slotIndex, const TTconceptNode *node) const { + TTconcept *concept = getFrameEntry(slotIndex, node); + return concept && concept->getState(); +} + +bool TTsentence::localWord(const char *str) const { + CScriptHandler &scriptHandler = *g_vm->_exeResources._owner; + bool foundMatch = false; + + if (scriptHandler._concept1P) { + TTstring s = scriptHandler._concept1P->getText(); + if (s == str) + foundMatch = true; + } else if (scriptHandler._concept2P) { + TTstring s = scriptHandler._concept2P->getText(); + if (s == str) + foundMatch = true; + } + + int val = g_vm->_exeResources.get18(); + bool result = false; + + for (TTsentenceNode *nodeP = _nodesP; nodeP && !result; + nodeP = static_cast<TTsentenceNode *>(nodeP->_nextP)) { + TTsynonym syn; + if (!nodeP->_wordP) + continue; + + const TTstring wordStr = nodeP->_wordP->_text; + if (val == 3 && wordStr == str) { + result = true; + } else if (nodeP->_wordP->findSynByName(str, &syn, val)) { + result = true; + } else if (foundMatch) { + result = wordStr == "it" || wordStr == "that" || wordStr == "he" + || wordStr == "she" || wordStr == "him" || wordStr == "her" + || wordStr == "them" || wordStr == "they" || wordStr == "those" + || wordStr == "1" || wordStr == "thing"; + } + } + + return result; +} + +bool TTsentence::contains(const char *str) const { + return _initialLine.contains(str) || _normalizedLine.contains(str); +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_sentence.h b/engines/titanic/true_talk/tt_sentence.h new file mode 100644 index 0000000000..7b2c6400c5 --- /dev/null +++ b/engines/titanic/true_talk/tt_sentence.h @@ -0,0 +1,132 @@ +/* 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_TT_SENTENCE_H +#define TITANIC_TT_SENTENCE_H + +#include "common/array.h" +#include "titanic/true_talk/tt_concept_node.h" +#include "titanic/true_talk/tt_npc_script.h" +#include "titanic/true_talk/tt_room_script.h" +#include "titanic/true_talk/tt_sentence_node.h" +#include "titanic/true_talk/tt_string.h" + +namespace Titanic { + +class CScriptHandler; +class TTword; + +class TTsentenceConcept : public TTconceptNode { +public: + TTsentenceConcept() : TTconceptNode() {} + TTsentenceConcept(const TTsentenceConcept &src) : TTconceptNode(src) {} + + /** + * Adds a new sibling instance + */ + TTsentenceConcept *addSibling(); +}; + +class TTsentence { +private: + CScriptHandler *_owner; + int _inputCtr; + int _field34; + TTsentenceNode *_nodesP; + int _field5C; + int _status; +private: + /** + * Copy sentence data from a given source + */ + void copyFrom(const TTsentence &src); +public: + TTsentenceConcept _sentenceConcept; + TTstring _initialLine; + TTstring _normalizedLine; + int _field38; + int _field58; + TTroomScript *_roomScript; + TTnpcScript *_npcScript; + int _field2C; +public: + TTsentence(int inputCtr, const TTstring &line, CScriptHandler *owner, + TTroomScript *roomScript, TTnpcScript *npcScript); + TTsentence(const TTsentence *src); + ~TTsentence(); + + void setState(int v) { _field34 = v; } + void set38(int v) { _field38 = v; } + bool check2C() const { return _field2C > 1 && _field2C <= 10; } + int concept18(TTconceptNode *conceptNode) { + return conceptNode ? conceptNode->get18() : 0; + } + int get58() const { return _field58; } + int is18(int val, const TTconceptNode *node) const; + int is1C(int val, const TTconceptNode *node) const; + + int getStatus() const { return _status; } + + /** + * Gets a concept slot + */ + TTconcept *getFrameEntry(int slotIndex, const TTconceptNode *conceptNode = nullptr) const; + + /** + * Gets a conecpt slot and returns a duplicate of it + */ + TTconcept *getFrameSlot(int slotIndex, const TTconceptNode *conceptNode = nullptr) const; + + /** + * Returns true if the specified slot has an attached word with a given class + */ + bool isFrameSlotClass(int slotIndex, WordClass wordClass, const TTconceptNode *conceptNode = nullptr) const; + + /** + * Adds a found vocab word to the list of words representing + * the player's input + * @param word Word to node + */ + int storeVocabHit(TTword *word); + + bool fn1(const CString &str, int wordId1, const CString &str1, const CString &str2, + const CString &str3, int wordId2, int val1, int val2, const TTconceptNode *node) const; + bool fn3(const CString &str1, const CString &str2, const CString &str3, + const CString &str4, const CString &str5, const CString &str6, + int val1, int val2, const TTconceptNode *node) const; + bool fn2(int slotIndex, const TTstring &str, const TTconceptNode *node = nullptr) const; + bool fn4(int mode, int wordId, const TTconceptNode *node = nullptr) const; + + bool isConcept34(int slotIndex, const TTconceptNode *node = nullptr) const; + + bool localWord(const char *str) const; + + /** + * Returns true if the sentence (either the original or normalized lines) + * contain the specified substring + */ + bool contains(const char *str) const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_SENTENCE_H */ diff --git a/engines/titanic/true_talk/tt_sentence_node.cpp b/engines/titanic/true_talk/tt_sentence_node.cpp new file mode 100644 index 0000000000..33d7501c55 --- /dev/null +++ b/engines/titanic/true_talk/tt_sentence_node.cpp @@ -0,0 +1,34 @@ +/* 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/true_talk/tt_sentence_node.h" + +namespace Titanic { + +TTsentenceNode::TTsentenceNode() : TTnode(), _wordP(nullptr) { +} + +TTsentenceNode::TTsentenceNode(TTword *word) : TTnode(), _wordP(word) { +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_sentence_node.h b/engines/titanic/true_talk/tt_sentence_node.h new file mode 100644 index 0000000000..18fa56fd57 --- /dev/null +++ b/engines/titanic/true_talk/tt_sentence_node.h @@ -0,0 +1,41 @@ +/* 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_TT_SENTENCE_NODE_H +#define TITANIC_TT_SENTENCE_NODE_H + +#include "titanic/true_talk/tt_node.h" +#include "titanic/true_talk/tt_word.h" + +namespace Titanic { + +class TTsentenceNode : public TTnode { +public: + TTword *_wordP; +public: + TTsentenceNode(); + TTsentenceNode(TTword *word); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_SENTENCE_NODE_H */ diff --git a/engines/titanic/true_talk/tt_string.cpp b/engines/titanic/true_talk/tt_string.cpp new file mode 100644 index 0000000000..198a8c2e80 --- /dev/null +++ b/engines/titanic/true_talk/tt_string.cpp @@ -0,0 +1,164 @@ +/* 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/true_talk/tt_string.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +TTstring::TTstring() : _status(SS_VALID) { + _data = new TTstringData(); +} + +TTstring::TTstring(const char *str) : _status(SS_VALID) { + _data = new TTstringData(str); +} + +TTstring::TTstring(const CString &str) { + _status = SS_VALID; + _data = new TTstringData(str); +} + +TTstring::TTstring(const TTstring &str) { + if (str._status != SS_VALID) { + _status = SS_5; + _data = nullptr; + } else { + _status = SS_VALID; + _data = str._data; + _data->_referenceCount++; + } +} + +TTstring::~TTstring() { + if (_data && --_data->_referenceCount == 0) + delete _data; +} + +void TTstring::operator=(const TTstring &str) { + // Delete old string reference, if any + if (_data && --_data->_referenceCount == 0) + delete _data; + + // Copy source string data + _status = str._status; + _data = str._data; + if (_data) + _data->_referenceCount++; +} + +void TTstring::operator=(const CString &str) { + operator=(str.c_str()); +} + +void TTstring::operator=(const char *str) { + // Delete old string reference, if any + if (_data && --_data->_referenceCount == 0) + delete _data; + + // Create new string data + _data = new TTstringData(str); + _status = SS_VALID; +} + +TTstring &TTstring::operator+=(const char *str) { + _data->_string += str; + return *this; +} + +TTstring &TTstring::operator+=(const TTstring &str) { + _data->_string += str; + return *this; +} + +TTstring &TTstring::operator+=(char c) { + _data->_string += c; + return *this; +} + +bool TTstring::operator==(const TTstring &str) const { + return _data && str._data && _data->_string == str._data->_string; +} + +bool TTstring::operator==(const char *str) const { + return _data && _data->_string == str; +} + +void TTstring::save(SimpleFile *file) const { + file->writeFormat("%s", c_str()); +} + +TTstring TTstring::tokenize(const char *delim) { + const char *strP = _data->_string.c_str(); + const char *splitP = nullptr, *chP; + + for (const char *d = delim; d; ++d) { + chP = strchr(strP, *d); + if (chP && (splitP == nullptr || chP < splitP)) + splitP = chP; + } + + if (splitP) { + TTstring result(CString(strP, splitP)); + _data->_string = CString(splitP + 1); + return result; + } else { + return TTstring(); + } +} + +int TTstring::deletePrefix(int count) { + int strSize = size(); + if (count > strSize) + count = strSize; + + if (_data->_referenceCount == 1) { + // No other references to this string, so we can just directly modify it + _data->_string = CString(_data->_string.c_str() + count); + } else { + // Detach string from current shared data, and create a new one with the substring + _data->_referenceCount--; + _data = new TTstringData(_data->_string.c_str() + count); + } + + return 1; +} + +int TTstring::deleteSuffix(int count) { + int strSize = size(); + if (count > strSize) + count = strSize; + + CString newStr(_data->_string.c_str(), _data->_string.c_str() + strSize - count); + if (_data->_referenceCount == 1) { + // No other references to this string, so we can just directly modify it + _data->_string = newStr; + } else { + // Detach string from current shared data, and create a new one with the substring + _data->_referenceCount--; + _data = new TTstringData(newStr); + } + + return 1; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_string.h b/engines/titanic/true_talk/tt_string.h new file mode 100644 index 0000000000..5b12d93418 --- /dev/null +++ b/engines/titanic/true_talk/tt_string.h @@ -0,0 +1,173 @@ +/* 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_TT_STRING_H +#define TITANIC_TT_STRING_H + +#include "titanic/support/string.h" + +namespace Titanic { + +class SimpleFile; + +struct TTstringData { + CString _string; + int _referenceCount; + + TTstringData() : _referenceCount(1) {} + TTstringData(const char *str) : _string(str), _referenceCount(1) {} + TTstringData(const CString &str) : _string(str), _referenceCount(1) {} +}; + +enum TTstringStatus { + SS_VALID = 0, SS_1 = 1, SS_2 = 2, SS_3 = 3, SS_4 = 4, + SS_5 = 5, SS_7 = 7, SS_8 = 8, SS_11 = 11, SS_13 = 13 +}; + +class TTstring { +private: + TTstringData *_data; + TTstringStatus _status; +public: + TTstring(); + TTstring(const char *str); + TTstring(const CString &str); + TTstring(const TTstring &str); + virtual ~TTstring(); + + void operator=(const TTstring &str); + void operator=(const CString &str); + void operator=(const char *str); + TTstring &operator+=(const char *str); + TTstring &operator+=(const TTstring &str); + TTstring &operator+=(char c); + bool operator==(const TTstring &str) const; + bool operator==(const char *str) const; + + const char &operator[](int index) { + return *(c_str() + index); + } + + bool empty() const { + return _data->_string.empty(); + } + + char firstChar() const { + return _data->_string.firstChar(); + } + + char lastChar() const { + return _data->_string.lastChar(); + } + + int size() const { + return _data->_string.size(); + } + + void deleteLastChar() { + _data->_string.deleteLastChar(); + } + + bool hasPrefix(const CString &str) const { + return _data->_string.hasPrefix(str); + } + bool hasPrefix(const char *str) const { + return _data->_string.hasPrefix(str); + } + bool hasSuffix(const CString &str) const { + return _data->_string.hasSuffix(str); + } + bool hasSuffix(const char *str) const { + return _data->_string.hasSuffix(str); + } + + bool contains(const char *s) const { + return _data->_string.contains(s); + } + + /** + * Create a new copy of the string + */ + TTstring *copy() const { + return new TTstring(c_str()); + } + + /** + * Returns true if the string is valid + */ + bool isValid() const { + return _status == SS_VALID; + } + + /** + * Get the status of the string + */ + TTstringStatus getStatus() const { return _status; } + + /** + * Get a char * pointer to the string data + */ + const char *c_str() const { return _data->_string.c_str(); } + + /** + * Automatic operator to convert to a const char * + */ + operator const char *() const { return c_str(); } + + /** + * Get a character at a specified index + */ + char charAt(int index) const { return *(c_str() + index); } + + /** + * Save the sring to a passed file + */ + void save(SimpleFile *file) const; + + /** + * Compare a substring within the string at the specified index + */ + bool compareAt(int index, const char *str) const { + return !strncmp(c_str() + index, str, strlen(str)); + } + + /** + * Split off everything in the string until the first occurance + * of any specified delimiter character + */ + TTstring tokenize(const char *delim); + + /** + * Delets a specififed number of characters from the start of the string + */ + int deletePrefix(int count); + + /** + * Delets a specififed number of characters from the end of the string + */ + int deleteSuffix(int count); + +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_STRING_H */ diff --git a/engines/titanic/true_talk/tt_string_node.cpp b/engines/titanic/true_talk/tt_string_node.cpp new file mode 100644 index 0000000000..2bb0c5a74b --- /dev/null +++ b/engines/titanic/true_talk/tt_string_node.cpp @@ -0,0 +1,68 @@ +/* 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/true_talk/tt_string_node.h" + +namespace Titanic { + +TTstringNode::TTstringNode() : TTnode() { +} + +void TTstringNode::initialize(int mode) { + _mode = mode; + _file = HANDLE_STDIN; + + if (_string.isValid()) { + _field1C = 0; + } else { + _field1C = 11; + warning("TTstringNode::initialize has bad subobj"); + } +} + +void TTstringNode::initialize(TTstringNode *oldNode) { + _mode = oldNode->_mode; + _file = oldNode->_file; + + if (_string.isValid()) { + _field1C = 0; + } else { + _field1C = 11; + warning("TTstringNode::initialize has bad subobj"); + } + + delete oldNode; +} + +TTstringNode *TTstringNode::findByName(const TTstring &str, int mode) { + for (TTstringNode *nodeP = this; nodeP; nodeP = static_cast<TTstringNode *>(nodeP->_nextP)) { + if (nodeP->_mode == mode || (mode == 3 && nodeP->_mode < 3)) { + if (nodeP->_string == str) + return nodeP; + } + } + + return nullptr; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_string_node.h b/engines/titanic/true_talk/tt_string_node.h new file mode 100644 index 0000000000..ced162b439 --- /dev/null +++ b/engines/titanic/true_talk/tt_string_node.h @@ -0,0 +1,59 @@ +/* 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_TT_STRING_NODE_H +#define TITANIC_TT_STRING_NODE_H + +#include "titanic/true_talk/tt_node.h" +#include "titanic/true_talk/tt_string.h" +#include "titanic/support/exe_resources.h" + +namespace Titanic { + +class TTstringNode : public TTnode { +protected: + /** + * Initializes state for the node + */ + void initialize(int mode); + + /** + * Initializes state for the node + */ + void initialize(TTstringNode *oldNode); +public: + TTstring _string; + FileHandle _file; + int _mode; + int _field1C; +public: + TTstringNode(); + + /** + * Find a string node in the linked chain by name + */ + TTstringNode *findByName(const TTstring &str, int mode); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_STRING_NODE_H */ diff --git a/engines/titanic/true_talk/tt_synonym.cpp b/engines/titanic/true_talk/tt_synonym.cpp new file mode 100644 index 0000000000..0f56c5cb22 --- /dev/null +++ b/engines/titanic/true_talk/tt_synonym.cpp @@ -0,0 +1,87 @@ +/* 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/true_talk/tt_synonym.h" + +namespace Titanic { + +TTsynonym::TTsynonym() : TTstringNode(), _file(HANDLE_STDIN), + _mode(0), _field1C(0) { +} + +TTsynonym::TTsynonym(const TTsynonym *src) : TTstringNode(), + _mode(0), _field1C(0) { + _string = src->_string; + initialize(src->_mode); + _file = src->_file; +} + +TTsynonym::TTsynonym(int mode, const char *str, FileHandle file) : + TTstringNode(), _mode(0), _field1C(0) { + _string = str; + initialize(mode); + _file = file; +} + +TTsynonym::TTsynonym(int mode, TTstring *str) : TTstringNode() { + _string = *str; + initialize(mode); +} + +TTsynonym *TTsynonym::copyFrom(const TTsynonym *src) { + if (src->_field1C) { + _field1C = 5; + } else { + _field1C = 0; + if (src != this) + _string = src->_string; + } + + return this; +} + +int TTsynonym::save(SimpleFile *file) { + for (TTstringNode *synP = this; synP; synP = static_cast<TTstringNode *>(synP->_nextP)) { + file->writeFormat("%s", " 0 "); + synP->_string.save(file); + file->writeFormat("%c", ' '); + + if (synP->_mode) { + file->writeFormat("%1.0d", synP->_mode); + } else { + file->writeFormat("%c", '0'); + } + + file->writeFormat("%c", ' '); + + if (synP->_file) { + file->writeFormat("%2.0d", synP->_file); + } else { + file->writeFormat("%c", ' '); + } + file->writeFormat("%c", '\n'); + } + + return 0; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_synonym.h b/engines/titanic/true_talk/tt_synonym.h new file mode 100644 index 0000000000..d5dc2be09e --- /dev/null +++ b/engines/titanic/true_talk/tt_synonym.h @@ -0,0 +1,56 @@ +/* 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_TT_SYNONYM_H +#define TITANIC_TT_SYNONYM_H + +#include "titanic/true_talk/tt_string_node.h" +#include "titanic/support/simple_file.h" + +namespace Titanic { + +class TTsynonym : public TTstringNode { +public: + TTstring _string; + FileHandle _file; + int _mode; + int _field1C; +public: + TTsynonym(); + TTsynonym(const TTsynonym *src); + TTsynonym(int mode, const char *str, FileHandle file); + TTsynonym(int mode, TTstring *str); + + /** + * Copies data from one synonym to another + */ + TTsynonym *copyFrom(const TTsynonym *src); + + /** + * Save data for the synonym to file + */ + int save(SimpleFile *file); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_SYNONYM_H */ diff --git a/engines/titanic/true_talk/tt_talker.cpp b/engines/titanic/true_talk/tt_talker.cpp new file mode 100644 index 0000000000..61443a4835 --- /dev/null +++ b/engines/titanic/true_talk/tt_talker.cpp @@ -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. + * + */ + +#include "titanic/true_talk/tt_talker.h" +#include "titanic/messages/messages.h" +#include "titanic/pet_control/pet_control.h" + +namespace Titanic { + +void TTtalker::speechStarted(const CString &dialogueStr, uint dialogueId, uint soundId) { + _dialogueId = dialogueId; + + CTrueTalkNotifySpeechStartedMsg msg(soundId, dialogueId, 0); + msg.execute(_npc, nullptr, MSGFLAG_BREAK_IF_HANDLED); +} + +TTtalker::~TTtalker() { + CPetControl *petControl = _npc->getPetControl(); + if (petControl) + // Add in final line + petControl->convAddLine(_line); + + // Notify the end of the speech + CTrueTalkNotifySpeechEndedMsg endedMsg(_field24, _dialogueId); + endedMsg.execute(_npc, nullptr, MSGFLAG_BREAK_IF_HANDLED); +} + +void TTtalker::endSpeech(int val) { + _done = true; + _field24 = val; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_talker.h b/engines/titanic/true_talk/tt_talker.h new file mode 100644 index 0000000000..636eb0c022 --- /dev/null +++ b/engines/titanic/true_talk/tt_talker.h @@ -0,0 +1,65 @@ +/* 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_TT_TALKER_H +#define TITANIC_TT_TALKER_H + +#include "titanic/core/list.h" +#include "titanic/npcs/true_talk_npc.h" +#include "titanic/support/string.h" + +namespace Titanic { + +class CTrueTalkManager; + +class TTtalker : public ListItem { +public: + CTrueTalkManager *_owner; + CTrueTalkNPC *_npc; + CString _line; + int _dialogueId; + int _field24; + int _done; +public: + TTtalker() : _owner(nullptr), _npc(nullptr), + _dialogueId(0), _field24(0), _done(0) {} + TTtalker(CTrueTalkManager *owner, CTrueTalkNPC *npc) : + _owner(owner), _npc(npc), _dialogueId(0), _field24(0), _done(0) {} + ~TTtalker(); + + /** + * Start a new speech + */ + void speechStarted(const CString &dialogueStr, uint dialogueId, uint soundId); + + /** + * End the speech + */ + void endSpeech(int val); +}; + +class TTtalkerList : public List<TTtalker> { +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_TALKER_H */ diff --git a/engines/titanic/true_talk/tt_title_script.cpp b/engines/titanic/true_talk/tt_title_script.cpp new file mode 100644 index 0000000000..85b56d0e1e --- /dev/null +++ b/engines/titanic/true_talk/tt_title_script.cpp @@ -0,0 +1,31 @@ +/* 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/true_talk/tt_title_script.h" + +namespace Titanic { + +TTTitleScript::TTTitleScript() : TTscriptBase(1, "", 0, "", 0, -1, -1, -1, 0), + _field50(0), _field5C(-1), _field60(0) { +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_title_script.h b/engines/titanic/true_talk/tt_title_script.h new file mode 100644 index 0000000000..f02e591c54 --- /dev/null +++ b/engines/titanic/true_talk/tt_title_script.h @@ -0,0 +1,43 @@ +/* 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_TT_TITLE_SCRIPT_H +#define TITANIC_TT_TITLE_SCRIPT_H + +#include "titanic/true_talk/tt_script_base.h" +#include "titanic/true_talk/tt_string.h" + +namespace Titanic { + +class TTTitleScript : public TTscriptBase { +private: + int _field50; + TTstring _string1; + int _field5C; + int _field60; +public: + TTTitleScript(); +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_TITLE_SCRIPT_H */ diff --git a/engines/titanic/true_talk/tt_vocab.cpp b/engines/titanic/true_talk/tt_vocab.cpp new file mode 100644 index 0000000000..08d6e9e1a7 --- /dev/null +++ b/engines/titanic/true_talk/tt_vocab.cpp @@ -0,0 +1,557 @@ +/* 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/file.h"
+#include "titanic/true_talk/tt_vocab.h"
+#include "titanic/true_talk/tt_adj.h"
+#include "titanic/true_talk/tt_action.h"
+#include "titanic/true_talk/tt_adj.h"
+#include "titanic/true_talk/tt_major_word.h"
+#include "titanic/true_talk/tt_picture.h"
+#include "titanic/true_talk/tt_pronoun.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+TTvocab::TTvocab(int val): _headP(nullptr), _tailP(nullptr), _word(nullptr),
+ _fieldC(0), _field10(0), _vocabMode(val) {
+ load("STVOCAB.TXT");
+}
+
+TTvocab::~TTvocab() {
+ if (_headP) {
+ _headP->deleteSiblings();
+ delete _headP;
+ _headP = _tailP = nullptr;
+ }
+}
+
+int TTvocab::load(const CString &name) {
+ SimpleFile *file = g_vm->_exeResources._owner->openResource(name);
+ int result = 0;
+ bool skipFlag;
+
+ while (!result && !file->eos()) {
+ skipFlag = false;
+ WordClass wordClass = (WordClass)file->readNumber();
+ TTstring space(" ");
+
+ switch (wordClass) {
+ case WC_UNKNOWN: {
+ if (_word)
+ result = _word->readSyn(file);
+ skipFlag = true;
+ break;
+ }
+
+ case WC_ACTION: {
+ TTaction *word = new TTaction(space, WC_UNKNOWN, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ case WC_THING: {
+ TTpicture *word = new TTpicture(space, WC_UNKNOWN, 0, 0, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ case WC_ABSTRACT:
+ case WC_ADVERB: {
+ TTmajorWord *word = new TTmajorWord(space, WC_UNKNOWN, 0, 0);
+ result = word->load(file, wordClass);
+ _word = word;
+ break;
+ }
+
+ case WC_ARTICLE:
+ case WC_CONJUNCTION:
+ case WC_PREPOSITION: {
+ TTword *word = new TTword(space, WC_UNKNOWN, 0);
+ result = word->load(file, wordClass);
+ _word = word;
+ break;
+ }
+
+ case WC_ADJECTIVE: {
+ TTadj *word = new TTadj(space, WC_UNKNOWN, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ case WC_PRONOUN: {
+ TTpronoun *word = new TTpronoun(space, WC_UNKNOWN, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ default:
+ result = 4;
+ break;
+ }
+
+ if (!skipFlag && _word) {
+ if (result) {
+ // Something wrong occurred, so delete word
+ delete _word;
+ _word = nullptr;
+ } else {
+ // Add the word to the master vocab list
+ addWord(_word);
+ }
+ }
+ }
+
+ // Close resource and return result
+ delete file;
+ return result;
+}
+
+void TTvocab::addWord(TTword *word) {
+ TTword *existingWord = findWord(word->_text);
+
+ if (existingWord) {
+ if (word->_synP) {
+ // Move over the synonym
+ existingWord->appendNode(word->_synP);
+ word->_synP = nullptr;
+ }
+
+ _word = nullptr;
+ if (word)
+ delete word;
+ } else if (_tailP) {
+ _tailP->_nextP = word;
+ _tailP = word;
+ } else {
+ if (!_headP)
+ _headP = word;
+
+ _tailP = word;
+ }
+}
+
+TTword *TTvocab::findWord(const TTstring &str) {
+ TTsynonym *tempNode = new TTsynonym();
+ bool flag = false;
+ TTword *word = _headP;
+
+ while (word && !flag) {
+ if (_vocabMode != 3 || strcmp(word->c_str(), str)) {
+ if (word->findSynByName(str, tempNode, _vocabMode))
+ flag = true;
+ else
+ word = word->_nextP;
+ } else {
+ flag = true;
+ }
+ }
+
+ delete tempNode;
+ return word;
+}
+
+TTword *TTvocab::getWord(TTstring &str, TTword **srcWord) const {
+ TTword *word = getPrimeWord(str, srcWord);
+
+ if (!word) {
+ TTstring tempStr(str);
+ if (tempStr.size() > 2) {
+ word = getSuffixedWord(tempStr);
+
+ if (!word)
+ word = getPrefixedWord(tempStr);
+ }
+ }
+
+ return word;
+}
+
+TTword *TTvocab::getPrimeWord(TTstring &str, TTword **srcWord) const {
+ TTsynonym tempSyn;
+ char c = str.charAt(0);
+ TTword *newWord = nullptr;
+ TTword *vocabP;
+
+ if (!Common::isDigit(c)) {
+ vocabP = _headP;
+ newWord = new TTword(str, WC_ABSTRACT, 300);
+ } else {
+ for (vocabP = _headP; vocabP && !newWord; vocabP = vocabP->_nextP) {
+ if (_vocabMode == 3 && !strcmp(str.c_str(), vocabP->c_str())) {
+ newWord = vocabP->copy();
+ newWord->_nextP = nullptr;
+ newWord->setSyn(nullptr);
+ } else if (vocabP->findSynByName(str, &tempSyn, _vocabMode)) {
+ // Create a copy of the word and the found synonym
+ TTsynonym *newSyn = new TTsynonym(tempSyn);
+ newSyn->_nextP = newSyn->_priorP = nullptr;
+ newWord = vocabP->copy();
+ newWord->_nextP = nullptr;
+ newWord->setSyn(newSyn);
+ }
+ }
+ }
+
+ if (srcWord)
+ // Pass out the pointer to the original word
+ *srcWord = vocabP;
+
+ // Return the new copy of the word
+ return newWord;
+}
+
+TTword *TTvocab::getSuffixedWord(TTstring &str) const {
+ TTstring tempStr(str);
+ TTword *word = nullptr;
+
+ if (tempStr.hasSuffix("s")) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (!word) {
+ if (!tempStr.hasSuffix("e")) {
+ tempStr = str;
+ } else {
+ tempStr.deleteLastChar();
+ word = getPrimeWord(tempStr);
+ }
+ }
+
+ } else if (tempStr.hasSuffix("ing")) {
+ tempStr.deleteSuffix(3);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == 1) {
+ delete word;
+ word = nullptr;
+ } else {
+ delete word;
+ word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
+ }
+ } else {
+ tempStr += "e";
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass != 1) {
+ delete word;
+ word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
+ }
+ } else {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass != 1) {
+ delete word;
+ word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
+ }
+ } else {
+ tempStr = str;
+ }
+ }
+ }
+
+ } else if (tempStr.hasSuffix("ed")) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (!word) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+ }
+
+ if (word) {
+ if (word->_wordClass == WC_ACTION) {
+ static_cast<TTaction *>(word)->setVal(1);
+ }
+ } else {
+ tempStr = str;
+ }
+
+ } else if (tempStr.hasSuffix("ly")) {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ delete word;
+ word = new TTword(str, WC_ADVERB, 0);
+ } else {
+ tempStr = str;
+ }
+
+ } else if (tempStr.hasSuffix("er")) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word && word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ }
+ }
+
+ } else if (tempStr.hasSuffix("est")) {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ }
+ }
+
+ } else if (tempStr.hasSuffix("s*")) {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_PRONOUN || word->_wordClass == WC_ADVERB) {
+ delete word;
+ TTstring isStr("is");
+ word = getPrimeWord(isStr);
+ } else {
+ switch (word->_id) {
+ case 200:
+ if (word->proc10() == 2) {
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
+ } else if (word->proc10() == 1) {
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 4);
+ }
+ break;
+
+ case 201:
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
+ break;
+
+ case 202:
+ case 203:
+ if (word->proc10() == 2) {
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
+ } else {
+ int val = word->proc10() == 1 ? 0 : 4;
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, val);
+ }
+ break;
+
+ case 204:
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 6);
+ break;
+
+ default:
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 0);
+ break;
+ }
+ }
+ }
+ }
+
+ if (word)
+ word->setSynStr(str);
+
+ return word;
+}
+
+TTword *TTvocab::getPrefixedWord(TTstring &str) const {
+ TTstring tempStr(str);
+ TTword *word = nullptr;
+ int prefixLen = 0;
+
+ if (tempStr.hasPrefix("pre")) {
+ prefixLen = 3;
+ } else if (tempStr.hasPrefix("re") || tempStr.hasPrefix("co")) {
+ prefixLen = 2;
+ } else if (tempStr.hasPrefix("inter") || tempStr.hasPrefix("multi")) {
+ prefixLen = 5;
+ } else if (tempStr.hasPrefix("over") || tempStr.hasPrefix("post") || tempStr.hasPrefix("self")) {
+ prefixLen = 4;
+ }
+
+ if (prefixLen) {
+ // Known prefix found, so scan for word without prefix
+ tempStr.deletePrefix(prefixLen);
+ word = getPrimeWord(tempStr);
+ if (word)
+ tempStr = str;
+
+ } else if (tempStr.hasPrefix("anti") || tempStr.hasPrefix("counter")) {
+ prefixLen = tempStr[0] == 'a' ? 4 : 7;
+
+ tempStr.deletePrefix(prefixLen);
+ word = getPrimeWord(tempStr);
+ if (!word)
+ tempStr = str;
+ else if (word->_wordClass == 8) {
+ delete word;
+ word = nullptr;
+ }
+
+ } else if (tempStr.hasPrefix("hyper") || tempStr.hasPrefix("super") ||
+ tempStr.hasPrefix("ultra")) {
+ tempStr.deletePrefix(5);
+ word = getPrimeWord(tempStr);
+
+ if (!word)
+ tempStr = str;
+ else if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0)
+ adj->adjFn1(val1);
+ } else if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+
+ if (word) {
+ // Set the original word on either the found word or synonym
+ if (word->hasSynonyms())
+ word->setSynStr(str);
+ else
+ word->_text = str;
+ }
+
+ delete tempStr;
+ return word;
+}
+
+} // End of namespace Titanic
diff --git a/engines/titanic/true_talk/tt_vocab.h b/engines/titanic/true_talk/tt_vocab.h new file mode 100644 index 0000000000..fc7ee2e102 --- /dev/null +++ b/engines/titanic/true_talk/tt_vocab.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_ST_VOCAB_H +#define TITANIC_ST_VOCAB_H + +#include "titanic/support/string.h" +#include "titanic/true_talk/tt_string.h" +#include "titanic/true_talk/tt_word.h" + +namespace Titanic { + +class TTvocab { +private: + TTword *_headP; + TTword *_tailP; + TTword *_word; + int _fieldC; + int _field10; + int _vocabMode; +private: + /** + * Load the vocab data + */ + int load(const CString &name); + + /** + * Adds a specified word to the vocab list + */ + void addWord(TTword *word); + + /** + * Scans the vocab list for an existing word match + */ + TTword *findWord(const TTstring &str); + + /** + * Scans the vocab list for a word with a synonym matching the passed string. + * If found, creates a new word instance that only has the matching synonym + * linked to it. + * @param str Word text to scan for + * @param srcWord Optional pointer to store the original word match was found on + * @returns A new word instance if a match if found, or null if not + */ + TTword *getPrimeWord(TTstring &str, TTword **srcWord = nullptr) const; + + /** + * Checks the passed word for common suffixes, like 's', 'ing', etc. and, if found, + * checks for a word match for the base word without the suffix. + * @param str Word to check + * @returns New word instance for found match, or nullptr otherwise + */ + TTword *getSuffixedWord(TTstring &str) const; + + /** + * Checks the passed word for common prefixes, and checks for a word + * match for the word without the given prefix + * @param str Word to check + * @returns New word instance for found match, or nullptr otherwise + */ + TTword *getPrefixedWord(TTstring &str) const; +public: + TTvocab(int val); + ~TTvocab(); + + /** + * Gets a matching word from the vocab list given a passed string + * @param str Word text to scan for + * @param srcWord Optional pointer to store the original word match was found on + * @returns A new word instance if a match if found, or null if not + */ + TTword *getWord(TTstring &str, TTword **srcWord = nullptr) const; +}; + +} // End of namespace Titanic + +#endif /* TITANIC_ST_VOCAB_H */ diff --git a/engines/titanic/true_talk/tt_word.cpp b/engines/titanic/true_talk/tt_word.cpp new file mode 100644 index 0000000000..df6ee5c7bc --- /dev/null +++ b/engines/titanic/true_talk/tt_word.cpp @@ -0,0 +1,226 @@ +/* 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/true_talk/tt_word.h" +#include "titanic/true_talk/tt_string_node.h" +#include "titanic/titanic.h" + +namespace Titanic { + +TTword::TTword(const TTstring &str, WordClass wordClass, int id) : _text(str), + _wordClass(wordClass), _id(id), _tag(0), _field24(0), + _field28(0), _synP(nullptr), _nextP(nullptr) { + _status = str.getStatus() == SS_VALID ? SS_VALID : SS_5; +} + +TTword::TTword(const TTword *src) { + if (src->getStatus() != SS_VALID) { + _status = SS_5; + return; + } + + _text = src->_text; + _wordClass = src->_wordClass; + _id = src->_id; + _tag = src->_tag; + _synP = nullptr; + + TTsynonym *priorSyn = nullptr; + for (TTsynonym *synP = _synP; synP && !_status;) { + TTsynonym *newSyn = new TTsynonym(synP); + if (!newSyn) { + _status = SS_7; + } else { + newSyn->_priorP = priorSyn; + newSyn->_nextP = nullptr; + + if (priorSyn) { + priorSyn->_nextP = newSyn; + } else { + _synP = newSyn; + } + + priorSyn = newSyn; + } + } + + _nextP = src->_nextP; + _field24 = src->_field24; + _field28 = src->_field28; +} + +TTword::~TTword() { + if (_synP) { + _synP->deleteSiblings(); + delete _synP; + } +} + +void TTword::deleteSiblings() { + while (_nextP) { + TTword *next = _nextP; + _nextP = next->_nextP; + delete next; + } +} + +int TTword::readSyn(SimpleFile *file) { + CString str; + int mode, val1; + + if (!file->scanf("%s %d %d", &str, &mode, &val1)) + return 8; + if (!testFileHandle(file)) + return 5; + + // Create new synanym node + TTsynonym *synNode = new TTsynonym(mode, str.c_str(), (FileHandle)val1); + + if (_synP) { + // A synonym already exists, so add new one as a tail + // at the end of the linked list of synonyms + _synP->addToTail(synNode); + } else { + // Very first synonym, so set it + _synP = synNode; + } + + return 0; +} + +void TTword::setSyn(TTsynonym *synP) { + if (_synP) { + _synP->deleteSiblings(); + delete _synP; + } + + _synP = synP; +} + +int TTword::setSynStr(TTstring &str) { + if (str.empty()) + return 4; + + TTstring *newStr = new TTstring(str); + TTsynonym *newSyn = new TTsynonym(4, newStr); + setSyn(newSyn); + return 0; +} + +void TTword::appendNode(TTsynonym *node) { + if (_synP) + _synP->addToTail(node); + else + _synP = node; +} + +int TTword::load(SimpleFile *file, WordClass wordClass) { + CString str1, str2; + int id; + + if (file->scanf("%d %s %s", &id, &str1, &str2)) { + _text = str1; + _id = id; + _tag = readNumber(str2.c_str()); + _wordClass = wordClass; + return 0; + } else { + return 3; + } +} + +uint TTword::readNumber(const char *str) { + uint numValue = *str; + if (*str == '0') { + numValue = MKTAG('Z', 'Z', 'Z', '['); + } else { + ++str; + for (int idx = 0; idx < 3; ++idx, ++str) + numValue = (numValue << 8) + *str; + } + + return numValue; +} + +bool TTword::testFileHandle(FileHandle file) const { + if (g_vm->_exeResources.is18Equals(3)) + return true; + + // TODO: Figure out why original compares passed file handle against specific values + return true; +} + +bool TTword::findSynByName(const TTstring &str, TTsynonym *dest, int mode) const { + if (!_synP) + return false; + + const TTsynonym *synP = static_cast<const TTsynonym *>(_synP->findByName(str, mode)); + if (synP) { + dest->copyFrom(synP); + dest->_priorP = nullptr; + dest->_nextP = nullptr; + + return true; + } else { + return false; + } +} + +bool TTword::compareTo(const char *str) const { + return _text == str; +} + +TTword *TTword::copy() const { + return new TTword(this); +} + +FileHandle TTword::getSynFile() const { + return _synP ? _synP->_file : HANDLE_STDIN; +} + +bool TTword::checkSynFile(FileHandle file) const { + return _synP && _synP->_file == file; +} + +void TTword::setSynFile(FileHandle file) { + if (_synP && testFileHandle(file)) + _synP->_file = file; +} + +TTstringStatus TTword::getChainStatus() const { + for (const TTword *word = this; word; word = word->_nextP) { + if (word->getStatus()) + return word->getStatus(); + } + + return SS_VALID; +} + +TTword *TTword::copyWords() { + TTword *result = copy(); + for (TTword *word = result; word; word = word->_nextP) + word->_nextP = word->_nextP->copy(); + + return result; +} + +} // End of namespace Titanic diff --git a/engines/titanic/true_talk/tt_word.h b/engines/titanic/true_talk/tt_word.h new file mode 100644 index 0000000000..7fd61c38ac --- /dev/null +++ b/engines/titanic/true_talk/tt_word.h @@ -0,0 +1,216 @@ +/* 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_TT_WORD_H +#define TITANIC_TT_WORD_H + +#include "titanic/support/simple_file.h" +#include "titanic/true_talk/tt_string.h" +#include "titanic/true_talk/tt_synonym.h" + +namespace Titanic { + +/** + * Types of words + */ +enum WordClass { + WC_UNKNOWN = 0, WC_ACTION = 1, WC_THING = 2, WC_ABSTRACT = 3, + WC_ARTICLE = 4, WC_CONJUNCTION = 5, WC_PRONOUN = 6, + WC_PREPOSITION = 7, WC_ADJECTIVE = 8, WC_ADVERB = 9 +}; + +class TTword { +protected: + TTstringStatus _status; + int _field24; + int _field28; +protected: + /** + * Read in a number + */ + uint readNumber(const char *str); + + bool testFileHandle(SimpleFile *file) const { return true; } + bool testFileHandle(FileHandle resHandle) const; +public: + TTword *_nextP; + TTsynonym *_synP; + TTstring _text; + WordClass _wordClass; + int _id; + uint _tag; +public: + TTword(const TTstring &str, WordClass wordClass, int val2); + TTword(const TTword *src); + virtual ~TTword(); + + /** + * Delete any following words chained to the word + */ + void deleteSiblings(); + + /** + * Read in a synonym for the given word + */ + int readSyn(SimpleFile *file); + + /** + * Set a new synonym for the word + */ + void setSyn(TTsynonym *synP); + + /** + * Set a new synonym string + */ + int setSynStr(TTstring &str); + + /** + * Returns true if synonyms have been set for the word + */ + bool hasSynonyms() const { return _synP != nullptr; } + + /** + * Either sets the first synonym for a word, or adds it to an existing one + */ + void appendNode(TTsynonym *node); + + /** + * Load the word + */ + int load(SimpleFile *file, WordClass wordClass); + + /** + * Finds a synonym in the word by name, if one exists + * @param str Name to search for + * @param dest Destination synonym instance to copy match into + * @returns Returns true if a match was found + */ + bool findSynByName(const TTstring &str, TTsynonym *dest, int mode) const; + + const char *c_str() const { return _text.c_str(); } + operator const char *() const { return c_str(); } + + /** + * Return the text of the word + */ + const TTstring getText() { return _text; } + + /** + * Compares the word's text to a passed string + */ + bool compareTo(const char *str) const; + + /** + * Compares the word's text to a passed string + */ + bool compareTo(TTstring *str) const { + return compareTo(str->c_str()); + } + + /** + * Return the status of the word + */ + TTstringStatus getStatus() const { return _status; } + + /** + * Returns true if the word is in a valid state + */ + bool isValid() const { return _status == SS_VALID; } + + /** + * Return the status of the entire word chain + */ + TTstringStatus getChainStatus() const; + + /** + * Returns true if the word is of the specified class + */ + bool isClass(WordClass wordClass) const { return _wordClass == wordClass; } + + /** + * Copy the word and any attached to it + */ + TTword *copyWords(); + + /** + * Creates a copy of the word + */ + virtual TTword *copy() const; + + virtual bool proc2(int val) const { return false; } + virtual int proc3() const { return -1; } + virtual void proc4() {} + virtual void proc5() {} + + /** + * Checks whether the word's tag is a known type + */ + virtual bool checkTag() const { return false; } + + /** + * Compare the word's tag to a given tag value + */ + virtual bool compareTagTo(uint tag) const { return false; } + + /** + * Return the tag associated with the word + */ + virtual uint getTag() const { return 0; } + + virtual bool proc9(int val) const { return false; } + virtual int proc10() const { return 0; } + virtual void proc11() {} + virtual bool proc12(int val) const { return false; } + virtual int proc13() const { return 0; } + virtual bool proc14(int val) const { return false; } + virtual int proc15() const { return -1; } + virtual bool proc16() const { return false; } + virtual bool proc17() const { return false; } + virtual bool proc18() const { return false; } + virtual bool comparePronounTo(int val) const { return false; } + virtual int proc20() const { return 0; } + + /** + * Returns the file associated with the word's first synonym + */ + virtual FileHandle getSynFile() const; + + /** + * Checks whether the file associated with the word's first + * synonym matches the specified file + */ + virtual bool checkSynFile(FileHandle file) const; + + /** + * Sets the file associated with a synonym + */ + virtual void setSynFile(FileHandle file); + + /** + * Dumps data associated with the word to file + */ + virtual int save(SimpleFile *file) const { return 0; } +}; + +} // End of namespace Titanic + +#endif /* TITANIC_TT_WORD_H */ diff --git a/engines/wage/design.cpp b/engines/wage/design.cpp index 2bfea9df7d..fd2a67b81e 100644 --- a/engines/wage/design.cpp +++ b/engines/wage/design.cpp @@ -47,20 +47,20 @@ #include "graphics/managed_surface.h" #include "graphics/primitives.h" +#include "graphics/macgui/macwindowmanager.h" -#include "wage/macwindowmanager.h" #include "wage/design.h" namespace Wage { struct PlotData { Graphics::ManagedSurface *surface; - Patterns *patterns; + Graphics::MacPatterns *patterns; uint fillType; int thickness; Design *design; - PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t, Design *d) : + PlotData(Graphics::ManagedSurface *s, Graphics::MacPatterns *p, int f, int t, Design *d) : surface(s), patterns(p), fillType(f), thickness(t), design(d) {} }; @@ -85,7 +85,7 @@ Design::~Design() { delete _surface; } -void Design::paint(Graphics::ManagedSurface *surface, Patterns &patterns, int x, int y) { +void Design::paint(Graphics::ManagedSurface *surface, Graphics::MacPatterns &patterns, int x, int y) { bool needRender = false; if (_surface == NULL) { @@ -141,7 +141,7 @@ void Design::paint(Graphics::ManagedSurface *surface, Patterns &patterns, int x, } } -void Design::render(Patterns &patterns) { +void Design::render(Graphics::MacPatterns &patterns) { Common::MemoryReadStream in(_data, _len); bool needRender = true; @@ -235,9 +235,9 @@ void drawPixel(int x, int y, int color, void *data) { color : kColorWhite; } } else { - int x1 = x; + int x1 = x - p->thickness / 2; int x2 = x1 + p->thickness; - int y1 = y; + int y1 = y - p->thickness / 2; int y2 = y1 + p->thickness; for (y = y1; y < y2; y++) @@ -265,7 +265,7 @@ void drawPixelPlain(int x, int y, int color, void *data) { } void Design::drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); int16 y2 = in.readSint16BE(); @@ -294,7 +294,7 @@ void Design::drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, } void Design::drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); int16 y2 = in.readSint16BE(); @@ -320,7 +320,7 @@ void Design::drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream } void Design::drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { byte ignored = in.readSint16BE(); // ignored @@ -397,7 +397,7 @@ void Design::drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream & } void Design::drawOval(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); int16 y2 = in.readSint16BE(); @@ -501,11 +501,11 @@ void Design::drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadS tmp.free(); } -void Design::drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { drawRect(surface, rect.left, rect.top, rect.right, rect.bottom, thickness, color, patterns, fillType); } -void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawLine(x1, y1, x2, y1, kColorBlack, drawPixel, &pd); @@ -515,26 +515,26 @@ void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, } -void Design::drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType) { +void Design::drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, 1, nullptr); for (int y = rect.top; y <= rect.bottom; y++) Graphics::drawHLine(rect.left, rect.right, y, color, drawPixel, &pd); } -void Design::drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType) { +void Design::drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, 1, nullptr); Graphics::drawRoundRect(rect, arc, color, true, drawPixel, &pd); } -void Design::drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawHLine(x1, x2, y, color, drawPixel, &pd); } -void Design::drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawVLine(x, y1, y2, color, drawPixel, &pd); diff --git a/engines/wage/design.h b/engines/wage/design.h index 86225c9224..017fdfc14d 100644 --- a/engines/wage/design.h +++ b/engines/wage/design.h @@ -51,10 +51,15 @@ #include "common/memstream.h" #include "common/rect.h" -#include "wage/macwindowmanager.h" +#include "graphics/nine_patch.h" +#include "graphics/transparent_surface.h" + +#include "graphics/macgui/macwindowmanager.h" namespace Wage { +using namespace Graphics::MacGUIConstants; + class Design { public: Design(Common::SeekableReadStream *data); @@ -68,14 +73,14 @@ public: return _bounds; } - void paint(Graphics::ManagedSurface *canvas, Patterns &patterns, int x, int y); + void paint(Graphics::ManagedSurface *canvas, Graphics::MacPatterns &patterns, int x, int y); bool isPointOpaque(int x, int y); - static void drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType); - static void drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType); - static void drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType); - static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType); - static void drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType); - static void drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType); + static void drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); + static void drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Graphics::MacPatterns &patterns, byte fillType); bool isBoundsCalculation() { return _boundsCalculationMode; } void adjustBounds(int16 x, int16 y); @@ -88,15 +93,15 @@ private: bool _boundsCalculationMode; private: - void render(Patterns &patterns); + void render(Graphics::MacPatterns &patterns); void drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawOval(Graphics::ManagedSurface *surface, Common::ReadStream &in, - Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); + Graphics::MacPatterns &patterns, byte fillType, byte borderThickness, byte borderFillType); void drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadStream &in); }; diff --git a/engines/wage/detection.cpp b/engines/wage/detection.cpp index 8b8a6399a8..a27bfd7fde 100644 --- a/engines/wage/detection.cpp +++ b/engines/wage/detection.cpp @@ -99,7 +99,7 @@ SaveStateList WageMetaEngine::listSaves(const char *target) const { const uint32 WAGEflag = MKTAG('W','A','G','E'); Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; - char saveDesc[31]; + char saveDesc[128] = {0}; Common::String pattern = target; pattern += ".###"; @@ -113,9 +113,18 @@ SaveStateList WageMetaEngine::listSaves(const char *target) const { if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(*file); if (in) { + saveDesc[0] = 0; + in->seek(in->size() - 8); + uint32 offset = in->readUint32BE(); uint32 type = in->readUint32BE(); - if (type == WAGEflag) - in->read(saveDesc, 31); + if (type == WAGEflag) { + in->seek(offset); + + type = in->readUint32BE(); + if (type == WAGEflag) { + in->read(saveDesc, 127); + } + } saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); delete in; } @@ -142,11 +151,11 @@ void WageMetaEngine::removeSaveState(const char *target, int slot) const { namespace Wage { bool WageEngine::canLoadGameStateCurrently() { - return false; + return true; } bool WageEngine::canSaveGameStateCurrently() { - return false; + return true; } } // End of namespace Wage diff --git a/engines/wage/dialog.cpp b/engines/wage/dialog.cpp index 86080c9a6f..0a326817be 100644 --- a/engines/wage/dialog.cpp +++ b/engines/wage/dialog.cpp @@ -48,8 +48,9 @@ #include "common/system.h" #include "common/events.h" +#include "graphics/macgui/macwindowmanager.h" + #include "wage/wage.h" -#include "wage/macwindowmanager.h" #include "wage/design.h" #include "wage/gui.h" #include "wage/dialog.h" @@ -91,7 +92,7 @@ Dialog::~Dialog() { } const Graphics::Font *Dialog::getDialogFont() { - return _gui->_wm.getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); + return _gui->_wm.getFont(_gui->_wm.getFontName(0, 12), Graphics::FontManager::kBigGUIFont); // Default is Chicago } void Dialog::paint() { diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp index 43ac6c8cc7..3dcf37033a 100644 --- a/engines/wage/entities.cpp +++ b/engines/wage/entities.cpp @@ -48,6 +48,7 @@ #include "wage/wage.h" #include "wage/entities.h" #include "wage/design.h" +#include "wage/gui.h" #include "wage/script.h" #include "wage/world.h" @@ -80,6 +81,8 @@ Context::Context() { } Scene::Scene() { + _resourceId = 0; + _script = NULL; _design = NULL; _textBounds = NULL; @@ -104,6 +107,8 @@ Scene::Scene(Common::String name, Common::SeekableReadStream *data) { _classType = SCENE; _design = new Design(data); + _resourceId = 0; + _script = NULL; _textBounds = NULL; _fontSize = 0; @@ -142,65 +147,23 @@ void Scene::paint(Graphics::ManagedSurface *surface, int x, int y) { _design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); for (ObjList::const_iterator it = _objs.begin(); it != _objs.end(); ++it) { - debug(2, "paining Obj: %s, index: %d, type: %d", (*it)->_name.c_str(), (*it)->_index, (*it)->_type); + debug(2, "painting Obj: %s, index: %d, type: %d", (*it)->_name.c_str(), (*it)->_index, (*it)->_type); (*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); } for (ChrList::const_iterator it = _chrs.begin(); it != _chrs.end(); ++it) { - debug(2, "paining Chr: %s", (*it)->_name.c_str()); + debug(2, "painting Chr: %s", (*it)->_name.c_str()); (*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y); } } -// Source: Apple IIGS Technical Note #41, "Font Family Numbers" -// http://apple2.boldt.ca/?page=til/tn.iigs.041 -static const char *const fontNames[] = { - "Chicago", // system font - "Geneva", // application font - "New York", - "Geneva", - - "Monaco", - "Venice", - "London", - "Athens", - - "San Francisco", - "Toronto", - NULL, - "Cairo", - "Los Angeles", // 12 - - "Zapf Dingbats", - "Bookman", - "Helvetica Narrow", - "Palatino", - NULL, - "Zapf Chancery", - NULL, - - "Times", // 20 - "Helvetica", - "Courier", - "Symbol", - "Taliesin", // mobile? - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, // 30 - NULL, - NULL, - "Avant Garde", - "New Century Schoolbook" -}; - const char *Scene::getFontName() { - if (_fontType >= 0 && _fontType < ARRAYSIZE(fontNames) && fontNames[_fontType] != NULL) { - return fontNames[_fontType]; - } - return "Unknown"; + const char *name = ((WageEngine *)g_engine)->_gui->_wm.getFontName(_fontType, _fontSize); + + if (!name) + return "Unknown"; + + return name; } Designed *Scene::lookUpEntity(int x, int y) { @@ -221,6 +184,7 @@ Designed *Scene::lookUpEntity(int x, int y) { Obj::Obj() : _currentOwner(NULL), _currentScene(NULL) { _index = 0; + _resourceId = 0; _namePlural = false; _value = 0; _attackType = 0; @@ -231,7 +195,9 @@ Obj::Obj() : _currentOwner(NULL), _currentScene(NULL) { _damage = 0; } -Obj::Obj(Common::String name, Common::SeekableReadStream *data) { +Obj::Obj(Common::String name, Common::SeekableReadStream *data, int resourceId) { + _resourceId = resourceId; + _name = name; _classType = OBJ; _currentOwner = NULL; @@ -322,6 +288,7 @@ Chr::Chr(Common::String name, Common::SeekableReadStream *data) { _design = new Design(data); _index = 0; + _resourceId = 0; _currentScene = NULL; setDesignBounds(readRect(data)); diff --git a/engines/wage/entities.h b/engines/wage/entities.h index 9e706f0d58..f327270254 100644 --- a/engines/wage/entities.h +++ b/engines/wage/entities.h @@ -152,6 +152,7 @@ public: Chr(Common::String name, Common::SeekableReadStream *data); int _index; + int _resourceId; Common::String _initialScene; int _gender; bool _nameProperNoun; @@ -229,7 +230,7 @@ public: class Obj : public Designed { public: Obj(); - Obj(Common::String name, Common::SeekableReadStream *data); + Obj(Common::String name, Common::SeekableReadStream *data, int resourceId); ~Obj(); enum ObjectType { @@ -256,6 +257,7 @@ public: public: int _index; + int _resourceId; bool _namePlural; uint _value; int _attackType; @@ -301,6 +303,8 @@ public: RANDOM = 1 }; + int _resourceId; + Script *_script; Common::String _text; Common::Rect *_textBounds; diff --git a/engines/wage/gui-console.cpp b/engines/wage/gui-console.cpp index 8b6fe43a17..2476a8c7fb 100644 --- a/engines/wage/gui-console.cpp +++ b/engines/wage/gui-console.cpp @@ -51,24 +51,21 @@ #include "graphics/cursorman.h" #include "graphics/fonts/bdf.h" #include "graphics/palette.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" #include "wage/wage.h" #include "wage/design.h" #include "wage/entities.h" -#include "wage/macwindow.h" -#include "wage/macmenu.h" #include "wage/gui.h" #include "wage/world.h" namespace Wage { const Graphics::Font *Gui::getConsoleFont() { - char fontName[128]; Scene *scene = _engine->_world->_player->_currentScene; - snprintf(fontName, 128, "%s-%d", scene->getFontName(), scene->_fontSize); - - return _wm.getFont(fontName, Graphics::FontManager::kConsoleFont); + return _wm.getFont(scene->getFontName(), Graphics::FontManager::kConsoleFont); } void Gui::clearOutput() { @@ -309,7 +306,20 @@ void Gui::drawInput() { font->drawString(&_screen, _out[_inputTextLineNum], x, y, _screen.w, kColorBlack); - g_system->copyRectToScreen(_screen.getBasePtr(x, y), _screen.pitch, x, y, _consoleWindow->getInnerDimensions().width(), font->getFontHeight()); + int w = _consoleWindow->getInnerDimensions().width(); + int h = font->getFontHeight(); + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + if (x + w > _screen.w) w = _screen.w - x; + if (y + h > _screen.h) h = _screen.h - y; + if (w != 0 && h != 0) + g_system->copyRectToScreen(_screen.getBasePtr(x, y), _screen.pitch, x, y, w, h); } _cursorX = font->getStringWidth(_out[_inputTextLineNum]) + kConHPadding; diff --git a/engines/wage/gui.cpp b/engines/wage/gui.cpp index 099279158f..cd259e6ddd 100644 --- a/engines/wage/gui.cpp +++ b/engines/wage/gui.cpp @@ -49,25 +49,25 @@ #include "common/system.h" #include "graphics/cursorman.h" #include "graphics/primitives.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" #include "wage/wage.h" #include "wage/design.h" #include "wage/entities.h" #include "wage/gui.h" -#include "wage/macwindow.h" -#include "wage/macwindowmanager.h" -#include "wage/macmenu.h" #include "wage/world.h" namespace Wage { -static const MenuData menuSubItems[] = { +static const Graphics::MenuData menuSubItems[] = { { kMenuHighLevel, "File", 0, 0, false }, { kMenuHighLevel, "Edit", 0, 0, false }, { kMenuFile, "New", kMenuActionNew, 0, false }, - { kMenuFile, "Open...", kMenuActionOpen, 0, false }, + { kMenuFile, "Open...", kMenuActionOpen, 0, true }, { kMenuFile, "Close", kMenuActionClose, 0, true }, - { kMenuFile, "Save", kMenuActionSave, 0, false }, + { kMenuFile, "Save", kMenuActionSave, 0, true }, { kMenuFile, "Save as...", kMenuActionSaveAs, 0, true }, { kMenuFile, "Revert", kMenuActionRevert, 0, false }, { kMenuFile, "Quit", kMenuActionQuit, 0, true }, @@ -96,16 +96,22 @@ static void cursorTimerHandler(void *refCon) { x += gui->_consoleWindow->getInnerDimensions().left; y += gui->_consoleWindow->getInnerDimensions().top; + int h = kCursorHeight; - gui->_screen.vLine(x, y, y + kCursorHeight, gui->_cursorState ? kColorBlack : kColorWhite); + if (y + h > gui->_consoleWindow->getInnerDimensions().bottom) { + h = gui->_consoleWindow->getInnerDimensions().bottom - y; + } + + if (h > 0) + gui->_screen.vLine(x, y, y + h, gui->_cursorState ? kColorBlack : kColorWhite); if (!gui->_cursorOff) gui->_cursorState = !gui->_cursorState; gui->_cursorRect.left = x; gui->_cursorRect.right = MIN<uint16>(x + 1, gui->_screen.w); - gui->_cursorRect.top = y; - gui->_cursorRect.bottom = MIN<uint16>(y + kCursorHeight, gui->_screen.h); + gui->_cursorRect.top = MIN<uint16>(y - 1, gui->_consoleWindow->getInnerDimensions().top); + gui->_cursorRect.bottom = MIN<uint16>(MIN<uint16>(y + h, gui->_screen.h), gui->_consoleWindow->getInnerDimensions().bottom); gui->_cursorDirty = true; } @@ -168,6 +174,9 @@ Gui::Gui(WageEngine *engine) { _consoleWindow = _wm.addWindow(true, true, true); _consoleWindow->setCallback(consoleWindowCallback, this); + + loadBorders(); + } Gui::~Gui() { @@ -211,8 +220,19 @@ void Gui::draw() { _wm.draw(); if (_cursorDirty && _cursorRect.left < _screen.w && _cursorRect.bottom < _screen.h) { - g_system->copyRectToScreen(_screen.getBasePtr(_cursorRect.left, _cursorRect.top), _screen.pitch, - _cursorRect.left, _cursorRect.top, _cursorRect.width(), _cursorRect.height()); + int x = _cursorRect.left, y = _cursorRect.top, w = _cursorRect.width(), h = _cursorRect.height(); + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + if (x + w > _screen.w) w = _screen.w - x; + if (y + h > _screen.h) h = _screen.h - y; + if (w != 0 && h != 0) + g_system->copyRectToScreen(_screen.getBasePtr(x, y), _screen.pitch, x, y, w, h); _cursorDirty = false; } @@ -323,12 +343,19 @@ void Gui::executeMenuCommand(int action, Common::String &text) { switch(action) { case kMenuActionAbout: case kMenuActionNew: - case kMenuActionOpen: case kMenuActionClose: - case kMenuActionSave: - case kMenuActionSaveAs: case kMenuActionRevert: case kMenuActionQuit: + break; + + case kMenuActionOpen: + _engine->scummVMSaveLoadDialog(false); + break; + + case kMenuActionSave: + case kMenuActionSaveAs: + _engine->scummVMSaveLoadDialog(true); + break; case kMenuActionUndo: actionUndo(); @@ -356,4 +383,30 @@ void Gui::executeMenuCommand(int action, Common::String &text) { } } +void Gui::loadBorders() { + // Do not load borders for now + //loadBorder(_sceneWindow, "border_inac.bmp", false); + //loadBorder(_sceneWindow, "border_act.bmp", true); +} + +void Gui::loadBorder(Graphics::MacWindow *target, Common::String filename, bool active) { + Common::File borderfile; + + if (!borderfile.open(filename)) { + debug(1, "Cannot open border file"); + return; + } + + Image::BitmapDecoder bmpDecoder; + Common::SeekableReadStream *stream = borderfile.readStream(borderfile.size()); + if (stream) { + + target->loadBorder(*stream, active, 10, 10, 1, 1); + + borderfile.close(); + + delete stream; + } +} + } // End of namespace Wage diff --git a/engines/wage/gui.h b/engines/wage/gui.h index ba1bb5ef3b..898c7c3162 100644 --- a/engines/wage/gui.h +++ b/engines/wage/gui.h @@ -51,15 +51,25 @@ #include "common/str-array.h" #include "graphics/font.h" #include "graphics/managed_surface.h" +#include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macwindow.h" +#include "graphics/macgui/macmenu.h" +#include "graphics/macgui/macwindowborder.h" + #include "common/events.h" #include "common/rect.h" -#include "wage/macwindow.h" -#include "wage/macwindowmanager.h" +#include "common/file.h" +#include "graphics/pixelformat.h" +#include "image/bmp.h" + +#include "graphics/palette.h" + namespace Wage { -class Menu; +using namespace Graphics::MacWindowConstants; + class Scene; class WageEngine; @@ -67,6 +77,44 @@ enum { kCursorHeight = 12 }; +enum { + kFontStyleBold = 1, + kFontStyleItalic = 2, + kFontStyleUnderline = 4, + kFontStyleOutline = 8, + kFontStyleShadow = 16, + kFontStyleCondensed = 32, + kFontStyleExtended = 64 +}; + +enum { + kMenuHighLevel = -1, + kMenuAbout = 0, + kMenuFile = 1, + kMenuEdit = 2, + kMenuCommands = 3, + kMenuWeapons = 4 +}; + +enum { + kMenuActionAbout, + kMenuActionNew, + kMenuActionOpen, + kMenuActionClose, + kMenuActionSave, + kMenuActionSaveAs, + kMenuActionRevert, + kMenuActionQuit, + + kMenuActionUndo, + kMenuActionCut, + kMenuActionCopy, + kMenuActionPaste, + kMenuActionClear, + + kMenuActionCommand +}; + class Gui { public: Gui(WageEngine *engine); @@ -107,6 +155,9 @@ private: int calcTextX(int x, int textLine); int calcTextY(int y); void updateTextSelection(int x, int y); + + void loadBorders(); + void loadBorder(Graphics::MacWindow *target, Common::String filename, bool active); public: Graphics::ManagedSurface _screen; @@ -121,13 +172,14 @@ public: Scene *_scene; - MacWindowManager _wm; - MacWindow *_sceneWindow; - MacWindow *_consoleWindow; + Graphics::MacWindowManager _wm; + Graphics::MacWindow *_sceneWindow; + Graphics::MacWindow *_consoleWindow; private: + Graphics::ManagedSurface _console; - Menu *_menu; + Graphics::Menu *_menu; bool _sceneDirty; bool _consoleDirty; diff --git a/engines/wage/macmenu.cpp b/engines/wage/macmenu.cpp deleted file mode 100644 index ed5f5070ff..0000000000 --- a/engines/wage/macmenu.cpp +++ /dev/null @@ -1,563 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "common/system.h" -#include "common/keyboard.h" - -#include "graphics/primitives.h" -#include "graphics/font.h" - -#include "wage/macwindowmanager.h" -#include "wage/macwindow.h" -#include "wage/macmenu.h" - -namespace Wage { - -enum { - kMenuHeight = 20, - kMenuLeftMargin = 7, - kMenuSpacing = 13, - kMenuPadding = 16, - kMenuDropdownPadding = 14, - kMenuDropdownItemHeight = 16, - kMenuItemHeight = 20 -}; - -struct MenuSubItem { - Common::String text; - int action; - int style; - char shortcut; - bool enabled; - Common::Rect bbox; - - MenuSubItem(const char *t, int a, int s = 0, char sh = 0, bool e = true) : text(t), action(a), style(s), shortcut(sh), enabled(e) {} -}; - -typedef Common::Array<MenuSubItem *> SubItemArray; - -struct MenuItem { - Common::String name; - SubItemArray subitems; - Common::Rect bbox; - Common::Rect subbbox; - - MenuItem(const char *n) : name(n) {} -}; - -Menu::Menu(int id, const Common::Rect &bounds, MacWindowManager *wm) - : BaseMacWindow(id, false, wm) { - _font = getMenuFont(); - - _screen.create(bounds.width(), bounds.height(), Graphics::PixelFormat::createFormatCLUT8()); - - _bbox.left = 0; - _bbox.top = 0; - _bbox.right = _screen.w; - _bbox.bottom = kMenuHeight; - - _menuActivated = false; - _activeItem = -1; - _activeSubItem = -1; - - _ccallback = NULL; - _cdata = NULL; - - _tempSurface.create(_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); -} - -Menu::~Menu() { - for (uint i = 0; i < _items.size(); i++) { - for (uint j = 0; j < _items[i]->subitems.size(); j++) - delete _items[i]->subitems[j]; - delete _items[i]; - } -} - -void Menu::addStaticMenus(const MenuData *data) { - MenuItem *about = new MenuItem(_wm->hasBuiltInFonts() ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple - _items.push_back(about); - - for (int i = 0; data[i].menunum; i++) { - const MenuData *m = &data[i]; - - if (m->menunum == kMenuHighLevel) { - MenuItem *item = new MenuItem(m->title); - _items.push_back(item); - - continue; - } - - _items[m->menunum]->subitems.push_back(new MenuSubItem(m->title, m->action, 0, m->shortcut, m->enabled)); - } -} - -int Menu::addMenuItem(const char *name) { - MenuItem *i = new MenuItem(name); - _items.push_back(i); - - return _items.size() - 1; -} - -void Menu::addMenuSubItem(int id, const char *text, int action, int style, char shortcut, bool enabled) { - _items[id]->subitems.push_back(new MenuSubItem(text, action, style, shortcut, enabled)); -} - -void Menu::calcDimensions() { - // Calculate menu dimensions - int y = 1; - int x = 18; - - for (uint i = 0; i < _items.size(); i++) { - int w = _font->getStringWidth(_items[i]->name); - - if (_items[i]->bbox.bottom == 0) { - _items[i]->bbox.left = x - kMenuLeftMargin; - _items[i]->bbox.top = y; - _items[i]->bbox.right = x + w + kMenuSpacing - kMenuLeftMargin; - _items[i]->bbox.bottom = y + _font->getFontHeight() + (_wm->hasBuiltInFonts() ? 3 : 2); - } - - calcMenuBounds(_items[i]); - - x += w + kMenuSpacing; - } -} - -void Menu::clearSubMenu(int id) { - MenuItem *menu = _items[id]; - - for (uint j = 0; j < menu->subitems.size(); j++) - delete menu->subitems[j]; - - menu->subitems.clear(); -} - -void Menu::createSubMenuFromString(int id, const char *str) { - clearSubMenu(id); - - MenuItem *menu = _items[id]; - Common::String string(str); - - Common::String item; - - for (uint i = 0; i < string.size(); i++) { - while(i < string.size() && string[i] != ';') // Read token - item += string[i++]; - - if (item == "(-") { - menu->subitems.push_back(new MenuSubItem(NULL, 0)); - } else { - bool enabled = true; - int style = 0; - char shortcut = 0; - const char *shortPtr = strrchr(item.c_str(), '/'); - if (shortPtr != NULL) { - if (strlen(shortPtr) >= 2) { - shortcut = shortPtr[1]; - item.deleteChar(shortPtr - item.c_str()); - item.deleteChar(shortPtr - item.c_str()); - } else { - error("Unexpected shortcut: '%s', item '%s' in menu '%s'", shortPtr, item.c_str(), string.c_str()); - } - } - - while (item.size() >= 2 && item[item.size() - 2] == '<') { - char c = item.lastChar(); - if (c == 'B') { - style |= kFontStyleBold; - } else if (c == 'I') { - style |= kFontStyleItalic; - } else if (c == 'U') { - style |= kFontStyleUnderline; - } else if (c == 'O') { - style |= kFontStyleOutline; - } else if (c == 'S') { - style |= kFontStyleShadow; - } else if (c == 'C') { - style |= kFontStyleCondensed; - } else if (c == 'E') { - style |= kFontStyleExtended; - } - item.deleteLastChar(); - item.deleteLastChar(); - } - - Common::String tmpitem(item); - tmpitem.trim(); - if (tmpitem[0] == '(') { - enabled = false; - - for (uint j = 0; j < item.size(); j++) - if (item[j] == '(') { - item.deleteChar(j); - break; - } - } - - menu->subitems.push_back(new MenuSubItem(item.c_str(), kMenuActionCommand, style, shortcut, enabled)); - } - - item.clear(); - } - - calcMenuBounds(menu); -} - -const Graphics::Font *Menu::getMenuFont() { - return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} - -const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { - static char res[20]; - *res = 0; - - if (item->shortcut != 0) - sprintf(res, "%s%c%c", prefix, (_wm->hasBuiltInFonts() ? '^' : '\x11'), item->shortcut); - - return res; -} - -int Menu::calculateMenuWidth(MenuItem *menu) { - int maxWidth = 0; - for (uint i = 0; i < menu->subitems.size(); i++) { - MenuSubItem *item = menu->subitems[i]; - if (!item->text.empty()) { - Common::String text(item->text); - Common::String acceleratorText(getAcceleratorString(item, " ")); - if (!acceleratorText.empty()) { - text += acceleratorText; - } - - int width = _font->getStringWidth(text); - if (width > maxWidth) { - maxWidth = width; - } - } - } - return maxWidth; -} - -void Menu::calcMenuBounds(MenuItem *menu) { - // TODO: cache maxWidth - int maxWidth = calculateMenuWidth(menu); - int x1 = menu->bbox.left - 1; - int y1 = menu->bbox.bottom + 1; - int x2 = x1 + maxWidth + kMenuDropdownPadding * 2 - 4; - int y2 = y1 + menu->subitems.size() * kMenuDropdownItemHeight + 2; - - menu->subbbox.left = x1; - menu->subbbox.top = y1; - menu->subbbox.right = x2; - menu->subbbox.bottom = y2; -} - -static void drawPixelPlain(int x, int y, int color, void *data) { - Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; - - if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) - *((byte *)surface->getBasePtr(x, y)) = (byte)color; -} - -static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color) { - Graphics::drawRoundRect(rect, arc, color, true, drawPixelPlain, surface); -} - -bool Menu::draw(Graphics::ManagedSurface *g, bool forceRedraw) { - Common::Rect r(_bbox); - - if (!_contentIsDirty && !forceRedraw) - return false; - - _contentIsDirty = false; - - _screen.clear(kColorGreen); - - drawFilledRoundRect(&_screen, r, kDesktopArc, kColorWhite); - r.top = 7; - _screen.fillRect(r, kColorWhite); - r.top = kMenuHeight - 1; - r.bottom++; - _screen.fillRect(r, kColorGreen); - r.bottom--; - _screen.fillRect(r, kColorBlack); - - for (uint i = 0; i < _items.size(); i++) { - int color = kColorBlack; - MenuItem *it = _items[i]; - - if ((uint)_activeItem == i) { - Common::Rect hbox = it->bbox; - - hbox.left -= 1; - hbox.right += 3; - hbox.bottom += 1; - - _screen.fillRect(hbox, kColorBlack); - color = kColorWhite; - - if (!it->subitems.empty()) - renderSubmenu(it); - } - - _font->drawString(&_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_wm->hasBuiltInFonts() ? 2 : 1), it->bbox.width(), color); - } - - g->transBlitFrom(_screen, kColorGreen); - - g_system->copyRectToScreen(g->getPixels(), g->pitch, 0, 0, g->w, g->h); - - return true; -} - -void Menu::renderSubmenu(MenuItem *menu) { - Common::Rect *r = &menu->subbbox; - - if (r->width() == 0 || r->height() == 0) - return; - - _screen.fillRect(*r, kColorWhite); - _screen.frameRect(*r, kColorBlack); - _screen.vLine(r->right, r->top + 3, r->bottom + 1, kColorBlack); - _screen.vLine(r->right + 1, r->top + 3, r->bottom + 1, kColorBlack); - _screen.hLine(r->left + 3, r->bottom, r->right + 1, kColorBlack); - _screen.hLine(r->left + 3, r->bottom + 1, r->right + 1, kColorBlack); - - int x = r->left + kMenuDropdownPadding; - int y = r->top + 1; - for (uint i = 0; i < menu->subitems.size(); i++) { - Common::String text(menu->subitems[i]->text); - Common::String acceleratorText(getAcceleratorString(menu->subitems[i], "")); - int accelX = r->right - 25; - - int color = kColorBlack; - if (i == (uint)_activeSubItem && !text.empty() && menu->subitems[i]->enabled) { - color = kColorWhite; - Common::Rect trect(r->left, y - (_wm->hasBuiltInFonts() ? 1 : 0), r->right, y + _font->getFontHeight()); - - _screen.fillRect(trect, kColorBlack); - } - - if (!text.empty()) { - Graphics::ManagedSurface *s = &_screen; - int tx = x, ty = y; - - if (!menu->subitems[i]->enabled) { - s = &_tempSurface; - tx = 0; - ty = 0; - accelX -= x; - - _tempSurface.clear(kColorGreen); - } - - _font->drawString(s, text, tx, ty, r->width(), color); - - if (!acceleratorText.empty()) - _font->drawString(s, acceleratorText, accelX, ty, r->width(), color); - - if (!menu->subitems[i]->enabled) { - // I am lazy to extend drawString() with plotProc as a parameter, so - // fake it here - for (int ii = 0; ii < _tempSurface.h; ii++) { - const byte *src = (const byte *)_tempSurface.getBasePtr(0, ii); - byte *dst = (byte *)_screen.getBasePtr(x, y+ii); - byte pat = _wm->getPatterns()[kPatternCheckers2 - 1][ii % 8]; - for (int j = 0; j < r->width(); j++) { - if (*src != kColorGreen && (pat & (1 << (7 - (x + j) % 8)))) - *dst = *src; - src++; - dst++; - } - } - } - } else { // Delimiter - bool flip = r->left & 2; - byte *ptr = (byte *)_screen.getBasePtr(r->left + 1, y + kMenuDropdownItemHeight / 2); - for (int xx = r->left + 1; xx <= r->right - 1; xx++, ptr++) { - *ptr = flip ? kColorBlack : kColorWhite; - flip = !flip; - } - } - - y += kMenuDropdownItemHeight; - } - - _contentIsDirty = true; - //g_system->copyRectToScreen(_screen.getBasePtr(r->left, r->top), _screen.pitch, r->left, r->top, r->width() + 2, r->height() + 2); -} - -bool Menu::processEvent(Common::Event &event) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - return keyEvent(event); - case Common::EVENT_LBUTTONDOWN: - return mouseClick(event.mouse.x, event.mouse.y); - case Common::EVENT_LBUTTONUP: - return mouseRelease(event.mouse.x, event.mouse.y); - case Common::EVENT_MOUSEMOVE: - return mouseMove(event.mouse.x, event.mouse.y); - default: - return false; - } -} - -bool Menu::keyEvent(Common::Event &event) { - if (event.type != Common::EVENT_KEYDOWN) - return false; - - if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) { - if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { - return processMenuShortCut(event.kbd.flags, event.kbd.ascii); - } - } - - return false; -} - -bool Menu::mouseClick(int x, int y) { - if (_bbox.contains(x, y)) { - for (uint i = 0; i < _items.size(); i++) - if (_items[i]->bbox.contains(x, y)) { - if ((uint)_activeItem == i) - return false; - - if (_activeItem != -1) { // Restore background - Common::Rect r(_items[_activeItem]->subbbox); - r.right += 3; - r.bottom += 3; - - _wm->setFullRefresh(true); - } - - _activeItem = i; - _activeSubItem = -1; - _menuActivated = true; - - _contentIsDirty = true; - - return true; - } - } else if (_menuActivated && _items[_activeItem]->subbbox.contains(x, y)) { - MenuItem *it = _items[_activeItem]; - int numSubItem = (y - it->subbbox.top) / kMenuDropdownItemHeight; - - if (numSubItem != _activeSubItem) { - _activeSubItem = numSubItem; - - renderSubmenu(_items[_activeItem]); - _contentIsDirty = true; - } - } else if (_menuActivated && _activeItem != -1) { - _activeSubItem = -1; - - renderSubmenu(_items[_activeItem]); - _contentIsDirty = true; - } - - return false; -} - -bool Menu::mouseMove(int x, int y) { - if (_menuActivated) - if (mouseClick(x, y)) - return true; - - return false; -} - -bool Menu::mouseRelease(int x, int y) { - if (_menuActivated) { - _menuActivated = false; - - if (_activeItem != -1 && _activeSubItem != -1 && _items[_activeItem]->subitems[_activeSubItem]->enabled) - (*_ccallback)(_items[_activeItem]->subitems[_activeSubItem]->action, - _items[_activeItem]->subitems[_activeSubItem]->text, _cdata); - - _activeItem = -1; - _activeSubItem = -1; - - _wm->setFullRefresh(true); - - return true; - } - - return false; -} - -bool Menu::processMenuShortCut(byte flags, uint16 ascii) { - ascii = tolower(ascii); - - if (flags & (Common::KBD_CTRL | Common::KBD_META)) { - for (uint i = 0; i < _items.size(); i++) - for (uint j = 0; j < _items[i]->subitems.size(); j++) - if (_items[i]->subitems[j]->enabled && tolower(_items[i]->subitems[j]->shortcut) == ascii) { - (*_ccallback)(_items[i]->subitems[j]->action, _items[i]->subitems[j]->text, _cdata); - return true; - } - } - - return false; -} - -void Menu::enableCommand(int menunum, int action, bool state) { - for (uint i = 0; i < _items[menunum]->subitems.size(); i++) - if (_items[menunum]->subitems[i]->action == action) - _items[menunum]->subitems[i]->enabled = state; - - _contentIsDirty = true; -} - -void Menu::disableAllMenus() { - for (uint i = 1; i < _items.size(); i++) // Leave About menu on - for (uint j = 0; j < _items[i]->subitems.size(); j++) - _items[i]->subitems[j]->enabled = false; - - _contentIsDirty = true; -} - -} // End of namespace Wage diff --git a/engines/wage/macmenu.h b/engines/wage/macmenu.h deleted file mode 100644 index e73e4c48a9..0000000000 --- a/engines/wage/macmenu.h +++ /dev/null @@ -1,161 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef WAGE_MACMENU_H -#define WAGE_MACMENU_H - -namespace Wage { - -struct MenuItem; -struct MenuSubItem; - -enum { - kFontStyleBold = 1, - kFontStyleItalic = 2, - kFontStyleUnderline = 4, - kFontStyleOutline = 8, - kFontStyleShadow = 16, - kFontStyleCondensed = 32, - kFontStyleExtended = 64 -}; - -enum { - kMenuHighLevel = -1, - kMenuAbout = 0, - kMenuFile = 1, - kMenuEdit = 2, - kMenuCommands = 3, - kMenuWeapons = 4 -}; - -enum { - kMenuActionAbout, - kMenuActionNew, - kMenuActionOpen, - kMenuActionClose, - kMenuActionSave, - kMenuActionSaveAs, - kMenuActionRevert, - kMenuActionQuit, - - kMenuActionUndo, - kMenuActionCut, - kMenuActionCopy, - kMenuActionPaste, - kMenuActionClear, - - kMenuActionCommand -}; - -struct MenuData { - int menunum; - const char *title; - int action; - byte shortcut; - bool enabled; -}; - -class Menu : public BaseMacWindow { -public: - Menu(int id, const Common::Rect &bounds, MacWindowManager *wm); - ~Menu(); - - void setCommandsCallback(void (*callback)(int, Common::String &, void *), void *data) { _ccallback = callback; _cdata = data; } - - void addStaticMenus(const MenuData *data); - void calcDimensions(); - - int addMenuItem(const char *name); - void addMenuSubItem(int id, const char *text, int action, int style = 0, char shortcut = 0, bool enabled = true); - void createSubMenuFromString(int id, const char *string); - void clearSubMenu(int id); - - bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); - bool processEvent(Common::Event &event); - - void enableCommand(int menunum, int action, bool state); - void disableAllMenus(); - - void setActive(bool active) { _menuActivated = active; } - bool hasAllFocus() { return _menuActivated; } - - Common::Rect _bbox; - -private: - Graphics::ManagedSurface _screen; - Graphics::ManagedSurface _tempSurface; - -private: - const Graphics::Font *getMenuFont(); - const char *getAcceleratorString(MenuSubItem *item, const char *prefix); - int calculateMenuWidth(MenuItem *menu); - void calcMenuBounds(MenuItem *menu); - void renderSubmenu(MenuItem *menu); - - bool keyEvent(Common::Event &event); - bool mouseClick(int x, int y); - bool mouseRelease(int x, int y); - bool mouseMove(int x, int y); - - bool processMenuShortCut(byte flags, uint16 ascii); - - Common::Array<MenuItem *> _items; - - const Graphics::Font *_font; - - bool _menuActivated; - - int _activeItem; - int _activeSubItem; - - void (*_ccallback)(int action, Common::String &text, void *data); - void *_cdata; -}; - -} // End of namespace Wage - -#endif diff --git a/engines/wage/macwindow.cpp b/engines/wage/macwindow.cpp deleted file mode 100644 index db8ef38c39..0000000000 --- a/engines/wage/macwindow.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "graphics/font.h" -#include "graphics/primitives.h" -#include "common/events.h" - -#include "wage/macwindow.h" -#include "wage/macwindowmanager.h" - -namespace Wage { - -BaseMacWindow::BaseMacWindow(int id, bool editable, MacWindowManager *wm) : - _id(id), _editable(editable), _wm(wm) { - _callback = 0; - _dataPtr = 0; - - _contentIsDirty = true; - - _type = kWindowUnknown; -} - -MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm) : - BaseMacWindow(id, editable, wm), _scrollable(scrollable), _resizable(resizable) { - _active = false; - _borderIsDirty = true; - - _highlightedPart = kBorderNone; - - _scrollPos = _scrollSize = 0.0; - - _beingDragged = false; - _beingResized = false; - - _draggedX = _draggedY = 0; - - _type = kWindowWindow; -} - -MacWindow::~MacWindow() { -} - -const Graphics::Font *MacWindow::getTitleFont() { - return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} - -void MacWindow::setActive(bool active) { - if (active == _active) - return; - - _active = active; - _borderIsDirty = true; -} - -void MacWindow::resize(int w, int h) { - if (_surface.w == w && _surface.h == h) - return; - - _surface.free(); - _surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - _borderSurface.free(); - _borderSurface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - _composeSurface.free(); - _composeSurface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - - _dims.setWidth(w); - _dims.setHeight(h); - - updateInnerDims(); - - _contentIsDirty = true; - _borderIsDirty = true; -} - -void MacWindow::move(int x, int y) { - if (_dims.left == x && _dims.top == y) - return; - - _dims.moveTo(x, y); - updateInnerDims(); - - _contentIsDirty = true; -} - -void MacWindow::setDimensions(const Common::Rect &r) { - resize(r.width(), r.height()); - _dims.moveTo(r.left, r.top); - updateInnerDims(); - - _contentIsDirty = true; -} - -bool MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { - if (!_borderIsDirty && !_contentIsDirty && !forceRedraw) - return false; - - if (_borderIsDirty || forceRedraw) - drawBorder(); - - _contentIsDirty = false; - - // Compose - _composeSurface.blitFrom(_surface, Common::Rect(0, 0, _surface.w - 2, _surface.h - 2), Common::Point(2, 2)); - _composeSurface.transBlitFrom(_borderSurface, kColorGreen); - - g->transBlitFrom(_composeSurface, _composeSurface.getBounds(), Common::Point(_dims.left - 2, _dims.top - 2), kColorGreen2); - - return true; -} - -#define ARROW_W 12 -#define ARROW_H 6 -const int arrowPixels[ARROW_H][ARROW_W] = { - {0,0,0,0,0,1,1,0,0,0,0,0}, - {0,0,0,0,1,1,1,1,0,0,0,0}, - {0,0,0,1,1,1,1,1,1,0,0,0}, - {0,0,1,1,1,1,1,1,1,1,0,0}, - {0,1,1,1,1,1,1,1,1,1,1,0}, - {1,1,1,1,1,1,1,1,1,1,1,1}}; - -static void drawPixelInverted(int x, int y, int color, void *data) { - Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; - - if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) { - byte *p = (byte *)surface->getBasePtr(x, y); - - *p = *p == kColorWhite ? kColorBlack : kColorWhite; - } -} - -void MacWindow::updateInnerDims() { - _innerDims = _dims; - _innerDims.grow(-kBorderWidth); -} - -void MacWindow::drawBorder() { - _borderIsDirty = false; - - bool active = _active, scrollable = _scrollable, closeable = _active, drawTitle = !_title.empty(); - const int size = kBorderWidth; - int x = 0; - int y = 0; - int width = _borderSurface.w; - int height = _borderSurface.h; - Graphics::ManagedSurface *g = &_borderSurface; - - // We draw rect with outer kColorGreen2 and inner kColorGreen, so on 2 passes we cut out - // scene by external shape of the border - int sz = kBorderWidth / 2; - g->clear(kColorGreen2); - g->fillRect(Common::Rect(sz, sz, width - sz, height - sz), kColorGreen); - - drawBox(g, x, y, size, size); - drawBox(g, x + width - size - 1, y, size, size); - drawBox(g, x + width - size - 1, y + height - size - 1, size, size); - drawBox(g, x, y + height - size - 1, size, size); - drawBox(g, x + size, y + 2, width - 2 * size - 1, size - 4); - drawBox(g, x + size, y + height - size + 1, width - 2 * size - 1, size - 4); - drawBox(g, x + 2, y + size, size - 4, height - 2 * size - 1); - drawBox(g, x + width - size + 1, y + size, size - 4, height - 2 * size - 1); - - if (active) { - fillRect(g, x + size, y + 5, width - 2 * size - 1, 8, kColorBlack); - fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8, kColorBlack); - fillRect(g, x + 5, y + size, 8, height - 2 * size - 1, kColorBlack); - if (!scrollable) { - fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1, kColorBlack); - } else { - int x1 = x + width - 15; - int y1 = y + size + 1; - - for (int yy = 0; yy < ARROW_H; yy++) { - for (int xx = 0; xx < ARROW_W; xx++) - g->hLine(x1 + xx, y1 + yy, x1 + xx, (arrowPixels[yy][xx] != 0 ? kColorBlack : kColorWhite)); - } - - fillRect(g, x + width - 13, y + size + ARROW_H, 8, height - 2 * size - 1 - ARROW_H * 2, kColorBlack); - - y1 += height - 2 * size - ARROW_H - 2; - for (int yy = 0; yy < ARROW_H; yy++) { - for (int xx = 0; xx < ARROW_W; xx++) - g->hLine(x1 + xx, y1 + yy, x1 + xx, (arrowPixels[ARROW_H - yy - 1][xx] != 0 ? kColorBlack : kColorWhite)); - } - - if (_highlightedPart == kBorderScrollUp || _highlightedPart == kBorderScrollDown) { - int rx1 = x + width - kBorderWidth + 2; - int ry1 = y + size + _dims.height() * _scrollPos; - int rx2 = rx1 + size - 4; - int ry2 = ry1 + _dims.height() * _scrollSize; - Common::Rect rr(rx1, ry1, rx2, ry2); - - Graphics::drawFilledRect(rr, kColorBlack, drawPixelInverted, g); - } - } - if (closeable) { - if (_highlightedPart == kBorderCloseButton) { - fillRect(g, x + 6, y + 6, 6, 6, kColorBlack); - } else { - drawBox(g, x + 5, y + 5, 7, 7); - } - } - } - - if (drawTitle) { - const Graphics::Font *font = getTitleFont(); - int yOff = _wm->hasBuiltInFonts() ? 3 : 1; - - int w = font->getStringWidth(_title) + 10; - int maxWidth = width - size * 2 - 7; - if (w > maxWidth) - w = maxWidth; - drawBox(g, x + (width - w) / 2, y, w, size); - font->drawString(g, _title, x + (width - w) / 2 + 5, y + yOff, w, kColorBlack); - } -} - -void MacWindow::setHighlight(WindowClick highlightedPart) { - if (_highlightedPart == highlightedPart) - return; - - _highlightedPart = highlightedPart; - _borderIsDirty = true; -} - -void MacWindow::setScroll(float scrollPos, float scrollSize) { - if (_scrollPos == scrollPos && _scrollSize == scrollSize) - return; - - _scrollPos = scrollPos; - _scrollSize = scrollSize; - _borderIsDirty = true; -} - - -void MacWindow::drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h) { - Common::Rect r(x, y, x + w + 1, y + h + 1); - - g->fillRect(r, kColorWhite); - g->frameRect(r, kColorBlack); -} - -void MacWindow::fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color) { - Common::Rect r(x, y, x + w, y + h); - - g->fillRect(r, color); -} - -WindowClick MacWindow::isInBorder(int x, int y) { - if (_innerDims.contains(x, y)) - return kBorderInner; - - if (x >= _innerDims.left - kBorderWidth && x < _innerDims.left && y >= _innerDims.top - kBorderWidth && y < _innerDims.top) - return kBorderCloseButton; - - if (_resizable) - if (x >= _innerDims.right && x < _innerDims.right + kBorderWidth && y >= _innerDims.bottom && y < _innerDims.bottom + kBorderWidth) - return kBorderResizeButton; - - if (_scrollable && x >= _innerDims.right && x < _innerDims.right + kBorderWidth) { - if (y < _innerDims.top - kBorderWidth) - return kBorderBorder; - - if (y >= _innerDims.bottom + kBorderWidth) - return kBorderBorder; - - if (y >= _innerDims.top + _innerDims.height() / 2) - return kBorderScrollDown; - - return kBorderScrollUp; - } - - return kBorderBorder; -} - -bool MacWindow::processEvent(Common::Event &event) { - WindowClick click = isInBorder(event.mouse.x, event.mouse.y); - - switch (event.type) { - case Common::EVENT_MOUSEMOVE: - if (_beingDragged) { - _dims.translate(event.mouse.x - _draggedX, event.mouse.y - _draggedY); - updateInnerDims(); - - _draggedX = event.mouse.x; - _draggedY = event.mouse.y; - - _wm->setFullRefresh(true); - } - - if (_beingResized) { - resize(MAX(kBorderWidth * 4, _dims.width() + event.mouse.x - _draggedX), - MAX(kBorderWidth * 4, _dims.height() + event.mouse.y - _draggedY)); - - _draggedX = event.mouse.x; - _draggedY = event.mouse.y; - - _wm->setFullRefresh(true); - (*_callback)(click, event, _dataPtr); - } - break; - case Common::EVENT_LBUTTONDOWN: - setHighlight(click); - - if (click == kBorderBorder) { - _beingDragged = true; - - _draggedX = event.mouse.x; - _draggedY = event.mouse.y; - } - - if (click == kBorderResizeButton) { - _beingResized = true; - - _draggedX = event.mouse.x; - _draggedY = event.mouse.y; - } - - break; - case Common::EVENT_LBUTTONUP: - _beingDragged = false; - _beingResized = false; - - setHighlight(kBorderNone); - break; - default: - return false; - } - - return (*_callback)(click, event, _dataPtr); -} - -} // End of namespace Wage diff --git a/engines/wage/macwindow.h b/engines/wage/macwindow.h deleted file mode 100644 index 4c6e9efeff..0000000000 --- a/engines/wage/macwindow.h +++ /dev/null @@ -1,161 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef WAGE_MACWINDOW_H -#define WAGE_MACWINDOW_H - -#include "graphics/managed_surface.h" - -namespace Wage { - -class MacWindowManager; - -enum WindowType { - kWindowUnknown, - kWindowWindow, - kWindowMenu -}; - -enum { - kBorderWidth = 17 -}; - -enum WindowClick { - kBorderNone = 0, - kBorderScrollUp, - kBorderScrollDown, - kBorderCloseButton, - kBorderInner, - kBorderBorder, - kBorderResizeButton -}; - -class BaseMacWindow { -public: - BaseMacWindow(int id, bool editable, MacWindowManager *wm); - virtual ~BaseMacWindow() {} - - const Common::Rect &getDimensions() { return _dims; } - int getId() { return _id; } - WindowType getType() { return _type; } - bool isEditable() { return _editable; } - Graphics::ManagedSurface *getSurface() { return &_surface; } - virtual void setActive(bool active) = 0; - void setDirty(bool dirty) { _contentIsDirty = dirty; } - - virtual bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false) = 0; - virtual bool processEvent(Common::Event &event) = 0; - - virtual bool hasAllFocus() = 0; - - void setCallback(bool (*callback)(WindowClick, Common::Event &, void *), void *data) { _callback = callback; _dataPtr = data; } - -protected: - int _id; - WindowType _type; - - bool _editable; - - Graphics::ManagedSurface _surface; - bool _contentIsDirty; - - Common::Rect _dims; - - bool (*_callback)(WindowClick, Common::Event &, void *); - void *_dataPtr; - - MacWindowManager *_wm; -}; - -class MacWindow : public BaseMacWindow { -public: - MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm); - virtual ~MacWindow(); - void move(int x, int y); - void resize(int w, int h); - void setDimensions(const Common::Rect &r); - const Common::Rect &getInnerDimensions() { return _innerDims; } - - bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); - - void setActive(bool active); - void setTitle(Common::String &title) { _title = title; } - void setHighlight(WindowClick highlightedPart); - void setScroll(float scrollPos, float scrollSize); - bool processEvent(Common::Event &event); - bool hasAllFocus() { return _beingDragged || _beingResized; } - -private: - void drawBorder(); - void drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h); - void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color); - const Graphics::Font *getTitleFont(); - void updateInnerDims(); - WindowClick isInBorder(int x, int y); - -private: - Graphics::ManagedSurface _borderSurface; - Graphics::ManagedSurface _composeSurface; - bool _scrollable; - bool _resizable; - bool _active; - bool _borderIsDirty; - - bool _beingDragged, _beingResized; - int _draggedX, _draggedY; - - WindowClick _highlightedPart; - float _scrollPos, _scrollSize; - - Common::Rect _innerDims; - - Common::String _title; -}; - -} // End of namespace Wage - -#endif diff --git a/engines/wage/macwindowmanager.cpp b/engines/wage/macwindowmanager.cpp deleted file mode 100644 index 6ca2efd7c9..0000000000 --- a/engines/wage/macwindowmanager.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "common/array.h" -#include "common/events.h" -#include "common/list.h" -#include "common/unzip.h" -#include "common/system.h" -#include "common/stream.h" - -#include "graphics/cursorman.h" -#include "graphics/fonts/bdf.h" -#include "graphics/managed_surface.h" -#include "graphics/palette.h" -#include "graphics/primitives.h" - -#include "wage/macwindowmanager.h" -#include "wage/macwindow.h" -#include "wage/macmenu.h" - -namespace Wage { - -static const byte palette[] = { - 0, 0, 0, // Black - 0x80, 0x80, 0x80, // Gray - 0xff, 0xff, 0xff, // White - 0x00, 0xff, 0x00, // Green - 0x00, 0xcf, 0x00 // Green2 -}; - -static byte fillPatterns[][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // kPatternSolid - { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, // kPatternStripes - { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }, // kPatternCheckers - { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa } // kPatternCheckers2 -}; - -static const byte macCursorArrow[] = { - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, - 2, 0, 0, 0, 2, 3, 3, 3, 3, 3, 3, - 2, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3, - 2, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3, - 2, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, - 2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, - 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, - 2, 0, 0, 2, 0, 0, 2, 3, 3, 3, 3, - 2, 0, 2, 3, 2, 0, 0, 2, 3, 3, 3, - 2, 2, 3, 3, 2, 0, 0, 2, 3, 3, 3, - 2, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, - 3, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3 -}; - -static const byte macCursorBeam[] = { - 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, - 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, - 0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, -}; - -MacWindowManager::MacWindowManager() { - _screen = 0; - _lastId = 0; - _activeWindow = -1; - - _menu = 0; - - _fullRefresh = true; - - _builtInFonts = true; - - for (int i = 0; i < ARRAYSIZE(fillPatterns); i++) - _patterns.push_back(fillPatterns[i]); - - loadFonts(); - - g_system->getPaletteManager()->setPalette(palette, 0, ARRAYSIZE(palette) / 3); - - CursorMan.replaceCursorPalette(palette, 0, ARRAYSIZE(palette) / 3); - CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); - _cursorIsArrow = true; - CursorMan.showMouse(true); -} - -MacWindowManager::~MacWindowManager() { - for (int i = 0; i < _lastId; i++) - delete _windows[i]; -} - -MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable, bool editable) { - MacWindow *w = new MacWindow(_lastId, scrollable, resizable, editable, this); - - _windows.push_back(w); - _windowStack.push_back(w); - - setActive(_lastId); - - _lastId++; - - return w; -} - -Menu *MacWindowManager::addMenu() { - _menu = new Menu(_lastId, _screen->getBounds(), this); - - _windows.push_back(_menu); - - _lastId++; - - return _menu; -} - -void MacWindowManager::setActive(int id) { - if (_activeWindow == id) - return; - - if (_activeWindow != -1) - _windows[_activeWindow]->setActive(false); - - _activeWindow = id; - - _windows[id]->setActive(true); - - _windowStack.remove(_windows[id]); - _windowStack.push_back(_windows[id]); - - _fullRefresh = true; -} - -struct PlotData { - Graphics::ManagedSurface *surface; - Patterns *patterns; - uint fillType; - int thickness; - - PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t) : - surface(s), patterns(p), fillType(f), thickness(t) {} -}; - -static void drawPixel(int x, int y, int color, void *data) { - PlotData *p = (PlotData *)data; - - if (p->fillType > p->patterns->size()) - return; - - byte *pat = p->patterns->operator[](p->fillType - 1); - - if (p->thickness == 1) { - if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) { - uint xu = (uint)x; // for letting compiler optimize it - uint yu = (uint)y; - - *((byte *)p->surface->getBasePtr(xu, yu)) = - (pat[yu % 8] & (1 << (7 - xu % 8))) ? - color : kColorWhite; - } - } else { - int x1 = x; - int x2 = x1 + p->thickness; - int y1 = y; - int y2 = y1 + p->thickness; - - for (y = y1; y < y2; y++) - for (x = x1; x < x2; x++) - if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) { - uint xu = (uint)x; // for letting compiler optimize it - uint yu = (uint)y; - *((byte *)p->surface->getBasePtr(xu, yu)) = - (pat[yu % 8] & (1 << (7 - xu % 8))) ? - color : kColorWhite; - } - } -} - -void MacWindowManager::drawDesktop() { - Common::Rect r(_screen->getBounds()); - - PlotData pd(_screen, &_patterns, kPatternCheckers, 1); - - Graphics::drawRoundRect(r, kDesktopArc, kColorBlack, true, drawPixel, &pd); - - g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h); -} - -void MacWindowManager::draw() { - assert(_screen); - - if (_fullRefresh) - drawDesktop(); - - for (Common::List<BaseMacWindow *>::const_iterator it = _windowStack.begin(); it != _windowStack.end(); it++) { - BaseMacWindow *w = *it; - if (w->draw(_screen, _fullRefresh)) { - w->setDirty(false); - - Common::Rect clip(w->getDimensions().left - 2, w->getDimensions().top - 2, w->getDimensions().right - 2, w->getDimensions().bottom - 2); - clip.clip(_screen->getBounds()); - - g_system->copyRectToScreen(_screen->getBasePtr(clip.left, clip.top), _screen->pitch, clip.left, clip.top, clip.width(), clip.height()); - } - } - - // Menu is drawn on top of everything and always - if (_menu) - _menu->draw(_screen, _fullRefresh); - - _fullRefresh = false; -} - -bool MacWindowManager::processEvent(Common::Event &event) { - // Menu gets events first fir shortcuts and menu bar - if (_menu && _menu->processEvent(event)) - return true; - - if (event.type != Common::EVENT_MOUSEMOVE && event.type != Common::EVENT_LBUTTONDOWN && - event.type != Common::EVENT_LBUTTONUP) - return false; - - if (_windows[_activeWindow]->isEditable() && _windows[_activeWindow]->getType() == kWindowWindow && - ((MacWindow *)_windows[_activeWindow])->getInnerDimensions().contains(event.mouse.x, event.mouse.y)) { - if (_cursorIsArrow) { - CursorMan.replaceCursor(macCursorBeam, 11, 16, 3, 8, 3); - _cursorIsArrow = false; - } - } else { - if (_cursorIsArrow == false) { - CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); - _cursorIsArrow = true; - } - } - - for (Common::List<BaseMacWindow *>::const_iterator it = _windowStack.end(); it != _windowStack.begin();) { - it--; - BaseMacWindow *w = *it; - - if (w->hasAllFocus() || w->getDimensions().contains(event.mouse.x, event.mouse.y)) { - if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP) - setActive(w->getId()); - - return w->processEvent(event); - } - } - - return false; -} - -////////////////////// -// Font stuff -////////////////////// -void MacWindowManager::loadFonts() { - Common::Archive *dat; - - dat = Common::makeZipArchive("classicmacfonts.dat"); - - if (!dat) { - warning("Could not find classicmacfonts.dat. Falling back to built-in fonts"); - _builtInFonts = true; - - return; - } - - Common::ArchiveMemberList list; - dat->listMembers(list); - - for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { - Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); - - Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); - - delete stream; - - Common::String fontName = (*it)->getName(); - - // Trim the .bdf extension - for (int i = fontName.size() - 1; i >= 0; --i) { - if (fontName[i] == '.') { - while ((uint)i < fontName.size()) { - fontName.deleteLastChar(); - } - break; - } - } - - FontMan.assignFontToName(fontName, font); - - debug(2, " %s", fontName.c_str()); - } - - _builtInFonts = false; - - delete dat; -} - -const Graphics::Font *MacWindowManager::getFont(const char *name, Graphics::FontManager::FontUsage fallback) { - const Graphics::Font *font = 0; - - if (!_builtInFonts) { - font = FontMan.getFontByName(name); - - if (!font) - warning("Cannot load font %s", name); - } - - if (_builtInFonts || !font) - font = FontMan.getFontByUsage(fallback); - - return font; -} - -///////////////// -// Cursor stuff -///////////////// -void MacWindowManager::pushArrowCursor() { - CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3); -} - -void MacWindowManager::popCursor() { - CursorMan.popCursor(); -} - -} // End of namespace Wage diff --git a/engines/wage/macwindowmanager.h b/engines/wage/macwindowmanager.h deleted file mode 100644 index 13f85cddd4..0000000000 --- a/engines/wage/macwindowmanager.h +++ /dev/null @@ -1,141 +0,0 @@ -/* 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. - * - * MIT License: - * - * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef WAGE_MACWINDOWMANAGER_H -#define WAGE_MACWINDOWMANAGER_H - -#include "common/array.h" -#include "common/list.h" -#include "common/events.h" -#include "common/archive.h" - -#include "graphics/fontman.h" - -namespace Graphics { -class ManagedSurface; -} - -namespace Wage { - -enum { - kDesktopArc = 7 -}; - -enum { - kColorBlack = 0, - kColorGray = 1, - kColorWhite = 2, - kColorGreen = 3, - kColorGreen2 = 4 -}; - -enum { - kPatternSolid = 1, - kPatternStripes = 2, - kPatternCheckers = 3, - kPatternCheckers2 = 4 -}; - -class BaseMacWindow; -class MacWindow; -class Menu; - -typedef Common::Array<byte *> Patterns; - -class MacWindowManager { -public: - MacWindowManager(); - ~MacWindowManager(); - - void setScreen(Graphics::ManagedSurface *screen) { _screen = screen; } - bool hasBuiltInFonts() { return _builtInFonts; } - const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback); - - MacWindow *addWindow(bool scrollable, bool resizable, bool editable); - Menu *addMenu(); - void setActive(int id); - - void setFullRefresh(bool redraw) { _fullRefresh = true; } - - void draw(); - - bool processEvent(Common::Event &event); - - BaseMacWindow *getWindow(int id) { return _windows[id]; } - - Patterns &getPatterns() { return _patterns; } - void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color); - - void pushArrowCursor(); - void popCursor(); - -private: - void drawDesktop(); - void loadFonts(); - -private: - Graphics::ManagedSurface *_screen; - - Common::List<BaseMacWindow *> _windowStack; - Common::Array<BaseMacWindow *> _windows; - - int _lastId; - int _activeWindow; - - bool _fullRefresh; - - Patterns _patterns; - - Menu *_menu; - - bool _builtInFonts; - bool _cursorIsArrow; -}; - -} // End of namespace Wage - -#endif diff --git a/engines/wage/module.mk b/engines/wage/module.mk index e150d5f27e..be148dd439 100644 --- a/engines/wage/module.mk +++ b/engines/wage/module.mk @@ -9,10 +9,8 @@ MODULE_OBJS := \ entities.o \ gui.o \ gui-console.o \ - macmenu.o \ - macwindow.o \ - macwindowmanager.o \ randomhat.o \ + saveload.o \ script.o \ sound.o \ util.o \ diff --git a/engines/wage/saveload.cpp b/engines/wage/saveload.cpp new file mode 100644 index 0000000000..da10ad41c1 --- /dev/null +++ b/engines/wage/saveload.cpp @@ -0,0 +1,776 @@ +/* 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. + * + * MIT License: + * + * Copyright (c) 2009 Alexei Svitkine, Eugene Sandulenko + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "common/file.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/config-manager.h" +#include "common/savefile.h" +#include "common/system.h" +#include "common/textconsole.h" +#include "common/translation.h" + +#include "gui/saveload.h" + +#include "graphics/thumbnail.h" +#include "graphics/surface.h" + +#include "wage/wage.h" +#include "wage/world.h" +#include "wage/entities.h" + +#define SAVEGAME_CURRENT_VERSION 1 + +// +// Original saves format is supported. +// ScummVM adds flags, description and thumbnail +// in the end of the file (shouldn't make saves incompatible). +// +// Version 0 (original/ScummVM): first ScummVM version +// + +namespace Wage { + +static const uint32 WAGEflag = MKTAG('W', 'A', 'G', 'E'); + +//TODO: make sure these are calculated right: (we add flag, description, etc) +#define VARS_INDEX 0x005E +#define SCENES_INDEX 0x0232 + +#define SCENE_SIZE 0x0010 +#define CHR_SIZE 0x0016 +#define OBJ_SIZE 0x0010 + +#define GET_HEX_OFFSET(ptr, baseOffset, entrySize) ((ptr) == nullptr ? -1 : ((baseOffset) + (entrySize) * (ptr)->_index)) +#define GET_HEX_CHR_OFFSET(ptr) GET_HEX_OFFSET((ptr), chrsHexOffset, CHR_SIZE) +#define GET_HEX_OBJ_OFFSET(ptr) GET_HEX_OFFSET((ptr), objsHexOffset, OBJ_SIZE) +#define GET_HEX_SCENE_OFFSET(ptr) ((ptr) == nullptr ? -1 : \ + ((ptr) == _world->_storageScene ? 0 : (SCENES_INDEX + getSceneIndex(_world->_player->_currentScene) * SCENE_SIZE))) + +int WageEngine::getSceneIndex(Scene *scene) const { + assert(scene); + Common::Array<Scene *> &orderedScenes = _world->_orderedScenes; + for (uint32 i = 0; i < orderedScenes.size(); ++i) { + if (orderedScenes[i] == scene) return i-1; + } + + warning("Scene's index not found"); + return -1; +} + +Obj *WageEngine::getObjByOffset(int offset, int objBaseOffset) const { + int objIndex = -1; + + if (offset != 0xFFFF) { + objIndex = (offset - objBaseOffset) / CHR_SIZE; + } + + if (objIndex >= 0 && (uint)objIndex < _world->_orderedObjs.size()) { + return _world->_orderedObjs[objIndex]; + } + + return nullptr; +} + +Chr *WageEngine::getChrById(int resId) const { + Common::Array<Chr *> &orderedChrs = _world->_orderedChrs; + for (uint32 i = 0; i < orderedChrs.size(); ++i) { + if (orderedChrs[i]->_resourceId == resId) + return orderedChrs[i]; + } + + return nullptr; +} + +Chr *WageEngine::getChrByOffset(int offset, int chrBaseOffset) const { + int chrIndex = -1; + + if (offset != 0xFFFF) { + chrIndex = (offset - chrBaseOffset) / CHR_SIZE; + } + + if (chrIndex >= 0 && (uint)chrIndex < _world->_orderedChrs.size()) { + return _world->_orderedChrs[chrIndex]; + } + + return nullptr; +} + +Scene *WageEngine::getSceneById(int resId) const { + Common::Array<Scene *> &orderedScenes = _world->_orderedScenes; + for (uint32 i = 0; i < orderedScenes.size(); ++i) { + if (orderedScenes[i]->_resourceId == resId) + return orderedScenes[i]; + } + + return nullptr; +} + +Scene *WageEngine::getSceneByOffset(int offset) const { + int sceneIndex = -1; + + if (offset != 0xFFFF) { + if (offset == 0) + sceneIndex = 0; + else + sceneIndex = 1 + (offset - SCENES_INDEX) / SCENE_SIZE; + } + + if (sceneIndex >= 0 && (uint)sceneIndex < _world->_orderedScenes.size()) { + if (sceneIndex == 0) return _world->_storageScene; + return _world->_orderedScenes[sceneIndex]; + } + + return nullptr; +} + +int WageEngine::saveGame(const Common::String &fileName, const Common::String &descriptionString) { + Common::OutSaveFile *out; + int result = 0; + + debug(9, "WageEngine::saveGame(%s, %s)", fileName.c_str(), descriptionString.c_str()); + if (!(out = _saveFileMan->openForSaving(fileName))) { + warning("Can't create file '%s', game not saved", fileName.c_str()); + return -1; + } else { + debug(9, "Successfully opened %s for writing", fileName.c_str()); + } + + // Counters + out->writeSint16LE(_world->_scenes.size()); //numScenes + out->writeSint16LE(_world->_chrs.size()); //numChars + out->writeSint16LE(_world->_objs.size()); //numObjs + + // Hex Offsets + int chrsHexOffset = SCENES_INDEX + _world->_scenes.size() * SCENE_SIZE; //chrs start after scenes + int objsHexOffset = chrsHexOffset + _world->_chrs.size() * CHR_SIZE; //objs start after chrs + out->writeSint32LE(chrsHexOffset); + out->writeSint32LE(objsHexOffset); + + // Unique 8-byte World Signature + out->writeSint32LE(_world->_signature); //8-byte ints? seriously? (uses 4 bytes in java code too) + + Chr *player = _world->_player; + Context &playerContext = player->_context; + + // More Counters + out->writeSint32LE(playerContext._visits); //visitNum + out->writeSint32LE(_loopCount); //loopNum + out->writeSint32LE(playerContext._kills); //killNum + + // Hex offset to player character + out->writeSint32LE(GET_HEX_CHR_OFFSET(player)); //getPlayerHexOffset() == getHexOffsetForChr(player) + + // character in this scene? + out->writeSint32LE(GET_HEX_CHR_OFFSET(_monster)); //getPresCharHexOffset() == getHexOffsetForChr(monster) + + // Hex offset to current scene + out->writeSint32LE(GET_HEX_SCENE_OFFSET(player->_currentScene)); //getCurSceneHexOffset() + + // wearing a helmet? + out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::HEAD_ARMOR])); //helmetIndex + + // holding a shield? + out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::SHIELD_ARMOR])); //shieldIndex + + // wearing chest armor? + out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::BODY_ARMOR])); //chestArmIndex + + // wearing spiritual armor? + out->writeSint32LE(GET_HEX_OBJ_OFFSET(player->_armor[Chr::MAGIC_ARMOR])); //sprtArmIndex + + // TODO: + out->writeUint16LE(0xffff); // ???? - always FFFF + out->writeUint16LE(0xffff); // ???? - always FFFF + out->writeUint16LE(0xffff); // ???? - always FFFF + out->writeUint16LE(0xffff); // ???? - always FFFF + + // did a character just escape? + out->writeSint32LE(GET_HEX_CHR_OFFSET(_running)); //getRunCharHexOffset() == getHexOffsetForChr(running) + + // players experience points + out->writeSint32LE(playerContext._experience); + + out->writeSint16LE(_aim); //aim + out->writeSint16LE(_opponentAim); //opponentAim + + // TODO: + out->writeSint16LE(0x0000); // always 0 + out->writeSint16LE(0x0000); // always 0 + out->writeSint16LE(0x0000); // always 0 + + // Base character stats + out->writeByte(playerContext._statVariables[PHYS_STR_BAS]); //state.getBasePhysStr() + out->writeByte(playerContext._statVariables[PHYS_HIT_BAS]); //state.getBasePhysHp() + out->writeByte(playerContext._statVariables[PHYS_ARM_BAS]); //state.getBasePhysArm() + out->writeByte(playerContext._statVariables[PHYS_ACC_BAS]); //state.getBasePhysAcc() + out->writeByte(playerContext._statVariables[SPIR_STR_BAS]); //state.getBaseSprtStr() + out->writeByte(playerContext._statVariables[SPIR_HIT_BAS]); //state.getBaseSprtHp() + out->writeByte(playerContext._statVariables[SPIR_ARM_BAS]); //state.getBaseSprtArm() + out->writeByte(playerContext._statVariables[SPIR_ACC_BAS]); //state.getBaseSprtAcc() + out->writeByte(playerContext._statVariables[PHYS_SPE_BAS]); //state.getBaseRunSpeed() + + // TODO: + out->writeByte(0x0A); // ???? - always seems to be 0x0A + + // write user vars + for (uint32 i = 0; i < 26 * 9; ++i) + out->writeSint16LE(playerContext._userVariables[i]); + + // write updated info for all scenes + Common::Array<Scene *> &orderedScenes = _world->_orderedScenes; + for (uint32 i = 0; i < orderedScenes.size(); ++i) { + Scene *scene = orderedScenes[i]; + if (scene != _world->_storageScene) { + out->writeSint16LE(scene->_resourceId); + out->writeSint16LE(scene->_worldY); + out->writeSint16LE(scene->_worldX); + out->writeByte(scene->_blocked[NORTH] ? 0x01 : 0x00); + out->writeByte(scene->_blocked[SOUTH] ? 0x01 : 0x00); + out->writeByte(scene->_blocked[EAST] ? 0x01 : 0x00); + out->writeByte(scene->_blocked[WEST] ? 0x01 : 0x00); + out->writeSint16LE(scene->_soundFrequency); + out->writeByte(scene->_soundType); + // the following two bytes are currently unknown + out->writeByte(0); + out->writeByte(0); + out->writeByte(scene->_visited ? 0x01 : 0x00); + } + } + + // write updated info for all characters + Common::Array<Chr *> &orderedChrs = _world->_orderedChrs; + for (uint32 i = 0; i < orderedChrs.size(); ++i) { + Chr *chr = orderedChrs[i]; + out->writeSint16LE(chr->_resourceId); + out->writeSint16LE(chr->_currentScene->_resourceId); + Context &chrContext = chr->_context; + out->writeByte(chrContext._statVariables[PHYS_STR_CUR]); + out->writeByte(chrContext._statVariables[PHYS_HIT_CUR]); + out->writeByte(chrContext._statVariables[PHYS_ARM_CUR]); + out->writeByte(chrContext._statVariables[PHYS_ACC_CUR]); + out->writeByte(chrContext._statVariables[SPIR_STR_CUR]); + out->writeByte(chrContext._statVariables[SPIR_HIT_CUR]); + out->writeByte(chrContext._statVariables[SPIR_ARM_CUR]); + out->writeByte(chrContext._statVariables[SPIR_ACC_CUR]); + out->writeByte(chrContext._statVariables[PHYS_SPE_CUR]); + out->writeByte(chr->_rejectsOffers); + out->writeByte(chr->_followsOpponent); + // bytes 16-20 are unknown + out->writeByte(0); + out->writeByte(0); + out->writeByte(0); + out->writeByte(0); + out->writeByte(0); + out->writeByte(chr->_weaponDamage1); + out->writeByte(chr->_weaponDamage2); + } + + // write updated info for all objects + Common::Array<Obj *> &orderedObjs = _world->_orderedObjs; + for (uint32 i = 0; i < orderedObjs.size(); ++i) { + Obj *obj = orderedObjs[i]; + Scene *location = obj->_currentScene; + Chr *owner = obj->_currentOwner; + + out->writeSint16LE(obj->_resourceId); + out->writeSint16LE(location == nullptr ? 0 : location->_resourceId); + out->writeSint16LE(owner == nullptr ? 0 : owner->_resourceId); + + // bytes 7-9 are unknown (always = 0) + out->writeByte(0); + out->writeByte(0); + out->writeByte(0); + + out->writeByte(obj->_accuracy); + out->writeByte(obj->_value); + out->writeByte(obj->_type); + out->writeByte(obj->_damage); + out->writeByte(obj->_attackType); + out->writeSint16LE(obj->_numberOfUses); + } + + // the following is appended by ScummVM + int32 appendixOffset = out->pos(); + if (appendixOffset < 0) { + warning("OutSaveFile::pos() failed"); + } + out->writeUint32BE(WAGEflag); + + // Write description of saved game, limited to WAGE_SAVEDGAME_DESCRIPTION_LEN characters + terminating NUL + const int WAGE_SAVEDGAME_DESCRIPTION_LEN = 127; + char description[WAGE_SAVEDGAME_DESCRIPTION_LEN + 1]; + + memset(description, 0, sizeof(description)); + strncpy(description, descriptionString.c_str(), WAGE_SAVEDGAME_DESCRIPTION_LEN); + assert(WAGE_SAVEDGAME_DESCRIPTION_LEN + 1 == 128); // safety + out->write(description, 128); + + out->writeByte(SAVEGAME_CURRENT_VERSION); + debug(9, "Writing save game version (%d)", SAVEGAME_CURRENT_VERSION); + + // Thumbnail + Graphics::saveThumbnail(*out); + + out->writeUint32BE(appendixOffset); + + // this one to make checking easier: + // it couldn't be added to the beginning + // and we won't be able to find it in the middle, + // so these would be the last 4 bytes of the file + out->writeUint32BE(WAGEflag); + + out->finalize(); + if (out->err()) { + warning("Can't write file '%s'. (Disk full?)", fileName.c_str()); + result = -1; + } else + debug(9, "Saved game %s in file %s", descriptionString.c_str(), fileName.c_str()); + + delete out; + return result; +} + +int WageEngine::loadGame(int slotId) { + Common::InSaveFile *data; + Common::String fileName = getSavegameFilename(slotId); + + debug(9, "WageEngine::loadGame(%d)", slotId); + if (!(data = _saveFileMan->openForLoading(fileName))) { + warning("Can't open file '%s', game not loaded", fileName.c_str()); + return -1; + } else { + debug(9, "Successfully opened %s for reading", fileName.c_str()); + } + + // Counters + int numScenes = data->readSint16LE(); + int numChars = data->readSint16LE(); + int numObjs = data->readSint16LE(); + + // Hex Offsets + int chrsHexOffset = data->readSint32LE(); + int objsHexOffset = data->readSint32LE(); + + // Unique 8-byte World Signature + int signature = data->readSint32LE(); + if (_world->_signature != signature) { + warning("This saved game is for a different world, please select another one"); + warning("World signature = %d, save signature = %d", _world->_signature, signature); + delete data; + return -1; + } + + // More Counters + int visitNum = data->readSint32LE(); //visitNum + int loopNum = data->readSint32LE(); //loopNum + int killNum = data->readSint32LE(); //killNum + + // Hex offset to player character + int playerOffset = data->readSint32LE(); + + // character in this scene? + int presCharOffset = data->readSint32LE(); + + // Hex offset to current scene + int currentSceneOffset = data->readSint32LE(); + + // find player and current scene + Chr *player = getChrByOffset(playerOffset, chrsHexOffset); + if (player == nullptr) { + warning("Invalid Character! Aborting load."); + delete data; + return -1; + } + + Scene *currentScene = getSceneByOffset(currentSceneOffset); + if (currentScene == nullptr) { + warning("Invalid Scene! Aborting load."); + delete data; + return -1; + } + + // set player character + _world->_player = player; + + // set current scene + player->_currentScene = currentScene; + + // clear the players inventory list + player->_inventory.clear(); + + // wearing a helmet? + int helmetOffset = data->readSint32LE(); //helmetIndex + + // holding a shield? + int shieldOffset = data->readSint32LE(); //shieldIndex + + // wearing chest armor? + int armorOffset = data->readSint32LE(); //chestArmIndex + + // wearing spiritual armor? + int spiritualArmorOffset = data->readSint32LE(); //sprtArmIndex + + data->readSint16LE(); // FFFF + data->readSint16LE(); // FFFF + data->readSint16LE(); // FFFF + data->readSint16LE(); // FFFF + + int runCharOffset = data->readSint32LE(); + + // players experience points + int exp = data->readSint32LE(); // @ playerContext._experience + + int aim = data->readSint16LE(); //aim + int opponentAim = data->readSint16LE(); //opponentAim + + data->readSint16LE(); // 0000 + data->readSint16LE(); // 0000 + data->readSint16LE(); // 0000 + + // Base character stats + int basePhysStr = data->readByte(); + int basePhysHp = data->readByte(); + int basePhysArm = data->readByte(); + int basePhysAcc = data->readByte(); + int baseSprtStr = data->readByte(); + int baseSprtHp = data->readByte(); + int baseSprtArm = data->readByte(); + int baseSprtAcc = data->readByte(); + int baseRunSpeed = data->readByte(); + + // set player stats + Context &playerContext = player->_context; + // I'm setting player fields also, because those are used as base values in Chr::resetState() + playerContext._statVariables[PHYS_STR_BAS] = player->_physicalStrength = basePhysStr; + playerContext._statVariables[PHYS_HIT_BAS] = player->_physicalHp = basePhysHp; + playerContext._statVariables[PHYS_ARM_BAS] = player->_naturalArmor = basePhysArm; + playerContext._statVariables[PHYS_ACC_BAS] = player->_physicalAccuracy = basePhysAcc; + playerContext._statVariables[SPIR_STR_BAS] = player->_spiritualStength = baseSprtStr; + playerContext._statVariables[SPIR_HIT_BAS] = player->_spiritialHp = baseSprtHp; + playerContext._statVariables[SPIR_ARM_BAS] = player->_resistanceToMagic = baseSprtArm; + playerContext._statVariables[SPIR_ACC_BAS] = player->_spiritualAccuracy = baseSprtAcc; + playerContext._statVariables[PHYS_SPE_BAS] = player->_runningSpeed = baseRunSpeed; + + // set visit# + playerContext._visits = visitNum; + + // set monsters killed + playerContext._kills = killNum; + + // set experience + playerContext._experience = exp; + + // if a character is present, move it to this scene + // TODO: This is done in the engine object, would it be cleaner + // to move it here? + // well, it's actually down there now, now sure if that's "cleaner" + // when it's up there or down there + + // if a character just ran away, let our engine know + // TODO: The current engine doesn't have a case for this, we + // should update it + // yep, I don't see such code anywhere in java, so not added it here + + data->readByte(); // 0x0A? + + // set all user variables + for (uint32 i = 0; i < 26 * 9; ++i) { + playerContext._userVariables[i] = data->readSint16LE(); + } + + // update all scene stats + Common::Array<Scene *> &orderedScenes = _world->_orderedScenes; + if ((uint)numScenes != orderedScenes.size()) { + warning("scenes number in file (%d) differs from the one in world (%d)", numScenes, orderedScenes.size()); + } + for (uint32 i = 0; i < orderedScenes.size(); ++i) { + Scene *scene = orderedScenes[i]; + if (scene == _world->_storageScene) { + scene->_chrs.clear(); + scene->_objs.clear(); + } else { + int id = data->readSint16LE(); + + if (scene->_resourceId != id) { + warning("loadGame(): updating scenes: expected %d but got %d", scene->_resourceId, id); + data->skip(14); //2,2,1,1,1,1,2,1,1,1,1 down there + continue; + } + + scene->_worldY = data->readSint16LE(); + scene->_worldX = data->readSint16LE(); + scene->_blocked[NORTH] = data->readByte() != 0; + scene->_blocked[SOUTH] = data->readByte() != 0; + scene->_blocked[EAST] = data->readByte() != 0; + scene->_blocked[WEST] = data->readByte() != 0; + scene->_soundFrequency = data->readSint16LE(); + scene->_soundType = data->readByte(); + // the following two bytes are currently unknown + data->readByte(); + data->readByte(); + scene->_visited = data->readByte() != 0; + } + } + + // update all char locations and stats + Common::Array<Chr *> &orderedChrs = _world->_orderedChrs; + if ((uint)numChars != orderedChrs.size()) { + warning("characters number in file (%d) differs from the one in world (%d)", numChars, orderedChrs.size()); + } + for (uint32 i = 0; i < orderedChrs.size(); ++i) { + int resourceId = data->readSint16LE(); + int sceneResourceId = data->readSint16LE(); + + int strength = data->readByte(); + int hp = data->readByte(); + int armor = data->readByte(); + int accuracy = data->readByte(); + int spirStrength = data->readByte(); + int spirHp = data->readByte(); + int spirArmor = data->readByte(); + int spirAccuracy = data->readByte(); + int speed = data->readByte(); + int rejectsOffers = data->readByte(); + int followsOpponent = data->readByte(); + + // bytes 16-20 are unknown + data->readByte(); + data->readByte(); + data->readByte(); + data->readByte(); + data->readByte(); + + int weaponDamage1 = data->readByte(); + int weaponDamage2 = data->readByte(); + + Chr *chr = orderedChrs[i]; + if (chr->_resourceId != resourceId) { + warning("loadGame(): updating chrs: expected %d but got %d", chr->_resourceId, resourceId); + continue; + } + + chr->_currentScene = getSceneById(sceneResourceId); + Context &chrContext = chr->_context; + chrContext._statVariables[PHYS_STR_CUR] = strength; + chrContext._statVariables[PHYS_HIT_CUR] = hp; + chrContext._statVariables[PHYS_ARM_CUR] = armor; + chrContext._statVariables[PHYS_ACC_CUR] = accuracy; + chrContext._statVariables[SPIR_STR_CUR] = spirStrength; + chrContext._statVariables[SPIR_HIT_CUR] = spirHp; + chrContext._statVariables[SPIR_ARM_CUR] = spirArmor; + chrContext._statVariables[SPIR_ACC_CUR] = spirAccuracy; + chrContext._statVariables[PHYS_SPE_CUR] = speed; + chr->_rejectsOffers = rejectsOffers; + chr->_followsOpponent = followsOpponent; + chr->_weaponDamage1 = weaponDamage1; + chr->_weaponDamage2 = weaponDamage2; + } + + // update all object locations and stats + Common::Array<Obj *> &orderedObjs = _world->_orderedObjs; + if ((uint)numObjs != orderedObjs.size()) { + warning("objects number in file (%d) differs from the one in world (%d)", numObjs, orderedObjs.size()); + } + for (uint32 i = 0; i < orderedObjs.size(); ++i) { + int resourceId = data->readSint16LE(); + int locationResourceId = data->readSint16LE(); + int ownerResourceId = data->readSint16LE(); + + // bytes 7-9 are unknown (always = 0) + data->readByte(); + data->readByte(); + data->readByte(); + + int accuracy = data->readByte(); + int value = data->readByte(); + int type = data->readByte(); + int damage = data->readByte(); + int attackType= data->readByte(); + int numberOfUses = data->readSint16LE(); + + Obj *obj = orderedObjs[i]; + if (obj->_resourceId != resourceId) { + warning("loadGame(): updating objs: expected %d but got %d", obj->_resourceId, resourceId); + continue; + } + + if (ownerResourceId != 0) { + obj->setCurrentOwner(getChrById(ownerResourceId)); + if (obj->_currentOwner == nullptr) + warning("loadGame(): updating objs: owner not found - char with id %d", ownerResourceId); + } else { + obj->setCurrentScene(getSceneById(locationResourceId)); + if (obj->_currentScene == nullptr) + warning("loadGame(): updating objs: scene with id %d not found", ownerResourceId); + } + + obj->_accuracy = accuracy; + obj->_value = value; + obj->_type = type; + obj->_damage = damage; + obj->_attackType = attackType; + obj->_numberOfUses = numberOfUses; + } + + // update inventories and scene contents + for (uint32 i = 0; i < orderedObjs.size(); ++i) { + Obj *obj = orderedObjs[i]; + Chr *chr = obj->_currentOwner; + if (chr != nullptr) { + chr->_inventory.push_back(obj); + } else { + Scene *scene = obj->_currentScene; + scene->_objs.push_back(obj); + } + } + + // update scene chrs + for (uint32 i = 0; i < orderedChrs.size(); ++i) { + Chr *chr = orderedChrs[i]; + Scene *scene = chr->_currentScene; + scene->_chrs.push_back(chr); + if (chr != player) { + wearObjs(chr); + } + } + + // move all worn helmets, shields, chest armors and spiritual + // armors to player + for (int type = 0; type < Chr::NUMBER_OF_ARMOR_TYPES; ++type) { + Obj *armor; + + if (type == Chr::HEAD_ARMOR) + armor = getObjByOffset(helmetOffset, objsHexOffset); + else if (type == Chr::SHIELD_ARMOR) + armor = getObjByOffset(shieldOffset, objsHexOffset); + else if (type == Chr::BODY_ARMOR) + armor = getObjByOffset(armorOffset, objsHexOffset); + else + armor = getObjByOffset(spiritualArmorOffset, objsHexOffset); + + if (armor != nullptr) { + _world->move(armor, player); + player->_armor[type] = armor; + } + } + + //TODO: make sure that armor in the inventory gets put on if we are wearing it + + _loopCount = loopNum; + + // let the engine know if there is a npc in the current scene + if (presCharOffset != 0xffff) { + _monster = getChrByOffset(presCharOffset, chrsHexOffset); + } + + // java engine calls clearOutput(); here + // processTurn("look", NULL); called in Wage right after this loadGame() + + // TODO: as you may see, aim, opponentAim or runCharOffset are not used anywhere + // I'm fixing the first two, as those are clearly not even mentioned anywhere + // the runCharOffset is mentioned up there as "not implemented case" + _aim = aim; + _opponentAim = opponentAim; + + delete data; + return 0; +} + +Common::String WageEngine::getSavegameFilename(int16 slotId) const { + Common::String saveLoadSlot = _targetName; + saveLoadSlot += Common::String::format(".%.3d", slotId); + return saveLoadSlot; +} + +Common::Error WageEngine::loadGameState(int slot) { + if (loadGame(slot) == 0) + return Common::kNoError; + else + return Common::kUnknownError; +} + +Common::Error WageEngine::saveGameState(int slot, const Common::String &description) { + Common::String saveLoadSlot = getSavegameFilename(slot); + if (saveGame(saveLoadSlot, description) == 0) + return Common::kNoError; + else + return Common::kUnknownError; +} + +bool WageEngine::scummVMSaveLoadDialog(bool isSave) { + if (!isSave) { + // do loading + GUI::SaveLoadChooser dialog = GUI::SaveLoadChooser(_("Load game:"), _("Load"), false); + int slot = dialog.runModalWithCurrentTarget(); + + if (slot < 0) + return true; + + return loadGameState(slot).getCode() == Common::kNoError; + } + + // do saving + GUI::SaveLoadChooser dialog = GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + int slot = dialog.runModalWithCurrentTarget(); + Common::String desc = dialog.getResultString(); + + if (desc.empty()) { + // create our own description for the saved game, the user didnt enter it + desc = dialog.createDefaultSaveDescription(slot); + } + + if (desc.size() > 28) + desc = Common::String(desc.c_str(), 28); + + if (slot < 0) + return true; + + return saveGameState(slot, desc).getCode() == Common::kNoError; +} + +} // End of namespace Agi diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp index 567e2768d8..6a33efa02a 100644 --- a/engines/wage/wage.cpp +++ b/engines/wage/wage.cpp @@ -45,6 +45,7 @@ * */ +#include "common/config-manager.h" #include "common/debug-channels.h" #include "common/error.h" #include "common/events.h" @@ -126,6 +127,12 @@ Common::Error WageEngine::run() { _temporarilyHidden = true; performInitialSetup(); + if (ConfMan.hasKey("save_slot")) { + int saveSlot = ConfMan.getInt("save_slot"); + loadGame(saveSlot); + _gui->regenCommandsMenu(); + _gui->regenWeaponsMenu(); + } Common::String input("look"); processTurn(&input, NULL); _temporarilyHidden = false; @@ -307,6 +314,11 @@ void WageEngine::performInitialSetup() { } } +void WageEngine::wearObjs(Chr* chr) { + if (chr != nullptr) + chr->wearObjs(); +} + void WageEngine::doClose() { warning("STUB: doClose()"); } diff --git a/engines/wage/wage.h b/engines/wage/wage.h index eb50a2e3dd..511a2d9e26 100644 --- a/engines/wage/wage.h +++ b/engines/wage/wage.h @@ -208,6 +208,23 @@ public: void redrawScene(); void saveGame(); + virtual Common::Error loadGameState(int slot); + virtual Common::Error saveGameState(int slot, const Common::String &description); + bool scummVMSaveLoadDialog(bool isSave); + +private: + int getSceneIndex(Scene *scene) const; + Obj *getObjByOffset(int offset, int objBaseOffset) const; + Chr *getChrById(int resId) const; + Chr *getChrByOffset(int offset, int chrBaseOffset) const; + Scene *getSceneById(int id) const; + Scene *getSceneByOffset(int offset) const; + int saveGame(const Common::String &fileName, const Common::String &descriptionString); + int loadGame(int slotId); + Common::String getSavegameFilename(int16 slotId) const; + +public: + virtual GUI::Debugger *getDebugger() { return _debugger; } private: diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp index 0e40e114b4..acc2a83d97 100644 --- a/engines/wage/world.cpp +++ b/engines/wage/world.cpp @@ -69,12 +69,13 @@ World::World(WageEngine *engine) { _globalScript = nullptr; _player = nullptr; + _signature = 0; _weaponMenuDisabled = true; _engine = engine; - _patterns = new Patterns; + _patterns = new Graphics::MacPatterns; } World::~World() { @@ -146,7 +147,8 @@ bool World::loadWorld(Common::MacResManager *resMan) { res = resMan->getResource(MKTAG('V','E','R','S'), resArray[0]); - res->skip(10); + _signature = res->readSint32LE(); + res->skip(6); byte b = res->readByte(); _weaponMenuDisabled = (b != 0); if (b != 0 && b != 1) @@ -215,6 +217,8 @@ bool World::loadWorld(Common::MacResManager *resMan) { delete res; } + + scene->_resourceId = *iter; addScene(scene); } @@ -224,7 +228,7 @@ bool World::loadWorld(Common::MacResManager *resMan) { for (iter = resArray.begin(); iter != resArray.end(); ++iter) { res = resMan->getResource(MKTAG('A','O','B','J'), *iter); - addObj(new Obj(resMan->getResName(MKTAG('A','O','B','J'), *iter), res)); + addObj(new Obj(resMan->getResName(MKTAG('A','O','B','J'), *iter), res, *iter)); } // Load Characters @@ -234,7 +238,7 @@ bool World::loadWorld(Common::MacResManager *resMan) { for (iter = resArray.begin(); iter != resArray.end(); ++iter) { res = resMan->getResource(MKTAG('A','C','H','R'), *iter); Chr *chr = new Chr(resMan->getResName(MKTAG('A','C','H','R'), *iter), res); - + chr->_resourceId = *iter; addChr(chr); // TODO: What if there's more than one player character? if (chr->_playerCharacter) diff --git a/engines/wage/world.h b/engines/wage/world.h index 468bedbc59..5c1aaf319e 100644 --- a/engines/wage/world.h +++ b/engines/wage/world.h @@ -48,10 +48,15 @@ #ifndef WAGE_WORLD_H #define WAGE_WORLD_H -#include "wage/macwindowmanager.h" +#include "wage/entities.h" +#include "graphics/macgui/macwindowmanager.h" namespace Wage { +// Import the enum definitions +using Graphics::MacPatterns; + +class Script; class Sound; class World { @@ -87,9 +92,10 @@ public: ObjArray _orderedObjs; ChrArray _orderedChrs; Common::Array<Sound *> _orderedSounds; - Patterns *_patterns; + Graphics::MacPatterns *_patterns; Scene *_storageScene; Chr *_player; + int _signature; //List<MoveListener> moveListeners; Common::String *_gameOverMessage; diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp index ce4c5fdda5..1af7e2b56d 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -71,7 +71,7 @@ #include "common/system.h" #include "common/file.h" -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED #include "engines/wintermute/base/scriptables/debuggable/debuggable_script_engine.h" #endif @@ -402,7 +402,7 @@ bool BaseGame::initialize1() { break; } -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED _scEngine = new DebuggableScEngine(this); #else _scEngine = new ScEngine(this); diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h index 409cc20ba4..6aacc1feab 100644 --- a/engines/wintermute/base/base_game.h +++ b/engines/wintermute/base/base_game.h @@ -36,7 +36,7 @@ #include "engines/wintermute/math/rect32.h" #include "engines/wintermute/debugger.h" #include "common/events.h" -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED #include "engines/wintermute/base/scriptables/debuggable/debuggable_script_engine.h" #endif @@ -152,7 +152,7 @@ public: BaseRenderer *_renderer; BaseSoundMgr *_soundMgr; -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED DebuggableScEngine *_scEngine; #else ScEngine *_scEngine; diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp index 7427a9b082..fd9dd6a2a5 100644 --- a/engines/wintermute/base/base_script_holder.cpp +++ b/engines/wintermute/base/base_script_holder.cpp @@ -466,7 +466,7 @@ void BaseScriptHolder::makeFreezable(bool freezable) { ScScript *BaseScriptHolder::invokeMethodThread(const char *methodName) { for (int i = _scripts.size() - 1; i >= 0; i--) { if (_scripts[i]->canHandleMethod(methodName)) { -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED DebuggableScEngine* debuggableEngine; debuggableEngine = dynamic_cast<DebuggableScEngine*>(_scripts[i]->_engine); // TODO: Not pretty diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp index 938ec031da..c13310255d 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -32,7 +32,7 @@ #include "engines/wintermute/base/scriptables/script_engine.h" #include "engines/wintermute/base/scriptables/script_stack.h" #include "common/memstream.h" -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED #include "engines/wintermute/base/scriptables/debuggable/debuggable_script.h" #endif namespace Wintermute { @@ -1320,7 +1320,7 @@ ScScript *ScScript::invokeEventHandler(const Common::String &eventName, bool unb if (!pos) { return nullptr; } -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED // TODO: Not pretty DebuggableScEngine* debuggableEngine; debuggableEngine = dynamic_cast<DebuggableScEngine*>(_engine); diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp index 26122094f1..8d957c6951 100644 --- a/engines/wintermute/base/scriptables/script_engine.cpp +++ b/engines/wintermute/base/scriptables/script_engine.cpp @@ -144,7 +144,7 @@ ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) { } // add new script -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED DebuggableScEngine* debuggableEngine; debuggableEngine = dynamic_cast<DebuggableScEngine*>(this); // TODO: Not pretty diff --git a/engines/wintermute/debugger.h b/engines/wintermute/debugger.h index e5008bee3b..6b1d2312ba 100644 --- a/engines/wintermute/debugger.h +++ b/engines/wintermute/debugger.h @@ -23,11 +23,11 @@ #ifndef WINTERMUTE_DEBUGGER_H #define WINTERMUTE_DEBUGGER_H -#define EXTENDED_DEBUGGER_ENABLED true +#define EXTENDED_DEBUGGER_ENABLED 1 #include "gui/debugger.h" -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED #include "engines/wintermute/base/scriptables/debuggable/debuggable_script.h" #else #include "engines/wintermute/base/scriptables/script.h" @@ -71,7 +71,7 @@ public: bool Cmd_ShowFps(int argc, const char **argv); bool Cmd_DumpFile(int argc, const char **argv); -#if EXTENDED_DEBUGGER_ENABLED == true +#if EXTENDED_DEBUGGER_ENABLED /** * Step - break again on next line */ |