aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/core
diff options
context:
space:
mode:
authorEugene Sandulenko2016-08-01 00:27:28 +0300
committerGitHub2016-08-01 00:27:28 +0300
commit9d3a2c1c7f9365f65908f583e62047830f60693d (patch)
treed7ba49593a1e3d79f17b350e700b1fbcf71f5b22 /engines/titanic/core
parent567054d8298a013f93dd9e0e332e2a08402b10a6 (diff)
parent19f8a0965be832a71a101054748cf000adf16add (diff)
downloadscummvm-rg350-9d3a2c1c7f9365f65908f583e62047830f60693d.tar.gz
scummvm-rg350-9d3a2c1c7f9365f65908f583e62047830f60693d.tar.bz2
scummvm-rg350-9d3a2c1c7f9365f65908f583e62047830f60693d.zip
Merge pull request #786 from dreammaster/titanic
TITANIC: Starship Titanic engine
Diffstat (limited to 'engines/titanic/core')
-rw-r--r--engines/titanic/core/background.cpp78
-rw-r--r--engines/titanic/core/background.h59
-rw-r--r--engines/titanic/core/click_responder.cpp43
-rw-r--r--engines/titanic/core/click_responder.h49
-rw-r--r--engines/titanic/core/dont_save_file_item.cpp37
-rw-r--r--engines/titanic/core/dont_save_file_item.h48
-rw-r--r--engines/titanic/core/drop_target.cpp72
-rw-r--r--engines/titanic/core/drop_target.h63
-rw-r--r--engines/titanic/core/file_item.cpp49
-rw-r--r--engines/titanic/core/file_item.h67
-rw-r--r--engines/titanic/core/game_object.cpp1510
-rw-r--r--engines/titanic/core/game_object.h861
-rw-r--r--engines/titanic/core/game_object_desc_item.cpp57
-rw-r--r--engines/titanic/core/game_object_desc_item.h56
-rw-r--r--engines/titanic/core/link_item.cpp176
-rw-r--r--engines/titanic/core/link_item.h100
-rw-r--r--engines/titanic/core/list.cpp35
-rw-r--r--engines/titanic/core/list.h164
-rw-r--r--engines/titanic/core/mail_man.cpp81
-rw-r--r--engines/titanic/core/mail_man.h84
-rw-r--r--engines/titanic/core/message_target.cpp50
-rw-r--r--engines/titanic/core/message_target.h104
-rw-r--r--engines/titanic/core/multi_drop_target.cpp43
-rw-r--r--engines/titanic/core/multi_drop_target.h51
-rw-r--r--engines/titanic/core/named_item.cpp92
-rw-r--r--engines/titanic/core/named_item.h84
-rw-r--r--engines/titanic/core/node_item.cpp56
-rw-r--r--engines/titanic/core/node_item.h52
-rw-r--r--engines/titanic/core/project_item.cpp549
-rw-r--r--engines/titanic/core/project_item.h234
-rw-r--r--engines/titanic/core/resource_key.cpp89
-rw-r--r--engines/titanic/core/resource_key.h81
-rw-r--r--engines/titanic/core/room_item.cpp198
-rw-r--r--engines/titanic/core/room_item.h84
-rw-r--r--engines/titanic/core/saveable_object.cpp1642
-rw-r--r--engines/titanic/core/saveable_object.h110
-rw-r--r--engines/titanic/core/static_image.cpp39
-rw-r--r--engines/titanic/core/static_image.h48
-rw-r--r--engines/titanic/core/tree_item.cpp275
-rw-r--r--engines/titanic/core/tree_item.h252
-rw-r--r--engines/titanic/core/turn_on_object.cpp59
-rw-r--r--engines/titanic/core/turn_on_object.h53
-rw-r--r--engines/titanic/core/turn_on_play_sound.cpp49
-rw-r--r--engines/titanic/core/turn_on_play_sound.h52
-rw-r--r--engines/titanic/core/turn_on_turn_off.cpp53
-rw-r--r--engines/titanic/core/turn_on_turn_off.h54
-rw-r--r--engines/titanic/core/view_item.cpp313
-rw-r--r--engines/titanic/core/view_item.h105
48 files changed, 8560 insertions, 0 deletions
diff --git a/engines/titanic/core/background.cpp b/engines/titanic/core/background.cpp
new file mode 100644
index 0000000000..f180df8867
--- /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(), _fieldBC(0), _fieldC0(0), _fieldDC(0) {
+}
+
+void CBackground::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(1, indent);
+ file->writeNumberLine(_fieldBC, indent);
+ file->writeNumberLine(_fieldC0, indent);
+ file->writeQuotedLine(_string1, indent);
+ file->writeQuotedLine(_string2, indent);
+ file->writeNumberLine(_fieldDC, indent);
+
+ CGameObject::save(file, indent);
+}
+
+void CBackground::load(SimpleFile *file) {
+ file->readNumber();
+ _fieldBC = file->readNumber();
+ _fieldC0 = file->readNumber();
+ _string1 = file->readString();
+ _string2 = file->readString();
+ _fieldDC = file->readNumber();
+
+ CGameObject::load(file);
+}
+
+bool CBackground::StatusChangeMsg(CStatusChangeMsg *msg) {
+ setVisible(true);
+ if (_fieldDC) {
+ playMovie(_fieldBC, _fieldC0, 16);
+ } else {
+ playMovie(_fieldBC, _fieldC0, 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..6a2fd21454
--- /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 _fieldBC;
+ int _fieldC0;
+ 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..f9694557df
--- /dev/null
+++ b/engines/titanic/core/click_responder.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/core/click_responder.h"
+
+namespace Titanic {
+
+void CClickResponder::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(1, indent);
+ file->writeQuotedLine(_string1, indent);
+ file->writeQuotedLine(_string2, indent);
+
+ CGameObject::save(file, indent);
+}
+
+void CClickResponder::load(SimpleFile *file) {
+ file->readNumber();
+ _string1 = file->readString();
+ _string2 = file->readString();
+
+ CGameObject::load(file);
+}
+
+} // 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..78381b9948
--- /dev/null
+++ b/engines/titanic/core/click_responder.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_CLICK_RESPONDER_H
+#define TITANIC_CLICK_RESPONDER_H
+
+#include "titanic/core/game_object.h"
+
+namespace Titanic {
+
+class CClickResponder : public CGameObject {
+protected:
+ CString _string1, _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_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..05ea6445c3
--- /dev/null
+++ b/engines/titanic/core/drop_target.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/core/drop_target.h"
+
+namespace Titanic {
+
+CDropTarget::CDropTarget() : CGameObject(), _fieldC4(0),
+ _fieldD4(0), _fieldE4(0), _fieldF4(0), _fieldF8(0),
+ _fieldFC(0), _field10C(1), _field110(8), _field114(20) {
+}
+
+void CDropTarget::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(1, indent);
+ file->writePoint(_pos1, indent);
+ file->writeNumberLine(_fieldC4, indent);
+ file->writeQuotedLine(_string1, indent);
+ file->writeNumberLine(_fieldD4, indent);
+ file->writeQuotedLine(_string2, indent);
+ file->writeNumberLine(_fieldE4, indent);
+ file->writeQuotedLine(_string3, indent);
+ file->writeNumberLine(_fieldF4, indent);
+ file->writeNumberLine(_fieldF8, indent);
+ file->writeNumberLine(_fieldFC, indent);
+ file->writeQuotedLine(_string4, indent);
+ file->writeNumberLine(_field10C, indent);
+ file->writeNumberLine(_field110, indent);
+ file->writeNumberLine(_field114, indent);
+
+ CGameObject::save(file, indent);
+}
+
+void CDropTarget::load(SimpleFile *file) {
+ file->readNumber();
+ _pos1 = file->readPoint();
+ _fieldC4 = file->readNumber();
+ _string1 = file->readString();
+ _fieldD4 = file->readNumber();
+ _string2 = file->readString();
+ _fieldE4 = file->readNumber();
+ _string3 = file->readString();
+ _fieldF4 = file->readNumber();
+ _fieldF8 = file->readNumber();
+ _fieldFC = file->readNumber();
+ _string4 = file->readString();
+ _field10C = file->readNumber();
+ _field110 = file->readNumber();
+ _field114 = file->readNumber();
+
+ CGameObject::load(file);
+}
+
+} // 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..4bd0ae448c
--- /dev/null
+++ b/engines/titanic/core/drop_target.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_DROP_TARGET_H
+#define TITANIC_DROP_TARGET_H
+
+#include "titanic/core/game_object.h"
+
+namespace Titanic {
+
+class CDropTarget : public CGameObject {
+private:
+ Point _pos1;
+ int _fieldC4;
+ CString _string1;
+ int _fieldD4;
+ CString _string2;
+ int _fieldE4;
+ CString _string3;
+ int _fieldF4;
+ int _fieldF8;
+ int _fieldFC;
+ CString _string4;
+ int _field10C;
+ int _field110;
+ int _field114;
+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..39e4f8412e
--- /dev/null
+++ b/engines/titanic/core/game_object.cpp
@@ -0,0 +1,1510 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along 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;
+
+void CGameObject::init() {
+ _credits = nullptr;
+}
+
+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::soundFn1(int handle) {
+ if (handle != 0 && handle != -1) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager)
+ return gameManager->_sound.fn1(handle);
+ }
+
+ return false;
+}
+
+void CGameObject::soundFn2(const CString &resName, int v1, int v2, int v3, int handleIndex) {
+ warning("TODO: CGameObject::soundFn2");
+}
+
+void CGameObject::soundFn3(int handle, int val2, int val3) {
+ if (handle != 0 && handle != -1) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager)
+ return gameManager->_sound.fn3(handle, val2, val3);
+ }
+}
+
+void CGameObject::soundFn4(int v1, int v2, int v3) {
+ warning("CGameObject::soundFn4");
+}
+
+void CGameObject::soundFn5(int v1, int v2, int v3) {
+ warning("CGameObject::soundFn5");
+}
+
+void CGameObject::sound8(bool flag) const {
+ getGameManager()->_sound.managerProc8(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 **names, uint flags) {
+ // Count size of array
+ int count = 0;
+ for (const char **p = names; *p; ++p)
+ ++count;
+
+ // Play clip
+ const char *name = names[g_vm->getRandomNumber(count - 1)];
+ playClip(name, flags);
+}
+
+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, int val2, int val3, int val4) {
+ CProximity prox;
+ prox._field8 = val2;
+ prox._fieldC = val3;
+ prox._field20 = val4;
+ return playSound(name, prox);
+}
+
+int CGameObject::playSound(const CString &name, CProximity &prox) {
+ if (prox._field28 == 2) {
+ // TODO
+ }
+
+ return 0;
+}
+
+void CGameObject::stopSound(int handle, int val2) {
+ if (handle != 0 && handle != -1) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ if (val2)
+ gameManager->_sound.fn3(handle, 0, val2);
+ else
+ gameManager->_sound.fn2(handle);
+ }
+ }
+}
+
+int CGameObject::addTimer(int endVal, uint firstDuration, uint repeatDuration) {
+ CTimeEventInfo *timer = new CTimeEventInfo(g_vm->_events->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(g_vm->_events->getTicksCount(),
+ repeatDuration != 0, firstDuration, repeatDuration, this, 0, CString());
+
+ getGameManager()->addTimer(timer);
+ return timer->_id;
+}
+
+void CGameObject::stopTimer(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();
+ view->addUnder(this);
+}
+
+void CGameObject::moveToView(const CString &name) {
+ CViewItem *view = parseView(name);
+ detach();
+ view->addUnder(this);
+}
+
+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::setTextBorder(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, 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));
+}
+
+bool CGameObject::isObjectDragging() const {
+ CTreeItem *item = getGameManager()->_dragItem;
+ return item ? static_cast<CGameObject *>(item) != nullptr : false;
+}
+
+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;
+}
+
+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::setMovie14(int v) {
+ if (!_surface && !_resource.empty()) {
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ if (_surface && _surface->_movie)
+ _surface->_movie->_field14 = v;
+}
+
+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::getTickCount() {
+ return g_vm->_events->getTicksCount();
+}
+
+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();
+}
+
+/*------------------------------------------------------------------------*/
+
+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::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);
+}
+
+int CGameObject::petGetRooms1D0() const {
+ CPetControl *petControl = getPetControl();
+ return petControl ? petControl->getRooms1D0() : 0;
+}
+
+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::petSetRooms1D0(int val) {
+ CPetControl *petControl = getPetControl();
+ if (petControl)
+ petControl->setRooms1D0(val);
+}
+
+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);
+}
+
+void CGameObject::starFn2() {
+ CStarControl *starControl = getStarControl();
+ if (starControl)
+ starControl->fn4();
+}
+
+/*------------------------------------------------------------------------*/
+
+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;
+}
+
+} // 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..69036b1690
--- /dev/null
+++ b/engines/titanic/core/game_object.h
@@ -0,0 +1,861 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along 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 "titanic/support/mouse_cursor.h"
+#include "titanic/support/credit_text.h"
+#include "titanic/support/movie_range_info.h"
+#include "titanic/support/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 CCreditText *_credits;
+private:
+ /**
+ * Load a visual resource for the object
+ */
+ void loadResource(const CString &name);
+
+ /**
+ * Loads a movie
+ */
+ void loadMovie(const CString &name, bool pendingFlag = true);
+
+ /**
+ * Loads an image
+ */
+ void loadImage(const CString &name, bool pendingFlag = true);
+
+ /**
+ * 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:
+ Rect _bounds;
+ 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);
+
+ 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
+ */
+ int playSound(const CString &name, int val2 = 100, int val3 = 0, int val4 = 0);
+
+ /**
+ * Plays a sound
+ */
+ int playSound(const CString &name, CProximity &prox);
+
+ /**
+ * Stop a sound
+ */
+ void stopSound(int handle, int val2 = 0);
+
+ bool soundFn1(int handle);
+
+ void soundFn2(const CString &resName, int v1, int v2, int v3, int handleIndex);
+
+ void soundFn3(int handle, int val2, int val3);
+
+ void soundFn4(int v1, int v2, int v3);
+
+ void soundFn5(int v1, int v2, int v3);
+
+ 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);
+
+ /**
+ * Stops a timer
+ */
+ void stopTimer(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);
+
+ /**
+ * Get the centre of the game object's bounds
+ */
+ Point getControid() const;
+
+ /**
+ * Play an arbitrary clip
+ */
+ void playClip(const CString &name, uint flags);
+
+ /**
+ * Play a clip
+ */
+ void playClip(uint startFrame, uint endFrame);
+
+ /**
+ * Play a clip randomly from a passed list of names
+ */
+ void playRandomClip(const char **names, uint flags);
+
+ /**
+ * 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;
+
+ /**
+ * 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);
+
+ void setMovie14(int v);
+
+ 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 getTickCount();
+
+ /**
+ * Adds an object to the mail list
+ */
+ void addMail(int mailId);
+
+ /**
+ * Sets the mail identifier for an object
+ */
+ void setMailId(int mailId);
+
+ /**
+ * 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;
+
+ /**
+ * Remove an object from the mail list
+ */
+ void removeMail(int id, int v);
+
+ /**
+ * 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();
+
+ void setState1C(bool flag);
+ void stateInc14();
+ int stateGet14() const;
+ void stateSet24();
+ int stateGet24() const;
+ void stateInc38();
+ int stateGet38() const;
+
+ /**
+ * Flag to quit the game
+ */
+ void quitGame();
+
+ /**
+ * Set the frame rate for the currently loaded movie
+ */
+ void setMovieFrameRate(double rate);
+
+ /**
+ * Set up the text borders for the object
+ */
+ void setTextBorder(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();
+public:
+ 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);
+
+ /**
+ * 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;
+
+ /**
+ * 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 true if an item being dragged is a game object
+ */
+ bool isObjectDragging() 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;
+
+ /**
+ * 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);
+
+ /**
+ * 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);
+
+ int petGetRooms1D0() 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();
+
+ void petSetRooms1D0(int val);
+ 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);
+ void 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();
+};
+
+} // 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..a52de591b3
--- /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; \
+ } \
+ static const int DUMMY = 0
+
+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..f2998199b1
--- /dev/null
+++ b/engines/titanic/core/multi_drop_target.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/core/multi_drop_target.h"
+
+namespace Titanic {
+
+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);
+}
+
+} // 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..c004b9bece
--- /dev/null
+++ b/engines/titanic/core/multi_drop_target.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_MULTI_DROP_TARGET_H
+#define TITANIC_MULTI_DROP_TARGET_H
+
+#include "titanic/core/drop_target.h"
+
+namespace Titanic {
+
+class CMultiDropTarget : public CDropTarget {
+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..6eafbf8c8b
--- /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);
+}
+
+int CNamedItem::compareTo(const CString &name, int maxLen) const {
+ if (maxLen) {
+ return getName().left(maxLen).compareToIgnoreCase(name);
+ } else {
+ return getName().compareToIgnoreCase(name);
+ }
+}
+
+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..809cda1156
--- /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; }
+
+ /**
+ * Compares the name of the item to a passed name
+ */
+ virtual int compareTo(const CString &name, int maxLen) 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..1de065a49d
--- /dev/null
+++ b/engines/titanic/core/node_item.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/node_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);
+}
+
+} // 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..8fda9464ec
--- /dev/null
+++ b/engines/titanic/core/node_item.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_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);
+};
+
+} // 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..62cee47045
--- /dev/null
+++ b/engines/titanic/core/saveable_object.cpp
@@ -0,0 +1,1642 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along 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/game/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/call_pellerator.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/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/game/parrot/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_item.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/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(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(CPlaceHolderItem);
+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(CBowlStateChange);
+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(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, CPlaceHolderItem);
+ ADDFN(CLemonOnBar, CPlaceHolderItem);
+ ADDFN(CPlaceHolderItem, CGameObject);
+ ADDFN(CTVOnBar, CPlaceHolderItem);
+ 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(CBowlStateChange, 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..6adbbe39fa
--- /dev/null
+++ b/engines/titanic/core/tree_item.cpp
@@ -0,0 +1,275 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along 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_item.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(CPlaceHolderItem::_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;
+}
+
+CNamedItem *CTreeItem::findByName(const CString &name, int maxLen) {
+ CString nameLower = name;
+ nameLower.toLowercase();
+
+ for (CTreeItem *treeItem = this; treeItem; treeItem = treeItem->scan(this)) {
+ CString nodeName = treeItem->getName();
+ nodeName.toLowercase();
+
+ if (maxLen) {
+ if (nodeName.left(maxLen).compareTo(nameLower))
+ return dynamic_cast<CNamedItem *>(treeItem);
+ } else {
+ if (!nodeName.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..db4ba30a44
--- /dev/null
+++ b/engines/titanic/core/tree_item.h
@@ -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.
+ *
+ */
+
+#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(); }
+
+ /**
+ * 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();
+
+ /**
+ * Finds a tree item by name
+ */
+ CNamedItem *findByName(const CString &name, int maxLen = 0);
+};
+
+} // 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..56069a9799
--- /dev/null
+++ b/engines/titanic/core/view_item.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/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;
+ _field28 = 0.0;
+ _viewNumber = 0;
+ _field50 = 0;
+ _field54 = 0;
+ setData(0.0);
+}
+
+void CViewItem::setData(double v) {
+ _field28 = v;
+ _field50 = cos(_field28) * 30.0;
+ _field54 = sin(_field28) * -30.0;
+}
+
+void CViewItem::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(1, indent);
+ _resourceKey.save(file, indent);
+ file->writeQuotedLine("V", indent);
+ file->writeFloatLine(_field28, 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();
+ setData(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 (msg->isButtonUpMsg()) {
+ 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::fn1(double val1, double val2, double val3) {
+ warning("TODO: CViewItem::fn1");
+}
+
+} // 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..6e8003d6c6
--- /dev/null
+++ b/engines/titanic/core/view_item.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_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:
+ void setData(double v);
+
+ /**
+ * 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;
+ double _field28;
+ CResourceKey _resourceKey;
+ int _field50;
+ int _field54;
+public:
+ int _viewNumber;
+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);
+
+ void fn1(double val1, double val2, double val3);
+};
+
+} // End of namespace Titanic
+
+#endif /* TITANIC_NAMED_ITEM_H */