aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/core/game_object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic/core/game_object.cpp')
-rw-r--r--engines/titanic/core/game_object.cpp1689
1 files changed, 1689 insertions, 0 deletions
diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp
new file mode 100644
index 0000000000..0289e78823
--- /dev/null
+++ b/engines/titanic/core/game_object.cpp
@@ -0,0 +1,1689 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/core/game_object.h"
+#include "titanic/core/mail_man.h"
+#include "titanic/core/resource_key.h"
+#include "titanic/core/room_item.h"
+#include "titanic/npcs/true_talk_npc.h"
+#include "titanic/pet_control/pet_control.h"
+#include "titanic/star_control/star_control.h"
+#include "titanic/support/files_manager.h"
+#include "titanic/support/screen_manager.h"
+#include "titanic/support/video_surface.h"
+#include "titanic/game_manager.h"
+#include "titanic/titanic.h"
+
+namespace Titanic {
+
+EMPTY_MESSAGE_MAP(CGameObject, CNamedItem);
+
+CCreditText *CGameObject::_credits;
+int CGameObject::_soundHandles[4];
+
+void CGameObject::init() {
+ _credits = nullptr;
+ _soundHandles[0] = _soundHandles[1] = 0;
+ _soundHandles[2] = _soundHandles[3] = -1;
+}
+
+void CGameObject::deinit() {
+ if (_credits) {
+ _credits->clear();
+ delete _credits;
+ _credits = nullptr;
+ }
+}
+
+CGameObject::CGameObject(): CNamedItem() {
+ _bounds = Rect(0, 0, 15, 15);
+ _field34 = 0;
+ _field38 = 0;
+ _field3C = 0;
+ _field40 = 0;
+ _field44 = 0xF0;
+ _field48 = 0xF0;
+ _field4C = 0xFF;
+ _isMail = false;
+ _id = 0;
+ _roomFlags = 0;
+ _visible = true;
+ _field60 = 0;
+ _cursorId = CURSOR_ARROW;
+ _initialFrame = 0;
+ _frameNumber = -1;
+ _text = nullptr;
+ _textBorder = _textBorderRight = 0;
+ _field9C = 0;
+ _surface = nullptr;
+ _fieldB8 = 0;
+}
+
+CGameObject::~CGameObject() {
+ delete _surface;
+ delete _text;
+}
+
+void CGameObject::save(SimpleFile *file, int indent) {
+ file->writeNumberLine(7, indent);
+ _movieRangeInfoList.destroyContents();
+
+ if (_surface) {
+ const CMovieRangeInfoList *rangeList = _surface->getMovieRangeInfo();
+
+ if (rangeList) {
+ for (CMovieRangeInfoList::const_iterator i = rangeList->begin();
+ i != rangeList->end(); ++i) {
+ CMovieRangeInfo *rangeInfo = new CMovieRangeInfo(*i);
+ rangeInfo->_initialFrame = (i == rangeList->begin()) ? getMovieFrame() : -1;
+ }
+ }
+ }
+
+ _movieRangeInfoList.save(file, indent);
+ _movieRangeInfoList.destroyContents();
+
+ file->writeNumberLine(getMovieFrame(), indent + 1);
+ file->writeNumberLine(_cursorId, indent + 1);
+ _movieClips.save(file, indent + 1);
+ file->writeNumberLine(_field60, indent + 1);
+ file->writeNumberLine(_field40, indent + 1);
+ file->writeQuotedLine(_resource, indent + 1);
+ file->writeBounds(_bounds, indent + 1);
+
+ file->writeFloatLine(_field34, indent + 1);
+ file->writeFloatLine(_field38, indent + 1);
+ file->writeFloatLine(_field3C, indent + 1);
+
+ file->writeNumberLine(_field44, indent + 1);
+ file->writeNumberLine(_field48, indent + 1);
+ file->writeNumberLine(_field4C, indent + 1);
+ file->writeNumberLine(_fieldB8, indent + 1);
+ file->writeNumberLine(_visible, indent + 1);
+ file->writeNumberLine(_isMail, indent + 1);
+ file->writeNumberLine(_id, indent + 1);
+ file->writeNumberLine(_roomFlags, indent + 1);
+
+ if (_surface) {
+ _surface->_resourceKey.save(file, indent);
+ } else {
+ CResourceKey resourceKey;
+ resourceKey.save(file, indent);
+ }
+ file->writeNumberLine(_surface != nullptr, indent);
+
+ CNamedItem::save(file, indent);
+}
+
+void CGameObject::load(SimpleFile *file) {
+ int val = file->readNumber();
+ CResourceKey resourceKey;
+
+ switch (val) {
+ case 7:
+ _movieRangeInfoList.load(file);
+ _frameNumber = file->readNumber();
+ // Deliberate fall-through
+
+ case 6:
+ _cursorId = (CursorId)file->readNumber();
+ // Deliberate fall-through
+
+ case 5:
+ _movieClips.load(file);
+ // Deliberate fall-through
+
+ case 4:
+ _field60 = file->readNumber();
+ // Deliberate fall-through
+
+ case 3:
+ _field40 = file->readNumber();
+ // Deliberate fall-through
+
+ case 2:
+ _resource = file->readString();
+ // Deliberate fall-through
+
+ case 1:
+ _bounds = file->readBounds();
+ _field34 = file->readFloat();
+ _field38 = file->readFloat();
+ _field3C = file->readFloat();
+ _field44 = file->readNumber();
+ _field48 = file->readNumber();
+ _field4C = file->readNumber();
+ _fieldB8 = file->readNumber();
+ _visible = file->readNumber() != 0;
+ _isMail = file->readNumber();
+ _id = file->readNumber();
+ _roomFlags = file->readNumber();
+
+ resourceKey.load(file);
+ _surface = nullptr;
+ val = file->readNumber();
+ if (val) {
+ _resource = resourceKey.getString();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ CNamedItem::load(file);
+}
+
+void CGameObject::draw(CScreenManager *screenManager) {
+ if (!_visible)
+ return;
+ if (_credits && _credits->_objectP == this) {
+ if (!_credits->draw())
+ CGameObject::deinit();
+
+ return;
+ }
+
+ if (_field40) {
+ // If a text object is defined, handle drawing it
+ if (_text && _bounds.intersects(getGameManager()->_bounds))
+ _text->draw(screenManager);
+
+ return;
+ } else {
+ if (!_surface) {
+ if (!_resource.empty()) {
+ loadResource(_resource);
+ _resource = "";
+ }
+ }
+
+ if (_surface) {
+ _bounds.setWidth(_surface->getWidth());
+ _bounds.setHeight(_surface->getHeight());
+
+ if (!_bounds.width() || !_bounds.height())
+ return;
+
+ if (_frameNumber >= 0) {
+ loadFrame(_frameNumber);
+ _frameNumber = -1;
+ }
+
+ if (!_movieRangeInfoList.empty())
+ processMoveRangeInfo();
+
+ if (_bounds.intersects(getGameManager()->_bounds)) {
+ if (_surface) {
+ Point destPos(_bounds.left, _bounds.top);
+ screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &destPos);
+ }
+
+ if (_text)
+ _text->draw(screenManager);
+ }
+ }
+ }
+}
+
+Rect CGameObject::getBounds() const {
+ return (_surface && _surface->hasFrame()) ? _bounds : Rect();
+}
+
+void CGameObject::viewChange() {
+ // Handle freeing the surfaces of objects when their view is left
+ if (_surface) {
+ _resource = _surface->_resourceKey.getString();
+ _initialFrame = getMovieFrame();
+
+ delete _surface;
+ _surface = nullptr;
+ }
+}
+
+void CGameObject::stopMovie() {
+ if (_surface)
+ _surface->stopMovie();
+}
+
+bool CGameObject::checkPoint(const Point &pt, bool ignore40, bool visibleOnly) {
+ if ((!_visible && visibleOnly) || !_bounds.contains(pt))
+ return false;
+
+ if (ignore40 || _field40)
+ return true;
+
+ if (!_surface) {
+ if (_frameNumber == -1)
+ return true;
+ loadFrame(_frameNumber);
+ if (!_surface)
+ return true;
+ }
+
+ Common::Point pixelPos = pt - _bounds;
+ if (_surface->_transBlitFlag) {
+ pixelPos.y = ((_bounds.height() - _bounds.top) / 2) * 2 - pixelPos.y;
+ }
+
+ uint transColor = _surface->getTransparencyColor();
+ uint pixel = _surface->getPixel(pixelPos);
+ return pixel != transColor;
+}
+
+bool CGameObject::clipRect(const Rect &rect1, Rect &rect2) const {
+ if (!rect2.intersects(rect1))
+ return false;
+
+ rect2.clip(rect1);
+ return true;
+}
+
+void CGameObject::draw(CScreenManager *screenManager, const Rect &destRect, const Rect &srcRect) {
+ Rect tempRect = destRect;
+ if (clipRect(srcRect, tempRect)) {
+ if (!_surface && !_resource.empty()) {
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ if (_surface)
+ screenManager->blitFrom(SURFACE_PRIMARY, &tempRect, _surface);
+ }
+}
+
+void CGameObject::draw(CScreenManager *screenManager, const Point &destPos) {
+ if (!_surface && !_resource.empty()) {
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ if (_surface) {
+ int xSize = _surface->getWidth();
+ int ySize = _surface->getHeight();
+
+ if (xSize > 0 && ySize > 0) {
+ screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &destPos);
+ }
+ }
+}
+
+void CGameObject::draw(CScreenManager *screenManager, const Point &destPos, const Rect &srcRect) {
+ draw(screenManager, Rect(destPos.x, destPos.y, destPos.x + 52, destPos.y + 52), srcRect);
+}
+
+bool CGameObject::isPet() const {
+ return isInstanceOf(CPetControl::_type);
+}
+
+void CGameObject::loadResource(const CString &name) {
+ switch (name.fileTypeSuffix()) {
+ case FILETYPE_IMAGE:
+ loadImage(name);
+ break;
+ case FILETYPE_MOVIE:
+ loadMovie(name);
+ break;
+ default:
+ break;
+ }
+}
+
+void CGameObject::loadMovie(const CString &name, bool pendingFlag) {
+ g_vm->_filesManager->preload(name);
+
+ // Create the surface if it doesn't already exist
+ if (!_surface) {
+ CGameManager *gameManager = getGameManager();
+ _surface = new OSVideoSurface(gameManager->setScreenManager(), nullptr);
+ }
+
+ // Load the new movie resource
+ CResourceKey key(name);
+ _surface->loadResource(key);
+
+ if (_surface->hasSurface() && !pendingFlag) {
+ _bounds.setWidth(_surface->getWidth());
+ _bounds.setHeight(_surface->getHeight());
+ }
+
+ if (_initialFrame)
+ loadFrame(_initialFrame);
+}
+
+void CGameObject::loadImage(const CString &name, bool pendingFlag) {
+ // Get a refernce to the game and screen managers
+ CGameManager *gameManager = getGameManager();
+ CScreenManager *screenManager;
+
+ if (gameManager && (screenManager = CScreenManager::setCurrent()) != nullptr) {
+ // Destroy the object's surface if it already had one
+ if (_surface) {
+ delete _surface;
+ _surface = nullptr;
+ }
+
+ g_vm->_filesManager->preload(name);
+
+ if (!name.empty()) {
+ _surface = new OSVideoSurface(screenManager, CResourceKey(name), pendingFlag);
+ }
+
+ if (_surface && !pendingFlag) {
+ _bounds.right = _surface->getWidth();
+ _bounds.bottom = _surface->getHeight();
+ }
+
+ // Mark the object's area as dirty, so that on the next frame rendering
+ // this object will be redrawn
+ makeDirty();
+ }
+
+ _initialFrame = 0;
+}
+
+void CGameObject::loadFrame(int frameNumber) {
+ if (frameNumber != -1 && !_resource.empty())
+ loadResource(_resource);
+
+ if (_surface)
+ _surface->setMovieFrame(frameNumber);
+
+ makeDirty();
+}
+
+void CGameObject::processMoveRangeInfo() {
+ for (CMovieRangeInfoList::iterator i = _movieRangeInfoList.begin(); i != _movieRangeInfoList.end(); ++i)
+ (*i)->process(this);
+
+ _movieRangeInfoList.destroyContents();
+}
+
+void CGameObject::makeDirty(const Rect &r) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager)
+ gameManager->extendBounds(r);
+}
+
+void CGameObject::makeDirty() {
+ makeDirty(_bounds);
+}
+
+bool CGameObject::isSoundActive(int handle) const {
+ if (handle != 0 && handle != -1) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager)
+ return gameManager->_sound.isActive(handle);
+ }
+
+ return false;
+}
+
+void CGameObject::playGlobalSound(const CString &resName, int mode, bool initialMute, bool repeated, int handleIndex) {
+ if (handleIndex < 0 || handleIndex > 3)
+ return;
+ CGameManager *gameManager = getGameManager();
+ if (!gameManager)
+ return;
+
+ // Preload the file, and stop any existing sound using the given slot
+ CSound &sound = gameManager->_sound;
+ g_vm->_filesManager->preload(resName);
+ if (_soundHandles[handleIndex] != -1) {
+ sound.stopSound(_soundHandles[handleIndex]);
+ _soundHandles[handleIndex] = -1;
+ }
+
+ // If no new name specified, then exit
+ if (resName.empty())
+ return;
+
+ uint newVolume = sound._soundManager.getModeVolume(mode);
+ uint volume = initialMute ? 0 : newVolume;
+
+ CProximity prox;
+ prox._channelVolume = volume;
+ prox._repeated = repeated;
+
+ switch (handleIndex) {
+ case 0:
+ prox._channel = 6;
+ break;
+ case 1:
+ prox._channel = 7;
+ break;
+ case 2:
+ prox._channel = 8;
+ break;
+ case 3:
+ prox._channel = 9;
+ break;
+ default:
+ break;
+ }
+
+ _soundHandles[handleIndex] = sound.playSound(resName, prox);
+
+ if (_soundHandles[handleIndex])
+ sound.setVolume(_soundHandles[handleIndex], newVolume, 2);
+}
+
+void CGameObject::setSoundVolume(int handle, uint percent, uint seconds) {
+ if (handle != 0 && handle != -1) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager)
+ return gameManager->_sound.setVolume(handle, percent, seconds);
+ }
+}
+
+void CGameObject::stopGlobalSound(bool transition, int handleIndex) {
+ CGameManager *gameManager = getGameManager();
+ if (!gameManager)
+ return;
+ CSound &sound = gameManager->_sound;
+
+ if (handleIndex == -1) {
+ for (int idx = 0; idx < 4; ++idx) {
+ if (_soundHandles[idx] != -1) {
+ sound.setVolume(_soundHandles[idx], 0, transition ? 1 : 0);
+ sound.setCanFree(_soundHandles[idx]);
+ _soundHandles[idx] = -1;
+ }
+ }
+ } else if (handleIndex >= 0 && handleIndex <= 2 && _soundHandles[handleIndex] != -1) {
+ if (transition) {
+ // Transitioning to silent over 1 second
+ sound.setVolume(_soundHandles[handleIndex], 0, 1);
+ sleep(1000);
+ }
+
+ sound.stopSound(_soundHandles[handleIndex]);
+ _soundHandles[handleIndex] = -1;
+ }
+ warning("CGameObject::soundFn4");
+}
+
+void CGameObject::setGlobalSoundVolume(int mode, uint seconds, int handleIndex) {
+ CGameManager *gameManager = getGameManager();
+ if (!gameManager)
+ return;
+ CSound &sound = gameManager->_sound;
+
+ if (handleIndex == -1) {
+ // Iterate through calling the method for each handle
+ for (int idx = 0; idx < 3; ++idx)
+ setGlobalSoundVolume(mode, seconds, idx);
+ } else if (handleIndex >= 0 && handleIndex <= 3 && _soundHandles[handleIndex] != -1) {
+ uint newVolume = sound._soundManager.getModeVolume(mode);
+ sound.setVolume(_soundHandles[handleIndex], newVolume, seconds);
+ }
+}
+
+void CGameObject::sound8(bool flag) const {
+ getGameManager()->_sound.stopChannel(flag ? 3 : 0);
+}
+
+void CGameObject::setVisible(bool val) {
+ if (val != _visible) {
+ _visible = val;
+ makeDirty();
+ }
+}
+
+void CGameObject::petHighlightGlyph(int val) {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->highlightGlyph(val);
+}
+
+void CGameObject::petHideCursor() {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->hideCursor();
+}
+
+void CGameObject::petShowCursor() {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->showCursor();
+}
+
+void CGameObject::petShow() {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ gameManager->_gameState._petActive = true;
+ gameManager->_gameState.setMode(GSMODE_INTERACTIVE);
+ gameManager->initBounds();
+ }
+}
+
+void CGameObject::petHide() {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ gameManager->_gameState._petActive = false;
+ gameManager->_gameState.setMode(GSMODE_INTERACTIVE);
+ gameManager->initBounds();
+ }
+}
+
+void CGameObject::petSetRemoteTarget() {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->setRemoteTarget(this);
+}
+
+void CGameObject::playMovie(uint flags) {
+ _frameNumber = -1;
+
+ if (!_surface && !_resource.empty()) {
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
+ if (_surface) {
+ _surface->playMovie(flags, obj);
+ if (flags & MOVIE_GAMESTATE)
+ getGameManager()->_gameState.addMovie(_surface->_movie);
+ }
+}
+
+void CGameObject::playMovie(int startFrame, int endFrame, uint flags) {
+ _frameNumber = -1;
+
+ if (!_surface) {
+ if (!_resource.empty())
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
+ if (_surface) {
+ _surface->playMovie(startFrame, endFrame, flags, obj);
+ if (flags & MOVIE_GAMESTATE)
+ getGameManager()->_gameState.addMovie(_surface->_movie);
+ }
+}
+
+
+void CGameObject::playMovie(int startFrame, int endFrame, int initialFrame, uint flags) {
+ _frameNumber = -1;
+
+ if (!_surface) {
+ if (!_resource.empty())
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
+ if (_surface) {
+ _surface->playMovie(startFrame, endFrame, initialFrame, flags, obj);
+ if (flags & MOVIE_GAMESTATE)
+ getGameManager()->_gameState.addMovie(_surface->_movie);
+ }
+}
+
+void CGameObject::playClip(const CString &name, uint flags) {
+ _frameNumber = -1;
+ CMovieClip *clip = _movieClips.findByName(name);
+ if (clip)
+ playMovie(clip->_startFrame, clip->_endFrame, flags);
+}
+
+void CGameObject::playClip(uint startFrame, uint endFrame) {
+ CMovieClip *clip = new CMovieClip("", startFrame, endFrame);
+ CGameManager *gameManager = getGameManager();
+ CRoomItem *room = gameManager->getRoom();
+
+ gameManager->playClip(clip, room, room);
+}
+
+void CGameObject::playRandomClip(const char *const *names, uint flags) {
+ // Count size of array
+ int count = 0;
+ for (const char *const *p = names; *p; ++p)
+ ++count;
+
+ // Play clip
+ const char *name = names[g_vm->getRandomNumber(count - 1)];
+ playClip(name, flags);
+}
+
+void CGameObject::playCutscene(uint startFrame, uint endFrame) {
+ if (!_surface) {
+ if (!_resource.empty())
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ if (_surface && _surface->loadIfReady() && _surface->_movie) {
+ disableMouse();
+ _surface->_movie->playCutscene(_bounds, startFrame, endFrame);
+ enableMouse();
+ }
+}
+
+void CGameObject::savePosition() {
+ _savedPos = _bounds;
+}
+
+void CGameObject::resetPosition() {
+ setPosition(_savedPos);
+}
+
+void CGameObject::setPosition(const Point &newPos) {
+ makeDirty();
+ _bounds.moveTo(newPos);
+ makeDirty();
+}
+
+bool CGameObject::checkStartDragging(CMouseDragStartMsg *msg) {
+ if (_visible && checkPoint(msg->_mousePos, msg->_handled, 1)) {
+ savePosition();
+ msg->_dragItem = this;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool CGameObject::hasActiveMovie() const {
+ if (_surface && _surface->_movie)
+ return _surface->_movie->isActive();
+ return false;
+}
+
+int CGameObject::getMovieFrame() const {
+ if (_surface && _surface->_movie)
+ return _surface->_movie->getFrame();
+ return _initialFrame;
+}
+
+bool CGameObject::surfaceHasFrame() const {
+ return _surface ? _surface->hasFrame() : false;
+}
+
+void CGameObject::loadSound(const CString &name) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ g_vm->_filesManager->preload(name);
+ if (!name.empty())
+ gameManager->_sound.loadSound(name);
+ }
+}
+
+int CGameObject::playSound(const CString &name, uint volume, int val3, bool repeated) {
+ CProximity prox;
+ prox._channelVolume = volume;
+ prox._fieldC = val3;
+ prox._repeated = repeated;
+ return playSound(name, prox);
+}
+
+int CGameObject::playSound(const CString &name, CProximity &prox) {
+ if (prox._positioningMode == POSMODE_VECTOR) {
+ // If the proximity doesn't have a position defined, default it to
+ // the position of the view to which the game object belongs
+ if (prox._posX == 0.0 && prox._posY == 0.0 && prox._posZ == 0.0)
+ findView()->getPosition(prox._posX, prox._posY, prox._posZ);
+ }
+
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ g_vm->_filesManager->preload(name);
+
+ gameManager->_sound.playSound(name, prox);
+ }
+
+ return 0;
+}
+
+int CGameObject::queueSound(const CString &name, uint priorHandle, uint volume, int val3, bool repeated) {
+ CProximity prox;
+ prox._fieldC = val3;
+ prox._repeated = repeated;
+ prox._channelVolume = volume;
+ prox._priorSoundHandle = priorHandle;
+
+ return playSound(name, prox);
+}
+
+void CGameObject::stopSound(int handle, uint seconds) {
+ if (handle != 0 && handle != -1) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ if (seconds) {
+ gameManager->_sound.setVolume(handle, 0, seconds);
+ gameManager->_sound.setCanFree(handle);
+ } else {
+ gameManager->_sound.stopSound(handle);
+ }
+ }
+ }
+}
+
+int CGameObject::addTimer(int endVal, uint firstDuration, uint repeatDuration) {
+ CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration != 0,
+ firstDuration, repeatDuration, this, endVal, CString());
+
+ getGameManager()->addTimer(timer);
+ return timer->_id;
+}
+
+int CGameObject::addTimer(uint firstDuration, uint repeatDuration) {
+ CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration != 0,
+ firstDuration, repeatDuration, this, 0, CString());
+
+ getGameManager()->addTimer(timer);
+ return timer->_id;
+}
+
+void CGameObject::stopTimer(int id) {
+ getGameManager()->stopTimer(id);
+}
+
+int CGameObject::startAnimTimer(const CString &action, uint firstDuration, uint repeatDuration) {
+ CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration > 0,
+ firstDuration, repeatDuration, this, 0, action);
+ getGameManager()->addTimer(timer);
+
+ return timer->_id;
+}
+
+void CGameObject::stopAnimTimer(int id) {
+ getGameManager()->stopTimer(id);
+}
+
+void CGameObject::gotoView(const CString &viewName, const CString &clipName) {
+ CViewItem *newView = parseView(viewName);
+ CGameManager *gameManager = getGameManager();
+ CViewItem *oldView = gameManager ? gameManager->getView() : newView;
+ if (!oldView || !newView)
+ return;
+
+ CMovieClip *clip = nullptr;
+ if (clipName.empty()) {
+ CLinkItem *link = oldView->findLink(newView);
+ if (link)
+ clip = link->getClip();
+ } else {
+ clip = oldView->findNode()->findRoom()->findClip(clipName);
+ }
+
+ // Change the view
+ gameManager->_gameState.changeView(newView, clip);
+}
+
+CViewItem *CGameObject::parseView(const CString &viewString) {
+ int firstIndex = viewString.indexOf('.');
+ int lastIndex = viewString.lastIndexOf('.');
+ CString roomName, nodeName, viewName;
+
+ if (firstIndex == -1) {
+ roomName = viewString;
+ } else {
+ roomName = viewString.left(firstIndex);
+
+ if (lastIndex > firstIndex) {
+ nodeName = viewString.mid(firstIndex + 1, lastIndex - firstIndex - 1);
+ viewName = viewString.mid(lastIndex + 1);
+ } else {
+ nodeName = viewString.mid(firstIndex + 1);
+ }
+ }
+
+ CGameManager *gameManager = getGameManager();
+ if (!gameManager)
+ return nullptr;
+
+ CRoomItem *room = gameManager->getRoom();
+ CProjectItem *project = room->getRoot();
+
+ // Ensure we have the specified room
+ if (project) {
+ if (room->getName() != roomName) {
+ // Scan for the correct room
+ for (room = project->findFirstRoom(); room && room->getName() != roomName;
+ room = project->findNextRoom(room)) ;
+ }
+ }
+ if (!room)
+ return nullptr;
+
+ // Find the designated node within the room
+ CNodeItem *node = static_cast<CNodeItem *>(room->findChildInstanceOf(CNodeItem::_type));
+ while (node && node->getName() != nodeName)
+ node = static_cast<CNodeItem *>(room->findNextInstanceOf(CNodeItem::_type, node));
+ if (!node)
+ return nullptr;
+
+ CViewItem *view = static_cast<CViewItem *>(node->findChildInstanceOf(CViewItem::_type));
+ while (view && view->getName() != viewName)
+ view = static_cast<CViewItem *>(node->findNextInstanceOf(CViewItem::_type, view));
+ if (!view)
+ return nullptr;
+
+ // Find the view, so return it
+ return view;
+}
+
+CString CGameObject::getViewFullName() const {
+ CGameManager *gameManager = getGameManager();
+ CViewItem *view = gameManager->getView();
+ CNodeItem *node = view->findNode();
+ CRoomItem *room = node->findRoom();
+
+ return CString::format("%s.%s.%s", room->getName().c_str(),
+ node->getName().c_str(), view->getName().c_str());
+}
+
+void CGameObject::sleep(uint milli) {
+ g_vm->_events->sleep(milli);
+}
+
+Point CGameObject::getMousePos() const {
+ return getGameManager()->_gameState.getMousePos();
+}
+
+bool CGameObject::compareViewNameTo(const CString &name) const {
+ return getViewFullName().compareToIgnoreCase(name);
+}
+
+int CGameObject::compareRoomNameTo(const CString &name) {
+ CRoomItem *room = getGameManager()->getRoom();
+ return room->getName().compareToIgnoreCase(name);
+}
+
+CString CGameObject::getRoomName() const {
+ CRoomItem *room = getRoom();
+ return room ? room->getName() : CString();
+}
+
+CString CGameObject::getRoomNodeName() const {
+ CNodeItem *node = getNode();
+ if (!node)
+ return CString();
+
+ CRoomItem *room = node->findRoom();
+
+ return CString::format("%s.%s", room->getName().c_str(), node->getName().c_str());
+}
+
+CString CGameObject::getFullViewName() {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? gameManager->getFullViewName() : CString();
+}
+
+CGameObject *CGameObject::getMailManFirstObject() const {
+ CMailMan *mailMan = getMailMan();
+ return mailMan ? mailMan->getFirstObject() : nullptr;
+}
+
+CGameObject *CGameObject::getMailManNextObject(CGameObject *prior) const {
+ CMailMan *mailMan = getMailMan();
+ return mailMan ? mailMan->getNextObject(prior) : nullptr;
+}
+
+CGameObject *CGameObject::findMailByFlags(int mode, uint roomFlags) {
+ CMailMan *mailMan = getMailMan();
+ if (!mailMan)
+ return nullptr;
+
+ for (CGameObject *obj = mailMan->getFirstObject(); obj;
+ obj = mailMan->getNextObject(obj)) {
+ if (compareRoomFlags(mode, roomFlags, obj->_roomFlags))
+ return obj;
+ }
+
+ return nullptr;
+}
+
+CGameObject *CGameObject::getNextMail(CGameObject *prior) {
+ CMailMan *mailMan = getMailMan();
+ return mailMan ? mailMan->getNextObject(prior) : nullptr;
+}
+
+CGameObject *CGameObject::findRoomObject(const CString &name) const {
+ return static_cast<CGameObject *>(findRoom()->findByName(name));
+}
+
+CGameObject *CGameObject::findInRoom(const CString &name) {
+ CRoomItem *room = getRoom();
+ return room ? static_cast<CGameObject *>(room->findByName(name)) : nullptr;
+}
+
+Found CGameObject::find(const CString &name, CGameObject **item, int findAreas) {
+ CGameObject *go;
+ *item = nullptr;
+
+ // Scan under PET if flagged
+ if (findAreas & FIND_PET) {
+ for (go = getPetControl()->getFirstObject(); go; go = getPetControl()->getNextObject(go)) {
+ if (go->getName() == name) {
+ *item = go;
+ return FOUND_PET;
+ }
+ }
+ }
+
+ if (findAreas & FIND_MAILMAN) {
+ for (go = getMailManFirstObject(); go; go = getMailManNextObject(go)) {
+ if (go->getName() == name) {
+ *item = go;
+ return FOUND_MAILMAN;
+ }
+ }
+ }
+
+ if (findAreas & FIND_GLOBAL) {
+ go = static_cast<CGameObject *>(getRoot()->findByName(name));
+ if (go) {
+ *item = go;
+ return FOUND_GLOBAL;
+ }
+ }
+
+ if (findAreas & FIND_ROOM) {
+ go = findRoomObject(name);
+ if (go) {
+ *item = go;
+ return FOUND_ROOM;
+ }
+ }
+
+ return FOUND_NONE;
+}
+
+void CGameObject::moveToView() {
+ CViewItem *view = getGameManager()->getView();
+ detach();
+ addUnder(view);
+}
+
+void CGameObject::moveToView(const CString &name) {
+ CViewItem *view = parseView(name);
+ detach();
+ addUnder(view);
+}
+
+void CGameObject::stateInc14() {
+ getGameManager()->_gameState.inc14();
+}
+
+int CGameObject::stateGet14() const {
+ return getGameManager()->_gameState._field14;
+}
+
+void CGameObject::stateSet24() {
+ getGameManager()->_gameState.set24(1);
+}
+
+int CGameObject::stateGet24() const {
+ return getGameManager()->_gameState.get24();
+}
+
+void CGameObject::stateInc38() {
+ getGameManager()->_gameState.inc38();
+}
+
+int CGameObject::stateGet38() const {
+ return getGameManager()->_gameState._field38;
+}
+
+void CGameObject::quitGame() {
+ getGameManager()->_gameState._quitGame = true;
+}
+
+void CGameObject::inc54() {
+ getGameManager()->inc54();
+}
+
+void CGameObject::dec54() {
+ getGameManager()->dec54();
+}
+
+void CGameObject::setMovieFrameRate(double rate) {
+ if (_surface)
+ _surface->setMovieFrameRate(rate);
+}
+
+void CGameObject::setText(const CString &str, int border, int borderRight) {
+ if (!_text)
+ _text = new CPetText();
+ _textBorder = border;
+ _textBorderRight = borderRight;
+
+ _text->setText(str);
+ CScreenManager *screenManager = getGameManager()->setScreenManager();
+ _text->scrollToTop(screenManager);
+}
+
+void CGameObject::setTextHasBorders(bool hasBorders) {
+ if (!_text)
+ _text = new CPetText();
+
+ _text->setHasBorder(hasBorders);
+}
+
+void CGameObject::setTextBounds() {
+ Rect rect = _bounds;
+ rect.grow(_textBorder);
+ rect.right -= _textBorderRight;
+
+ _text->setBounds(rect);
+ makeDirty();
+}
+
+void CGameObject::setTextColor(byte r, byte g, byte b) {
+ if (!_text)
+ _text = new CPetText();
+
+ _text->setColor(r, g, b);
+}
+
+void CGameObject::setTextFontNumber(int fontNumber) {
+ if (!_text)
+ _text = new CPetText();
+
+ _text->setFontNumber(fontNumber);
+}
+
+int CGameObject::getTextWidth() const {
+ assert(_text);
+ return _text->getTextWidth(CScreenManager::_screenManagerPtr);
+}
+
+CTextCursor *CGameObject::getTextCursor() const {
+ return CScreenManager::_screenManagerPtr->_textCursor;
+}
+
+void CGameObject::scrollTextUp() {
+ if (_text)
+ _text->scrollUp(CScreenManager::_screenManagerPtr);
+}
+
+void CGameObject::scrollTextDown() {
+ if (_text)
+ _text->scrollDown(CScreenManager::_screenManagerPtr);
+}
+
+void CGameObject::lockMouse() {
+ CGameManager *gameMan = getGameManager();
+ gameMan->lockInputHandler();
+
+ if (CScreenManager::_screenManagerPtr->_mouseCursor)
+ CScreenManager::_screenManagerPtr->_mouseCursor->hide();
+}
+
+void CGameObject::hideMouse() {
+ CScreenManager::_screenManagerPtr->_mouseCursor->hide();
+}
+
+void CGameObject::showMouse() {
+ CScreenManager::_screenManagerPtr->_mouseCursor->show();
+}
+
+void CGameObject::disableMouse() {
+ lockInputHandler();
+ hideMouse();
+}
+
+void CGameObject::enableMouse() {
+ unlockInputHandler();
+ showMouse();
+}
+
+void CGameObject::mouseLockE4() {
+ CScreenManager::_screenManagerPtr->_mouseCursor->lockE4();
+}
+
+void CGameObject::mouseUnlockE4() {
+ CScreenManager::_screenManagerPtr->_mouseCursor->unlockE4();
+}
+
+void CGameObject::mouseSaveState(int v1, int v2, int v3) {
+ CScreenManager::_screenManagerPtr->_mouseCursor->saveState(v1, v2, v3);
+}
+
+void CGameObject::lockInputHandler() {
+ getGameManager()->lockInputHandler();
+}
+
+void CGameObject::unlockInputHandler() {
+ getGameManager()->unlockInputHandler();
+}
+
+void CGameObject::unlockMouse() {
+ if (CScreenManager::_screenManagerPtr->_mouseCursor)
+ CScreenManager::_screenManagerPtr->_mouseCursor->show();
+
+ CGameManager *gameMan = getGameManager();
+ gameMan->unlockInputHandler();
+}
+
+void CGameObject::loadSurface() {
+ if (!_surface && !_resource.empty()) {
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ if (_surface)
+ _surface->loadIfReady();
+}
+
+bool CGameObject::changeView(const CString &viewName) {
+ return changeView(viewName, "");
+}
+
+bool CGameObject::changeView(const CString &viewName, const CString &clipName) {
+ CViewItem *newView = parseView(viewName);
+ CGameManager *gameManager = getGameManager();
+ CViewItem *oldView = gameManager->getView();
+
+ if (!oldView || !newView)
+ return false;
+
+ CMovieClip *clip = nullptr;
+ if (!clipName.empty()) {
+ clip = oldView->findNode()->findRoom()->findClip(clipName);
+ } else {
+ CLinkItem *link = oldView->findLink(newView);
+ if (link)
+ clip = link->getClip();
+ }
+
+ gameManager->_gameState.changeView(newView, clip);
+ return true;
+}
+
+void CGameObject::dragMove(const Point &pt) {
+ if (_surface) {
+ _bounds.setWidth(_surface->getWidth());
+ _bounds.setHeight(_surface->getHeight());
+ }
+
+ setPosition(Point(pt.x - _bounds.width() / 2, pt.y - _bounds.height() / 2));
+}
+
+CGameObject *CGameObject::getDraggingObject() const {
+ CTreeItem *item = getGameManager()->_dragItem;
+ return static_cast<CGameObject *>(item);
+}
+
+Point CGameObject::getControid() const {
+ return Point(_bounds.left + _bounds.width() / 2,
+ _bounds.top + _bounds.height() / 2);
+}
+
+bool CGameObject::clipExistsByStart(const CString &name, int startFrame) const {
+ return _movieClips.existsByStart(name, startFrame);
+}
+
+bool CGameObject::clipExistsByEnd(const CString &name, int endFrame) const {
+ return _movieClips.existsByEnd(name, endFrame);
+}
+
+void CGameObject::petClear() const {
+ CPetControl *petControl = getPetControl();
+ if (petControl)
+ petControl->resetActiveNPC();
+}
+
+CDontSaveFileItem *CGameObject::getDontSave() const {
+ CProjectItem *project = getRoot();
+ return project ? project->getDontSaveFileItem() : nullptr;
+}
+
+CPetControl *CGameObject::getPetControl() const {
+ return static_cast<CPetControl *>(getDontSaveChild(CPetControl::_type));
+}
+
+CMailMan *CGameObject::getMailMan() const {
+ return dynamic_cast<CMailMan *>(getDontSaveChild(CMailMan::_type));
+}
+
+CTreeItem *CGameObject::getDontSaveChild(ClassDef *classDef) const {
+ CProjectItem *root = getRoot();
+ if (!root)
+ return nullptr;
+
+ CDontSaveFileItem *dontSave = root->getDontSaveFileItem();
+ if (!dontSave)
+ return nullptr;
+
+ return dontSave->findChildInstanceOf(classDef);
+}
+
+CRoomItem *CGameObject::getHiddenRoom() const {
+ CProjectItem *root = getRoot();
+ return root ? root->findHiddenRoom() : nullptr;
+}
+
+CRoomItem *CGameObject::locateRoom(const CString &name) const {
+ if (name.empty())
+ return nullptr;
+
+ CProjectItem *project = getRoot();
+ for (CRoomItem *room = project->findFirstRoom(); room; room = project->findNextRoom(room)) {
+ if (!room->getName().compareToIgnoreCase(name))
+ return room;
+ }
+
+ return nullptr;
+}
+
+CGameObject *CGameObject::getHiddenObject(const CString &name) const {
+ CRoomItem *room = getHiddenRoom();
+ return room ? static_cast<CGameObject *>(findUnder(room, name)) : nullptr;
+}
+
+CTreeItem *CGameObject::findUnder(CTreeItem *parent, const CString &name) const {
+ if (!parent)
+ return nullptr;
+
+ for (CTreeItem *item = parent->getFirstChild(); item; item = item->scan(parent)) {
+ if (item->getName() == name)
+ return item;
+ }
+
+ return nullptr;
+}
+
+CRoomItem *CGameObject::findRoomByName(const CString &name) {
+ CProjectItem *project = getRoot();
+ for (CRoomItem *room = project->findFirstRoom(); room; room = project->findNextRoom(room)) {
+ if (!room->getName().compareToIgnoreCase(name))
+ return room;
+ }
+
+ return nullptr;
+}
+
+CMusicRoom *CGameObject::getMusicRoom() const {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? &gameManager->_musicRoom : nullptr;
+}
+
+int CGameObject::getPassengerClass() const {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? gameManager->_gameState._passengerClass : 3;
+}
+
+int CGameObject::getPriorClass() const {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? gameManager->_gameState._priorClass : 3;
+}
+
+void CGameObject::setPassengerClass(int newClass) {
+ if (newClass >= 1 && newClass <= 4) {
+ // Change the passenger class
+ CGameManager *gameMan = getGameManager();
+ gameMan->_gameState._priorClass = gameMan->_gameState._passengerClass;
+ gameMan->_gameState._passengerClass = newClass;
+
+ // Setup the PET again, so the new class's PET background can take effect
+ CPetControl *petControl = getPetControl();
+ if (petControl)
+ petControl->setup();
+ }
+}
+
+void CGameObject::createCredits() {
+ _credits = new CCreditText();
+ CScreenManager *screenManager = getGameManager()->setScreenManager();
+ _credits->load(this, screenManager, _bounds);
+}
+
+void CGameObject::fn10(int v1, int v2, int v3) {
+ makeDirty();
+ _field44 = v1;
+ _field48 = v2;
+ _field4C = v3;
+}
+
+void CGameObject::movieSetAudioTiming(bool flag) {
+ if (!_surface && !_resource.empty()) {
+ loadResource(_resource);
+ _resource.clear();
+ }
+
+ if (_surface && _surface->_movie)
+ _surface->_movie->_hasAudioTiming = flag;
+}
+
+void CGameObject::movieEvent(int frameNumber) {
+ if (_surface)
+ _surface->addMovieEvent(frameNumber, this);
+}
+
+void CGameObject::movieEvent() {
+ if (_surface)
+ _surface->addMovieEvent(-1, this);
+}
+
+int CGameObject::getClipDuration(const CString &name, int frameRate) const {
+ CMovieClip *clip = _movieClips.findByName(name);
+ return clip ? (clip->_endFrame - clip->_startFrame) * 1000 / frameRate : 0;
+}
+
+uint32 CGameObject::getTicksCount() {
+ return g_vm->_events->getTicksCount();
+}
+
+Common::SeekableReadStream *CGameObject::getResource(const CString &name) {
+ return g_vm->_filesManager->getResource(name);
+}
+
+bool CGameObject::compareRoomFlags(int mode, uint flags1, uint flags2) {
+ switch (mode) {
+ case 1:
+ return CRoomFlags::compareLocation(flags1, flags2);
+
+ case 2:
+ return CRoomFlags::compareClassElevator(flags1, flags2);
+
+ case 3:
+ return CRoomFlags::isTitania(flags1, flags2);
+
+ default:
+ return false;
+ }
+}
+
+void CGameObject::setState1C(bool flag) {
+ getGameManager()->_gameState._field1C = flag;
+}
+
+void CGameObject::addMail(int mailId) {
+ CMailMan *mailMan = getMailMan();
+ if (mailMan) {
+ makeDirty();
+ mailMan->addMail(this, mailId);
+ }
+}
+
+void CGameObject::setMailId(int mailId) {
+ CMailMan *mailMan = getMailMan();
+ if (mailMan) {
+ makeDirty();
+ mailMan->setMailId(this, mailId);
+ }
+}
+
+bool CGameObject::mailExists(int id) const {
+ return findMail(id) != nullptr;
+}
+
+CGameObject *CGameObject::findMail(int id) const {
+ CMailMan *mailMan = getMailMan();
+ return mailMan ? mailMan->findMail(id) : nullptr;
+}
+
+void CGameObject::removeMail(int id, int v) {
+ CMailMan *mailMan = getMailMan();
+ if (mailMan)
+ mailMan->removeMail(id, v);
+}
+
+void CGameObject::resetMail() {
+ CMailMan *mailMan = getMailMan();
+ if (mailMan)
+ mailMan->resetValue();
+}
+
+int CGameObject::getRandomNumber(int max, int *oldVal) {
+ if (oldVal) {
+ int startingVal = *oldVal;
+ while (*oldVal == startingVal && max > 0)
+ *oldVal = g_vm->getRandomNumber(max);
+
+ return *oldVal;
+ } else {
+ return g_vm->getRandomNumber(max);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+CRoomItem *CGameObject::getRoom() const {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? gameManager->getRoom() : nullptr;
+}
+
+CNodeItem *CGameObject::getNode() const {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? gameManager->getNode() : nullptr;
+}
+
+CViewItem *CGameObject::getView() const {
+ CGameManager *gameManager = getGameManager();
+ return gameManager ? gameManager->getView() : nullptr;
+}
+
+/*------------------------------------------------------------------------*/
+
+void CGameObject::petAddToCarryParcel(CGameObject *obj) {
+ CPetControl *pet = getPetControl();
+ if (pet) {
+ CGameObject *parcel = pet->getHiddenObject("CarryParcel");
+ if (parcel)
+ parcel->moveUnder(obj);
+ }
+}
+
+void CGameObject::petAddToInventory() {
+ CPetControl *pet = getPetControl();
+ if (pet) {
+ makeDirty();
+ pet->addToInventory(this);
+ }
+}
+
+CTreeItem *CGameObject::petContainerRemove(CGameObject *obj) {
+ CPetControl *pet = getPetControl();
+ if (!obj || !pet)
+ return nullptr;
+ if (!obj->compareRoomNameTo("CarryParcel"))
+ return obj;
+
+ CGameObject *item = static_cast<CGameObject *>(pet->getLastChild());
+ if (item)
+ item->detach();
+
+ pet->moveToHiddenRoom(obj);
+ pet->removeFromInventory(item, false, false);
+
+ return item;
+}
+
+bool CGameObject::petCheckNode(const CString &name) {
+ CPetControl *pet = getPetControl();
+ return pet ? pet->checkNode(name) : false;
+}
+
+bool CGameObject::petDismissBot(const CString &name) {
+ CPetControl *pet = getPetControl();
+ return pet ? pet->dismissBot(name) : false;
+}
+
+bool CGameObject::petDoorOrBellbotPresent() const {
+ CPetControl *pet = getPetControl();
+ return pet ? pet->isDoorOrBellbotPresent() : false;
+}
+
+void CGameObject::petDisplayMessage(int unused, const CString &msg) {
+ petDisplayMessage(msg);
+}
+
+void CGameObject::petDisplayMessage(const CString &msg) {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->displayMessage(msg);
+}
+
+void CGameObject::petInvChange() {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->invChange(this);
+}
+
+void CGameObject::petLockInput() {
+ getPetControl()->incInputLocks();
+}
+
+void CGameObject::petMoveToHiddenRoom() {
+ CPetControl *pet = getPetControl();
+ if (pet) {
+ makeDirty();
+ pet->moveToHiddenRoom(this);
+ }
+}
+
+void CGameObject::petReassignRoom(int passClassNum) {
+ CPetControl *petControl = getPetControl();
+ if (petControl)
+ petControl->reassignRoom(passClassNum);
+}
+
+void CGameObject::petSetArea(PetArea newArea) const {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->setArea(newArea);
+}
+
+void CGameObject::petSetRoomsWellEntry(int entryNum) {
+ CPetControl *petControl = getPetControl();
+ if (petControl)
+ petControl->setRoomsWellEntry(entryNum);
+}
+
+int CGameObject::petGetRoomsWellEntry() const {
+ CPetControl *petControl = getPetControl();
+ return petControl ? petControl->getRoomsWellEntry() : 0;
+}
+
+void CGameObject::petSetRooms1D4(int v) {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->setRooms1D4(v);
+}
+
+void CGameObject::petOnSummonBot(const CString &name, int val) {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->summonBot(name, val);
+}
+
+void CGameObject::petUnlockInput() {
+ getPetControl()->decInputLocks();
+}
+
+/*------------------------------------------------------------------------*/
+
+CStarControl *CGameObject::getStarControl() const {
+ CStarControl *starControl = static_cast<CStarControl *>(getDontSaveChild(CStarControl::_type));
+ if (!starControl) {
+ CViewItem *view = getGameManager()->getView();
+ if (view)
+ starControl = static_cast<CStarControl *>(view->findChildInstanceOf(CStarControl::_type));
+ }
+
+ return starControl;
+}
+
+void CGameObject::starFn1(int v) {
+ CStarControl *starControl = getStarControl();
+ if (starControl)
+ starControl->fn1(v);
+}
+
+bool CGameObject::starFn2() {
+ CStarControl *starControl = getStarControl();
+ return starControl ? starControl->fn4() : false;
+}
+
+/*------------------------------------------------------------------------*/
+
+void CGameObject::startTalking(const CString &npcName, uint id, CViewItem *view) {
+ CTrueTalkNPC *npc = static_cast<CTrueTalkNPC *>(getRoot()->findByName(npcName));
+ startTalking(npc, id, view);
+}
+
+void CGameObject::startTalking(CTrueTalkNPC *npc, uint id, CViewItem *view) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ CTrueTalkManager *talkManager = gameManager->getTalkManager();
+ if (talkManager)
+ talkManager->start(npc, id, view);
+ }
+}
+
+void CGameObject::endTalking(CTrueTalkNPC *npc, bool viewFlag, CViewItem *view) {
+ CPetControl *pet = getPetControl();
+ if (pet)
+ pet->setActiveNPC(npc);
+
+ if (viewFlag)
+ npc->setView(view);
+
+ if (pet)
+ pet->refreshNPC();
+}
+
+void CGameObject::talkSetDialRegion(const CString &name, int dialNum, int regionNum) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ CTrueTalkManager *talkManager = gameManager->getTalkManager();
+ if (talkManager) {
+ TTnpcScript *npcScript = talkManager->getTalker(name);
+ if (npcScript)
+ npcScript->setDialRegion(dialNum, regionNum);
+ }
+ }
+}
+
+int CGameObject::talkGetDialRegion(const CString &name, int dialNum) {
+ CGameManager *gameManager = getGameManager();
+ if (gameManager) {
+ CTrueTalkManager *talkManager = gameManager->getTalkManager();
+ if (talkManager) {
+ TTnpcScript *npcScript = talkManager->getTalker(name);
+ if (npcScript)
+ return npcScript->getDialRegion(dialNum);
+ }
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+uint CGameObject::getNodeChangedCtr() const {
+ return getGameManager()->_gameState.getNodeChangedCtr();
+}
+
+uint CGameObject::getNodeEnterTicks() const {
+ return getGameManager()->_gameState.getNodeEnterTicks();
+}
+
+
+} // End of namespace Titanic