1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "titanic/core/game_object.h"
24 #include "titanic/core/mail_man.h"
25 #include "titanic/core/resource_key.h"
26 #include "titanic/core/room_item.h"
27 #include "titanic/core/project_item.h"
28 #include "titanic/debugger.h"
29 #include "titanic/events.h"
30 #include "titanic/game_manager.h"
31 #include "titanic/npcs/true_talk_npc.h"
32 #include "titanic/pet_control/pet_control.h"
33 #include "titanic/star_control/star_control.h"
34 #include "titanic/support/files_manager.h"
35 #include "titanic/support/screen_manager.h"
36 #include "titanic/support/video_surface.h"
37 #include "titanic/titanic.h"
38
39 namespace Titanic {
40
41 EMPTY_MESSAGE_MAP(CGameObject, CNamedItem);
42
43 CCreditText *CGameObject::_credits;
44 int CGameObject::_soundHandles[4];
45
init()46 void CGameObject::init() {
47 _credits = nullptr;
48 _soundHandles[0] = _soundHandles[1] = -1;
49 _soundHandles[2] = _soundHandles[3] = -1;
50 }
51
deinit()52 void CGameObject::deinit() {
53 if (_credits) {
54 _credits->clear();
55 delete _credits;
56 _credits = nullptr;
57 }
58 }
59
CGameObject()60 CGameObject::CGameObject(): CNamedItem() {
61 _bounds = Rect(0, 0, 15, 15);
62 _unused1 = 0;
63 _unused2 = 0;
64 _unused3 = 0;
65 _nonvisual = false;
66 _toggleR = 0xF0;
67 _toggleG = 0xF0;
68 _toggleB = 0xFF;
69 _isPendingMail = false;
70 _destRoomFlags = 0;
71 _roomFlags = 0;
72 _visible = true;
73 _handleMouseFlag = false;
74 _cursorId = CURSOR_ARROW;
75 _initialFrame = 0;
76 _frameNumber = -1;
77 _text = nullptr;
78 _textBorder = _textBorderRight = 0;
79 _surface = nullptr;
80 _unused4 = 0;
81 }
82
~CGameObject()83 CGameObject::~CGameObject() {
84 delete _surface;
85 delete _text;
86 }
87
save(SimpleFile * file,int indent)88 void CGameObject::save(SimpleFile *file, int indent) {
89 file->writeNumberLine(7, indent);
90 _movieRangeInfoList.destroyContents();
91
92 if (_surface) {
93 const CMovieRangeInfoList *rangeList = _surface->getMovieRangeInfo();
94
95 if (rangeList) {
96 for (CMovieRangeInfoList::const_iterator i = rangeList->begin();
97 i != rangeList->end(); ++i) {
98 CMovieRangeInfo *rangeInfo = new CMovieRangeInfo(*i);
99 rangeInfo->_initialFrame = (i == rangeList->begin()) ? getMovieFrame() : -1;
100 _movieRangeInfoList.push_back(rangeInfo);
101 }
102 }
103 }
104
105 _movieRangeInfoList.save(file, indent);
106 _movieRangeInfoList.destroyContents();
107
108 file->writeNumberLine(getMovieFrame(), indent + 1);
109 file->writeNumberLine(_cursorId, indent + 1);
110 _movieClips.save(file, indent + 1);
111 file->writeNumberLine(_handleMouseFlag, indent + 1);
112 file->writeNumberLine(_nonvisual, indent + 1);
113 file->writeQuotedLine(_resource, indent + 1);
114 file->writeBounds(_bounds, indent + 1);
115
116 file->writeFloatLine(_unused1, indent + 1);
117 file->writeFloatLine(_unused2, indent + 1);
118 file->writeFloatLine(_unused3, indent + 1);
119
120 file->writeNumberLine(_toggleR, indent + 1);
121 file->writeNumberLine(_toggleG, indent + 1);
122 file->writeNumberLine(_toggleB, indent + 1);
123 file->writeNumberLine(_unused4, indent + 1);
124 file->writeNumberLine(_visible, indent + 1);
125 file->writeNumberLine(_isPendingMail, indent + 1);
126 file->writeNumberLine(_destRoomFlags, indent + 1);
127 file->writeNumberLine(_roomFlags, indent + 1);
128
129 if (_surface) {
130 _surface->_resourceKey.save(file, indent);
131 } else {
132 CResourceKey resourceKey;
133 resourceKey.save(file, indent);
134 }
135 file->writeNumberLine(_surface != nullptr, indent);
136
137 CNamedItem::save(file, indent);
138 }
139
load(SimpleFile * file)140 void CGameObject::load(SimpleFile *file) {
141 int val = file->readNumber();
142 CResourceKey resourceKey;
143
144 switch (val) {
145 case 7:
146 _movieRangeInfoList.load(file);
147 _frameNumber = file->readNumber();
148 // Intentional fall-through
149
150 case 6:
151 _cursorId = (CursorId)file->readNumber();
152 // Intentional fall-through
153
154 case 5:
155 _movieClips.load(file);
156 // Intentional fall-through
157
158 case 4:
159 _handleMouseFlag = file->readNumber();
160 // Intentional fall-through
161
162 case 3:
163 _nonvisual = file->readNumber();
164 // Intentional fall-through
165
166 case 2:
167 _resource = file->readString();
168 // Intentional fall-through
169
170 case 1:
171 _bounds = file->readBounds();
172 _unused1 = file->readFloat();
173 _unused2 = file->readFloat();
174 _unused3 = file->readFloat();
175 _toggleR = file->readNumber();
176 _toggleG = file->readNumber();
177 _toggleB = file->readNumber();
178 _unused4 = file->readNumber();
179 _visible = file->readNumber() != 0;
180 _isPendingMail = file->readNumber();
181 _destRoomFlags = file->readNumber();
182 _roomFlags = file->readNumber();
183
184 resourceKey.load(file);
185 _surface = nullptr;
186 val = file->readNumber();
187 if (val) {
188 _resource = resourceKey.getString();
189 }
190 break;
191
192 default:
193 break;
194 }
195
196 CNamedItem::load(file);
197 }
198
draw(CScreenManager * screenManager)199 void CGameObject::draw(CScreenManager *screenManager) {
200 if (!_visible)
201 return;
202 if (_credits && _credits->_objectP == this) {
203 if (!_credits->draw())
204 CGameObject::deinit();
205
206 return;
207 }
208
209 if (_nonvisual) {
210 // If a text is defined, handle drawing it
211 if (_text && _bounds.intersects(getGameManager()->_bounds))
212 _text->draw(screenManager);
213
214 return;
215 } else {
216 if (!_surface) {
217 if (!_resource.empty()) {
218 loadResource(_resource);
219 _resource = "";
220 }
221 }
222
223 if (_surface) {
224 _bounds.setWidth(_surface->getWidth());
225 _bounds.setHeight(_surface->getHeight());
226
227 if (!_bounds.width() || !_bounds.height())
228 return;
229
230 if (_frameNumber >= 0) {
231 loadFrame(_frameNumber);
232 _frameNumber = -1;
233 }
234
235 if (!_movieRangeInfoList.empty())
236 processMoveRangeInfo();
237
238 if (_bounds.intersects(getGameManager()->_bounds)) {
239 if (_surface) {
240 Point destPos(_bounds.left, _bounds.top);
241 screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &destPos);
242 }
243
244 if (_text)
245 _text->draw(screenManager);
246 }
247 }
248 }
249 }
250
getBounds() const251 Rect CGameObject::getBounds() const {
252 return (_surface && _surface->hasFrame()) ? _bounds : Rect();
253 }
254
freeSurface()255 void CGameObject::freeSurface() {
256 // Handle freeing the surfaces of objects when their view is left
257 if (_surface) {
258 _resource = _surface->_resourceKey.getString();
259 _initialFrame = getMovieFrame();
260
261 delete _surface;
262 _surface = nullptr;
263 }
264 }
265
stopMovie()266 void CGameObject::stopMovie() {
267 if (_surface)
268 _surface->stopMovie();
269 }
270
checkPoint(const Point & pt,bool ignoreSurface,bool visibleOnly)271 bool CGameObject::checkPoint(const Point &pt, bool ignoreSurface, bool visibleOnly) {
272 if ((!_visible && visibleOnly) || !_bounds.contains(pt))
273 return false;
274
275 if (ignoreSurface || _nonvisual)
276 return true;
277
278 if (!_surface) {
279 if (_frameNumber == -1)
280 return true;
281 loadFrame(_frameNumber);
282 if (!_surface)
283 return true;
284 }
285
286 Common::Point pixelPos = pt - _bounds;
287 if (_surface->_flipVertically) {
288 pixelPos.y = ((_bounds.height() - _bounds.top) / 2) * 2 - pixelPos.y;
289 }
290
291 uint transColor = _surface->getTransparencyColor();
292 uint pixel = _surface->getPixel(pixelPos);
293 return pixel != transColor;
294 }
295
findPoint(Quadrant quadrant,Point & pt)296 bool CGameObject::findPoint(Quadrant quadrant, Point &pt) {
297 // Start by checking a centroid point in the bounds
298 if (!_bounds.isEmpty()) {
299 pt = _bounds.getPoint(quadrant);
300 if (checkPoint(pt, false, true))
301 return true;
302 }
303
304 // Scan through all the area of the bounds to find a valid point
305 for (; pt.y < _bounds.bottom; ++pt.y, pt.x = _bounds.left) {
306 for (; pt.x < _bounds.right; ++pt.x) {
307 if (checkPoint(pt, false, true))
308 return true;
309 }
310 }
311
312 pt = Point(0, 0);
313 return false;
314 }
315
clipRect(const Rect & rect1,Rect & rect2) const316 bool CGameObject::clipRect(const Rect &rect1, Rect &rect2) const {
317 if (!rect2.intersects(rect1))
318 return false;
319
320 rect2.clip(rect1);
321 return true;
322 }
323
draw(CScreenManager * screenManager,const Rect & destRect,const Rect & srcRect)324 void CGameObject::draw(CScreenManager *screenManager, const Rect &destRect, const Rect &srcRect) {
325 Rect tempRect = destRect;
326 if (clipRect(srcRect, tempRect)) {
327 if (!_surface && !_resource.empty()) {
328 loadResource(_resource);
329 _resource.clear();
330 }
331
332 if (_surface)
333 screenManager->blitFrom(SURFACE_PRIMARY, &tempRect, _surface);
334 }
335 }
336
draw(CScreenManager * screenManager,const Point & destPos)337 void CGameObject::draw(CScreenManager *screenManager, const Point &destPos) {
338 if (!_surface && !_resource.empty()) {
339 loadResource(_resource);
340 _resource.clear();
341 }
342
343 if (_surface) {
344 int xSize = _surface->getWidth();
345 int ySize = _surface->getHeight();
346
347 if (xSize > 0 && ySize > 0) {
348 screenManager->blitFrom(SURFACE_BACKBUFFER, _surface, &destPos);
349 }
350 }
351 }
352
draw(CScreenManager * screenManager,const Point & destPos,const Rect & srcRect)353 void CGameObject::draw(CScreenManager *screenManager, const Point &destPos, const Rect &srcRect) {
354 draw(screenManager, Rect(destPos.x, destPos.y, destPos.x + 52, destPos.y + 52), srcRect);
355 }
356
isPet() const357 bool CGameObject::isPet() const {
358 return isInstanceOf(CPetControl::_type);
359 }
360
loadResource(const CString & name)361 void CGameObject::loadResource(const CString &name) {
362 switch (name.fileTypeSuffix()) {
363 case FILETYPE_IMAGE:
364 loadImage(name);
365 break;
366 case FILETYPE_MOVIE:
367 loadMovie(name);
368 break;
369 default:
370 break;
371 }
372 }
373
loadMovie(const CString & name,bool pendingFlag)374 void CGameObject::loadMovie(const CString &name, bool pendingFlag) {
375 g_vm->_filesManager->preload(name);
376
377 // Create the surface if it doesn't already exist
378 if (!_surface) {
379 CGameManager *gameManager = getGameManager();
380 _surface = new OSVideoSurface(gameManager->setScreenManager(), nullptr);
381 }
382
383 // Load the new movie resource
384 CResourceKey key(name);
385 _surface->loadResource(key);
386
387 if (_surface->hasSurface() && !pendingFlag) {
388 _bounds.setWidth(_surface->getWidth());
389 _bounds.setHeight(_surface->getHeight());
390 }
391
392 if (_initialFrame)
393 loadFrame(_initialFrame);
394 }
395
loadImage(const CString & name,bool pendingFlag)396 void CGameObject::loadImage(const CString &name, bool pendingFlag) {
397 // Get a refernce to the game and screen managers
398 CGameManager *gameManager = getGameManager();
399 CScreenManager *screenManager;
400
401 if (gameManager && (screenManager = CScreenManager::setCurrent()) != nullptr) {
402 // Destroy the object's surface if it already had one
403 if (_surface) {
404 delete _surface;
405 _surface = nullptr;
406 }
407
408 g_vm->_filesManager->preload(name);
409
410 if (!name.empty()) {
411 _surface = new OSVideoSurface(screenManager, CResourceKey(name), pendingFlag);
412 }
413
414 if (_surface && !pendingFlag) {
415 _bounds.right = _surface->getWidth();
416 _bounds.bottom = _surface->getHeight();
417 }
418
419 // Mark the object's area as dirty, so that on the next frame rendering
420 // this object will be redrawn
421 makeDirty();
422 }
423
424 _initialFrame = 0;
425 }
426
loadFrame(int frameNumber)427 void CGameObject::loadFrame(int frameNumber) {
428 _frameNumber = -1;
429
430 if (!_surface && !_resource.empty()) {
431 loadResource(_resource);
432 _resource.clear();
433 }
434
435 if (_surface)
436 _surface->setMovieFrame(frameNumber);
437
438 makeDirty();
439 }
440
processMoveRangeInfo()441 void CGameObject::processMoveRangeInfo() {
442 for (CMovieRangeInfoList::iterator i = _movieRangeInfoList.begin(); i != _movieRangeInfoList.end(); ++i)
443 (*i)->process(this);
444
445 _movieRangeInfoList.destroyContents();
446 }
447
makeDirty(const Rect & r)448 void CGameObject::makeDirty(const Rect &r) {
449 CGameManager *gameManager = getGameManager();
450 if (gameManager)
451 gameManager->addDirtyRect(r);
452 }
453
makeDirty()454 void CGameObject::makeDirty() {
455 makeDirty(_bounds);
456 }
457
isSoundActive(int handle) const458 bool CGameObject::isSoundActive(int handle) const {
459 if (handle != 0 && handle != -1) {
460 CGameManager *gameManager = getGameManager();
461 if (gameManager)
462 return gameManager->_sound.isActive(handle);
463 }
464
465 return false;
466 }
467
playAmbientSound(const CString & resName,VolumeMode mode,bool initialMute,bool repeated,int handleIndex,Audio::Mixer::SoundType soundType)468 void CGameObject::playAmbientSound(const CString &resName, VolumeMode mode, bool initialMute, bool repeated,
469 int handleIndex, Audio::Mixer::SoundType soundType) {
470 if (handleIndex < 0 || handleIndex > 3)
471 return;
472 CGameManager *gameManager = getGameManager();
473 if (!gameManager)
474 return;
475
476 // Preload the file, and stop any existing sound using the given slot
477 CSound &sound = gameManager->_sound;
478 g_vm->_filesManager->preload(resName);
479 if (_soundHandles[handleIndex] != -1) {
480 sound.stopSound(_soundHandles[handleIndex]);
481 _soundHandles[handleIndex] = -1;
482 }
483
484 // If no new name specified, then exit
485 if (resName.empty())
486 return;
487
488 uint newVolume = sound._soundManager.getModeVolume(mode);
489 uint volume = initialMute ? 0 : newVolume;
490
491 CProximity prox;
492 prox._channelVolume = volume;
493 prox._repeated = repeated;
494 prox._soundType = soundType;
495
496 switch (handleIndex) {
497 case 0:
498 prox._channelMode = 6;
499 break;
500 case 1:
501 prox._channelMode = 7;
502 break;
503 case 2:
504 prox._channelMode = 8;
505 break;
506 case 3:
507 prox._channelMode = 9;
508 break;
509 default:
510 break;
511 }
512
513 _soundHandles[handleIndex] = sound.playSound(resName, prox);
514
515 if (_soundHandles[handleIndex])
516 sound.setVolume(_soundHandles[handleIndex], newVolume, 2);
517 }
518
setSoundVolume(int handle,uint percent,uint seconds)519 void CGameObject::setSoundVolume(int handle, uint percent, uint seconds) {
520 if (handle != 0 && handle != -1) {
521 CGameManager *gameManager = getGameManager();
522 if (gameManager)
523 return gameManager->_sound.setVolume(handle, percent, seconds);
524 }
525 }
526
stopAmbientSound(bool transition,int handleIndex)527 void CGameObject::stopAmbientSound(bool transition, int handleIndex) {
528 CGameManager *gameManager = getGameManager();
529 if (!gameManager)
530 return;
531 CSound &sound = gameManager->_sound;
532
533 if (handleIndex == -1) {
534 for (int idx = 0; idx < 4; ++idx) {
535 if (_soundHandles[idx] != -1) {
536 sound.setVolume(_soundHandles[idx], 0, transition ? 1 : 0);
537 sound.setCanFree(_soundHandles[idx]);
538 _soundHandles[idx] = -1;
539 }
540 }
541 } else if (handleIndex >= 0 && handleIndex <= 2 && _soundHandles[handleIndex] != -1) {
542 if (transition) {
543 // Transitioning to silent over 1 second
544 sound.setVolume(_soundHandles[handleIndex], 0, 1);
545 sleep(1000);
546 }
547
548 sound.stopSound(_soundHandles[handleIndex]);
549 _soundHandles[handleIndex] = -1;
550 }
551 }
552
setAmbientSoundVolume(VolumeMode mode,uint seconds,int handleIndex)553 void CGameObject::setAmbientSoundVolume(VolumeMode mode, uint seconds, int handleIndex) {
554 CGameManager *gameManager = getGameManager();
555 if (!gameManager)
556 return;
557 CSound &sound = gameManager->_sound;
558
559 if (handleIndex == -1) {
560 // Iterate through calling the method for each handle
561 for (int idx = 0; idx < 3; ++idx)
562 setAmbientSoundVolume(mode, seconds, idx);
563 } else if (handleIndex >= 0 && handleIndex <= 3 && _soundHandles[handleIndex] != -1) {
564 uint newVolume = sound._soundManager.getModeVolume(mode);
565 sound.setVolume(_soundHandles[handleIndex], newVolume, seconds);
566 }
567 }
568
stopSoundChannel(bool channel3)569 void CGameObject::stopSoundChannel(bool channel3) {
570 getGameManager()->_sound.stopChannel(channel3 ? 3 : 0);
571 }
572
setVisible(bool val)573 void CGameObject::setVisible(bool val) {
574 if (val != _visible) {
575 _visible = val;
576 makeDirty();
577 }
578 }
579
petHighlightGlyph(int val)580 void CGameObject::petHighlightGlyph(int val) {
581 CPetControl *pet = getPetControl();
582 if (pet)
583 pet->highlightGlyph(val);
584 }
585
petHideCursor()586 void CGameObject::petHideCursor() {
587 CPetControl *pet = getPetControl();
588 if (pet)
589 pet->hideCursor();
590 }
591
petShowCursor()592 void CGameObject::petShowCursor() {
593 CPetControl *pet = getPetControl();
594 if (pet)
595 pet->showCursor();
596 }
597
petShow()598 void CGameObject::petShow() {
599 CGameManager *gameManager = getGameManager();
600 if (gameManager) {
601 gameManager->_gameState._petActive = true;
602 gameManager->_gameState.setMode(GSMODE_INTERACTIVE);
603 gameManager->markAllDirty();
604 }
605 }
606
petHide()607 void CGameObject::petHide() {
608 CGameManager *gameManager = getGameManager();
609 if (gameManager) {
610 gameManager->_gameState._petActive = false;
611 gameManager->_gameState.setMode(GSMODE_INTERACTIVE);
612 gameManager->markAllDirty();
613 }
614 }
615
petIncAreaLocks()616 void CGameObject::petIncAreaLocks() {
617 CPetControl *pet = getPetControl();
618 if (pet)
619 pet->incAreaLocks();
620 }
621
petDecAreaLocks()622 void CGameObject::petDecAreaLocks() {
623 CPetControl *pet = getPetControl();
624 if (pet)
625 pet->decAreaLocks();
626 }
627
petSetRemoteTarget()628 void CGameObject::petSetRemoteTarget() {
629 CPetControl *pet = getPetControl();
630 if (pet)
631 pet->setRemoteTarget(this);
632 }
633
playMovie(uint flags)634 void CGameObject::playMovie(uint flags) {
635 _frameNumber = -1;
636
637 if (!_surface && !_resource.empty()) {
638 loadResource(_resource);
639 _resource.clear();
640 }
641
642 CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
643 if (_surface) {
644 _surface->playMovie(flags, obj);
645 if (flags & MOVIE_WAIT_FOR_FINISH)
646 getGameManager()->_gameState.addMovie(_surface->_movie);
647 }
648 }
649
playMovie(int startFrame,int endFrame,uint flags)650 void CGameObject::playMovie(int startFrame, int endFrame, uint flags) {
651 _frameNumber = -1;
652
653 if (!_surface && !_resource.empty()) {
654 loadResource(_resource);
655 _resource.clear();
656 }
657
658 CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
659 if (_surface) {
660 _surface->playMovie(startFrame, endFrame, flags, obj);
661 if (flags & MOVIE_WAIT_FOR_FINISH)
662 getGameManager()->_gameState.addMovie(_surface->_movie);
663 }
664 }
665
666
playMovie(int startFrame,int endFrame,int initialFrame,uint flags)667 void CGameObject::playMovie(int startFrame, int endFrame, int initialFrame, uint flags) {
668 _frameNumber = -1;
669
670 if (!_surface && !_resource.empty()) {
671 loadResource(_resource);
672 _resource.clear();
673 }
674
675 CGameObject *obj = (flags & MOVIE_NOTIFY_OBJECT) ? this : nullptr;
676 if (_surface) {
677 _surface->playMovie(startFrame, endFrame, initialFrame, flags, obj);
678 if (flags & MOVIE_WAIT_FOR_FINISH)
679 getGameManager()->_gameState.addMovie(_surface->_movie);
680 }
681 }
682
playClip(const CString & name,uint flags)683 void CGameObject::playClip(const CString &name, uint flags) {
684 debugC(DEBUG_DETAILED, kDebugScripts, "playClip - %s", name.c_str());
685
686 _frameNumber = -1;
687 CMovieClip *clip = _movieClips.findByName(name);
688 if (clip)
689 playMovie(clip->_startFrame, clip->_endFrame, flags);
690 }
691
playClip(uint startFrame,uint endFrame)692 void CGameObject::playClip(uint startFrame, uint endFrame) {
693 debugC(DEBUG_DETAILED, kDebugScripts, "playClip - %d to %d", startFrame, endFrame);
694
695 CMovieClip *clip = new CMovieClip("", startFrame, endFrame);
696 CGameManager *gameManager = getGameManager();
697 CRoomItem *room = gameManager->getRoom();
698
699 gameManager->playClip(clip, room, room);
700 delete clip;
701 }
702
playRandomClip(const char * const * names,uint flags)703 void CGameObject::playRandomClip(const char *const *names, uint flags) {
704 // Count size of array
705 int count = 0;
706 for (const char *const *p = names; *p; ++p)
707 ++count;
708
709 // Play clip
710 const char *name = names[g_vm->getRandomNumber(count - 1)];
711 playClip(name, flags);
712 }
713
playCutscene(uint startFrame,uint endFrame)714 bool CGameObject::playCutscene(uint startFrame, uint endFrame) {
715 if (!_surface) {
716 if (!_resource.empty())
717 loadResource(_resource);
718 _resource.clear();
719 }
720
721 bool result = true;
722 if (_surface && _surface->loadIfReady() && _surface->_movie) {
723 disableMouse();
724 result = _surface->_movie->playCutscene(_bounds, startFrame, endFrame);
725 enableMouse();
726 }
727
728 return result;
729 }
730
savePosition()731 void CGameObject::savePosition() {
732 _savedPos = _bounds;
733 }
734
resetPosition()735 void CGameObject::resetPosition() {
736 setPosition(_savedPos);
737 }
738
setPosition(const Point & newPos)739 void CGameObject::setPosition(const Point &newPos) {
740 makeDirty();
741 _bounds.moveTo(newPos);
742 makeDirty();
743 }
744
checkStartDragging(CMouseDragStartMsg * msg)745 bool CGameObject::checkStartDragging(CMouseDragStartMsg *msg) {
746 if (_visible && checkPoint(msg->_mousePos, msg->_handled, 1)) {
747 savePosition();
748 msg->_dragItem = this;
749 return true;
750 } else {
751 return false;
752 }
753 }
754
hasActiveMovie() const755 bool CGameObject::hasActiveMovie() const {
756 if (_surface && _surface->_movie)
757 return _surface->_movie->isActive();
758 return false;
759 }
760
getMovieFrame() const761 int CGameObject::getMovieFrame() const {
762 if (_surface && _surface->_movie)
763 return _surface->_movie->getFrame();
764 else if (_frameNumber > 0)
765 // WORKAROUND: If an object has a pending frame to be set to,
766 // but the movie hasn't yet been loaded, return that frame
767 return _frameNumber;
768
769 return _initialFrame;
770 }
771
surfaceHasFrame() const772 bool CGameObject::surfaceHasFrame() const {
773 return _surface ? _surface->hasFrame() : false;
774 }
775
loadSound(const CString & name)776 void CGameObject::loadSound(const CString &name) {
777 CGameManager *gameManager = getGameManager();
778 if (gameManager) {
779 g_vm->_filesManager->preload(name);
780 if (!name.empty())
781 gameManager->_sound.loadSound(name);
782 }
783 }
784
playSound(const CString & name,uint volume,int balance,bool repeated)785 int CGameObject::playSound(const CString &name, uint volume, int balance, bool repeated) {
786 CProximity prox;
787 prox._channelVolume = volume;
788 prox._balance = balance;
789 prox._repeated = repeated;
790 return playSound(name, prox);
791 }
792
playSound(const CString & name,CProximity & prox)793 int CGameObject::playSound(const CString &name, CProximity &prox) {
794 if (prox._positioningMode == POSMODE_VECTOR) {
795 // If the proximity doesn't have a position defined, default it to
796 // the position of the view to which the game object belongs
797 if (prox._posX == 0.0 && prox._posY == 0.0 && prox._posZ == 0.0)
798 findView()->getPosition(prox._posX, prox._posY, prox._posZ);
799 }
800
801 CGameManager *gameManager = getGameManager();
802 if (gameManager && !name.empty()) {
803 g_vm->_filesManager->preload(name);
804
805 return gameManager->_sound.playSound(name, prox);
806 }
807
808 return -1;
809 }
810
queueSound(const CString & name,uint priorHandle,uint volume,int balance,bool repeated,Audio::Mixer::SoundType soundType)811 int CGameObject::queueSound(const CString &name, uint priorHandle, uint volume, int balance, bool repeated,
812 Audio::Mixer::SoundType soundType) {
813 CProximity prox;
814 prox._balance = balance;
815 prox._repeated = repeated;
816 prox._channelVolume = volume;
817 prox._priorSoundHandle = priorHandle;
818 prox._soundType = soundType;
819
820 return playSound(name, prox);
821 }
822
stopSound(int handle,uint seconds)823 void CGameObject::stopSound(int handle, uint seconds) {
824 if (handle != 0 && handle != -1) {
825 CGameManager *gameManager = getGameManager();
826 if (gameManager) {
827 if (seconds) {
828 gameManager->_sound.setVolume(handle, 0, seconds);
829 gameManager->_sound.setCanFree(handle);
830 } else {
831 gameManager->_sound.stopSound(handle);
832 }
833 }
834 }
835 }
836
addTimer(int endVal,uint firstDuration,uint repeatDuration)837 int CGameObject::addTimer(int endVal, uint firstDuration, uint repeatDuration) {
838 CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration != 0,
839 firstDuration, repeatDuration, this, endVal, CString());
840
841 getGameManager()->addTimer(timer);
842 return timer->_id;
843 }
844
addTimer(uint firstDuration,uint repeatDuration)845 int CGameObject::addTimer(uint firstDuration, uint repeatDuration) {
846 CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration != 0,
847 firstDuration, repeatDuration, this, 0, CString());
848
849 CGameManager *gameMan = getGameManager();
850 if (gameMan)
851 gameMan->addTimer(timer);
852 return timer->_id;
853 }
854
stopTimer(int id)855 void CGameObject::stopTimer(int id) {
856 CGameManager *gameMan = getGameManager();
857 if (gameMan)
858 gameMan->stopTimer(id);
859 }
860
startAnimTimer(const CString & action,uint firstDuration,uint repeatDuration)861 int CGameObject::startAnimTimer(const CString &action, uint firstDuration, uint repeatDuration) {
862 CGameManager *gameMan = getGameManager();
863 if (gameMan) {
864 CTimeEventInfo *timer = new CTimeEventInfo(getTicksCount(), repeatDuration > 0,
865 firstDuration, repeatDuration, this, 0, action);
866 gameMan->addTimer(timer);
867 return timer->_id;
868 }
869
870 return -1;
871 }
872
stopAnimTimer(int id)873 void CGameObject::stopAnimTimer(int id) {
874 CGameManager *gameMan = getGameManager();
875 if (gameMan)
876 gameMan->stopTimer(id);
877 }
878
gotoView(const CString & viewName,const CString & clipName)879 void CGameObject::gotoView(const CString &viewName, const CString &clipName) {
880 CViewItem *newView = parseView(viewName);
881 CGameManager *gameManager = getGameManager();
882 CViewItem *oldView = gameManager->getView();
883 if (!oldView || !newView)
884 return;
885
886 CMovieClip *clip = nullptr;
887 if (clipName.empty()) {
888 CLinkItem *link = oldView->findLink(newView);
889 if (link)
890 clip = link->getClip();
891 } else {
892 clip = oldView->findNode()->findRoom()->findClip(clipName);
893 }
894
895 // Change the view
896 gameManager->_gameState.changeView(newView, clip);
897 }
898
parseView(const CString & viewString)899 CViewItem *CGameObject::parseView(const CString &viewString) {
900 return getRoot()->parseView(viewString);
901 }
902
getViewFullName() const903 CString CGameObject::getViewFullName() const {
904 CGameManager *gameManager = getGameManager();
905 CViewItem *view = gameManager->getView();
906 CNodeItem *node = view->findNode();
907 CRoomItem *room = node->findRoom();
908
909 return CString::format("%s.%s.%s", room->getName().c_str(),
910 node->getName().c_str(), view->getName().c_str());
911 }
912
sleep(uint milli)913 void CGameObject::sleep(uint milli) {
914 // Use an empty event target so that standard scene drawing won't happen
915 Events &events = *g_vm->_events;
916 CEventTarget nullTarget;
917 events.addTarget(&nullTarget);
918 events.sleep(milli);
919 events.removeTarget();
920 }
921
getMousePos() const922 Point CGameObject::getMousePos() const {
923 return getGameManager()->_gameState.getMousePos();
924 }
925
compareViewNameTo(const CString & name) const926 bool CGameObject::compareViewNameTo(const CString &name) const {
927 return !getViewFullName().compareToIgnoreCase(name);
928 }
929
compareRoomNameTo(const CString & name)930 bool CGameObject::compareRoomNameTo(const CString &name) {
931 CRoomItem *room = getGameManager()->getRoom();
932 return !room->getName().compareToIgnoreCase(name);
933 }
934
getRoomName() const935 CString CGameObject::getRoomName() const {
936 CRoomItem *room = getRoom();
937 return room ? room->getName() : CString();
938 }
939
getRoomNodeName() const940 CString CGameObject::getRoomNodeName() const {
941 CNodeItem *node = getNode();
942 if (!node)
943 return CString();
944
945 CRoomItem *room = node->findRoom();
946
947 return CString::format("%s.%s", room->getName().c_str(), node->getName().c_str());
948 }
949
getFullViewName()950 CString CGameObject::getFullViewName() {
951 CGameManager *gameManager = getGameManager();
952 return gameManager ? gameManager->getFullViewName() : CString();
953 }
954
getMailManFirstObject() const955 CGameObject *CGameObject::getMailManFirstObject() const {
956 CMailMan *mailMan = getMailMan();
957 return mailMan ? mailMan->getFirstObject() : nullptr;
958 }
959
getMailManNextObject(CGameObject * prior) const960 CGameObject *CGameObject::getMailManNextObject(CGameObject *prior) const {
961 CMailMan *mailMan = getMailMan();
962 return mailMan ? mailMan->getNextObject(prior) : nullptr;
963 }
964
findMailByFlags(RoomFlagsComparison compareType,uint roomFlags)965 CGameObject *CGameObject::findMailByFlags(RoomFlagsComparison compareType, uint roomFlags) {
966 CMailMan *mailMan = getMailMan();
967 if (!mailMan)
968 return nullptr;
969
970 for (CGameObject *obj = mailMan->getFirstObject(); obj;
971 obj = mailMan->getNextObject(obj)) {
972 if (compareRoomFlags(compareType, obj->_roomFlags, roomFlags))
973 return obj;
974 }
975
976 return nullptr;
977 }
978
getNextMail(CGameObject * prior)979 CGameObject *CGameObject::getNextMail(CGameObject *prior) {
980 CMailMan *mailMan = getMailMan();
981 return mailMan ? mailMan->getNextObject(prior) : nullptr;
982 }
983
findRoomObject(const CString & name) const984 CGameObject *CGameObject::findRoomObject(const CString &name) const {
985 return dynamic_cast<CGameObject *>(findRoom()->findByName(name));
986 }
987
findInRoom(const CString & name)988 CGameObject *CGameObject::findInRoom(const CString &name) {
989 CRoomItem *room = getRoom();
990 return room ? dynamic_cast<CGameObject *>(room->findByName(name)) : nullptr;
991 }
992
find(const CString & name,CGameObject ** item,int findAreas)993 Found CGameObject::find(const CString &name, CGameObject **item, int findAreas) {
994 CGameObject *go;
995 *item = nullptr;
996
997 // Scan under PET if flagged
998 if (findAreas & FIND_PET) {
999 for (go = getPetControl()->getFirstObject(); go; go = getPetControl()->getNextObject(go)) {
1000 if (go->getName() == name) {
1001 *item = go;
1002 return FOUND_PET;
1003 }
1004 }
1005 }
1006
1007 if (findAreas & FIND_MAILMAN) {
1008 for (go = getMailManFirstObject(); go; go = getMailManNextObject(go)) {
1009 if (go->getName() == name) {
1010 *item = go;
1011 return FOUND_MAILMAN;
1012 }
1013 }
1014 }
1015
1016 if (findAreas & FIND_GLOBAL) {
1017 go = dynamic_cast<CGameObject *>(getRoot()->findByName(name));
1018 if (go) {
1019 *item = go;
1020 return FOUND_GLOBAL;
1021 }
1022 }
1023
1024 if (findAreas & FIND_ROOM) {
1025 go = findRoomObject(name);
1026 if (go) {
1027 *item = go;
1028 return FOUND_ROOM;
1029 }
1030 }
1031
1032 return FOUND_NONE;
1033 }
1034
moveToView()1035 void CGameObject::moveToView() {
1036 CViewItem *view = getGameManager()->getView();
1037 detach();
1038 addUnder(view);
1039 }
1040
moveToView(const CString & name)1041 void CGameObject::moveToView(const CString &name) {
1042 CViewItem *view = parseView(name);
1043 detach();
1044 addUnder(view);
1045 }
1046
stateChangeSeason()1047 void CGameObject::stateChangeSeason() {
1048 getGameManager()->_gameState.changeSeason();
1049 }
1050
stateGetSeason() const1051 Season CGameObject::stateGetSeason() const {
1052 return getGameManager()->_gameState._seasonNum;
1053 }
1054
stateSetParrotMet()1055 void CGameObject::stateSetParrotMet() {
1056 getGameManager()->_gameState.setParrotMet(true);
1057 }
1058
stateGetParrotMet() const1059 bool CGameObject::stateGetParrotMet() const {
1060 return getGameManager()->_gameState.getParrotMet();
1061 }
1062
incParrotResponse()1063 void CGameObject::incParrotResponse() {
1064 getGameManager()->_gameState.incParrotResponse();
1065 }
1066
getParrotResponse() const1067 int CGameObject::getParrotResponse() const {
1068 return getGameManager()->_gameState._parrotResponseIndex;
1069 }
1070
quitGame()1071 void CGameObject::quitGame() {
1072 getGameManager()->_gameState._quitGame = true;
1073 }
1074
incTransitions()1075 void CGameObject::incTransitions() {
1076 getGameManager()->incTransitions();
1077 }
1078
decTransitions()1079 void CGameObject::decTransitions() {
1080 getGameManager()->decTransitions();
1081 }
1082
setMovieFrameRate(double rate)1083 void CGameObject::setMovieFrameRate(double rate) {
1084 if (_surface)
1085 _surface->setMovieFrameRate(rate);
1086 }
1087
setText(const CString & str,int border,int borderRight)1088 void CGameObject::setText(const CString &str, int border, int borderRight) {
1089 if (!_text)
1090 _text = new CTextControl();
1091 _textBorder = border;
1092 _textBorderRight = borderRight;
1093
1094 setTextBounds();
1095 _text->setText(str);
1096 CScreenManager *screenManager = getGameManager()->setScreenManager();
1097 _text->scrollToTop(screenManager);
1098 }
1099
setTextHasBorders(bool hasBorders)1100 void CGameObject::setTextHasBorders(bool hasBorders) {
1101 if (!_text)
1102 _text = new CTextControl();
1103
1104 _text->setHasBorder(hasBorders);
1105 }
1106
setTextBounds()1107 void CGameObject::setTextBounds() {
1108 Rect rect = _bounds;
1109 rect.grow(_textBorder);
1110 rect.right -= _textBorderRight;
1111
1112 _text->setBounds(rect);
1113 makeDirty();
1114 }
1115
setTextColor(byte r,byte g,byte b)1116 void CGameObject::setTextColor(byte r, byte g, byte b) {
1117 if (!_text)
1118 _text = new CTextControl();
1119
1120 _text->setColor(r, g, b);
1121 }
1122
setTextFontNumber(int fontNumber)1123 void CGameObject::setTextFontNumber(int fontNumber) {
1124 if (!_text)
1125 _text = new CTextControl();
1126
1127 _text->setFontNumber(fontNumber);
1128 }
1129
getTextWidth() const1130 int CGameObject::getTextWidth() const {
1131 assert(_text);
1132 return _text->getTextWidth(CScreenManager::_screenManagerPtr);
1133 }
1134
getTextCursor() const1135 CTextCursor *CGameObject::getTextCursor() const {
1136 return CScreenManager::_screenManagerPtr->_textCursor;
1137 }
1138
getMovement() const1139 Movement CGameObject::getMovement() const {
1140 return CLinkItem::getMovementFromCursor(_cursorId);
1141 }
1142
scrollTextUp()1143 void CGameObject::scrollTextUp() {
1144 if (_text)
1145 _text->scrollUp(CScreenManager::_screenManagerPtr);
1146 makeDirty();
1147 }
1148
scrollTextDown()1149 void CGameObject::scrollTextDown() {
1150 if (_text)
1151 _text->scrollDown(CScreenManager::_screenManagerPtr);
1152 makeDirty();
1153 }
1154
lockMouse()1155 void CGameObject::lockMouse() {
1156 CGameManager *gameMan = getGameManager();
1157 gameMan->lockInputHandler();
1158
1159 if (CScreenManager::_screenManagerPtr->_mouseCursor)
1160 CScreenManager::_screenManagerPtr->_mouseCursor->incBusyCount();
1161 }
1162
unlockMouse()1163 void CGameObject::unlockMouse() {
1164 if (CScreenManager::_screenManagerPtr->_mouseCursor)
1165 CScreenManager::_screenManagerPtr->_mouseCursor->decBusyCount();
1166
1167 CGameManager *gameMan = getGameManager();
1168 gameMan->unlockInputHandler();
1169 }
1170
hideMouse()1171 void CGameObject::hideMouse() {
1172 CScreenManager::_screenManagerPtr->_mouseCursor->incHideCounter();
1173 }
1174
showMouse()1175 void CGameObject::showMouse() {
1176 CScreenManager::_screenManagerPtr->_mouseCursor->decHideCounter();
1177 }
1178
disableMouse()1179 void CGameObject::disableMouse() {
1180 lockInputHandler();
1181 hideMouse();
1182 }
1183
enableMouse()1184 void CGameObject::enableMouse() {
1185 unlockInputHandler();
1186 showMouse();
1187 }
1188
mouseDisableControl()1189 void CGameObject::mouseDisableControl() {
1190 CScreenManager::_screenManagerPtr->_mouseCursor->disableControl();
1191 }
1192
mouseEnableControl()1193 void CGameObject::mouseEnableControl() {
1194 CScreenManager::_screenManagerPtr->_mouseCursor->enableControl();
1195 }
1196
mouseSetPosition(const Point & pt,double rate)1197 void CGameObject::mouseSetPosition(const Point &pt, double rate) {
1198 CScreenManager::_screenManagerPtr->_mouseCursor->setPosition(pt, rate);
1199 }
1200
lockInputHandler()1201 void CGameObject::lockInputHandler() {
1202 getGameManager()->lockInputHandler();
1203 }
1204
unlockInputHandler()1205 void CGameObject::unlockInputHandler() {
1206 getGameManager()->unlockInputHandler();
1207 }
1208
loadSurface()1209 void CGameObject::loadSurface() {
1210 if (!_surface && !_resource.empty()) {
1211 loadResource(_resource);
1212 _resource.clear();
1213 }
1214
1215 if (_surface)
1216 _surface->loadIfReady();
1217 }
1218
changeView(const CString & viewName)1219 bool CGameObject::changeView(const CString &viewName) {
1220 return getRoot()->changeView(viewName, "");
1221 }
1222
changeView(const CString & viewName,const CString & clipName)1223 bool CGameObject::changeView(const CString &viewName, const CString &clipName) {
1224 return getRoot()->changeView(viewName, clipName);
1225 }
1226
dragMove(const Point & pt)1227 void CGameObject::dragMove(const Point &pt) {
1228 if (_surface) {
1229 _bounds.setWidth(_surface->getWidth());
1230 _bounds.setHeight(_surface->getHeight());
1231 }
1232
1233 setPosition(Point(pt.x - _bounds.width() / 2, pt.y - _bounds.height() / 2));
1234 }
1235
getDraggingObject() const1236 CGameObject *CGameObject::getDraggingObject() const {
1237 CTreeItem *item = getGameManager()->_dragItem;
1238 return dynamic_cast<CGameObject *>(item);
1239 }
1240
getControid() const1241 Point CGameObject::getControid() const {
1242 return Point(_bounds.left + _bounds.width() / 2,
1243 _bounds.top + _bounds.height() / 2);
1244 }
1245
clipExistsByStart(const CString & name,int startFrame) const1246 bool CGameObject::clipExistsByStart(const CString &name, int startFrame) const {
1247 return _movieClips.existsByStart(name, startFrame);
1248 }
1249
clipExistsByEnd(const CString & name,int endFrame) const1250 bool CGameObject::clipExistsByEnd(const CString &name, int endFrame) const {
1251 return _movieClips.existsByEnd(name, endFrame);
1252 }
1253
petClear() const1254 void CGameObject::petClear() const {
1255 CPetControl *petControl = getPetControl();
1256 if (petControl)
1257 petControl->resetRemoteTarget();
1258 }
1259
getDontSave() const1260 CDontSaveFileItem *CGameObject::getDontSave() const {
1261 CProjectItem *project = getRoot();
1262 return project ? project->getDontSaveFileItem() : nullptr;
1263 }
1264
getPetControl() const1265 CPetControl *CGameObject::getPetControl() const {
1266 return dynamic_cast<CPetControl *>(getDontSaveChild(CPetControl::_type));
1267 }
1268
getMailMan() const1269 CMailMan *CGameObject::getMailMan() const {
1270 return dynamic_cast<CMailMan *>(getDontSaveChild(CMailMan::_type));
1271 }
1272
getDontSaveChild(ClassDef * classDef) const1273 CTreeItem *CGameObject::getDontSaveChild(ClassDef *classDef) const {
1274 CProjectItem *root = getRoot();
1275 if (!root)
1276 return nullptr;
1277
1278 CDontSaveFileItem *dontSave = root->getDontSaveFileItem();
1279 if (!dontSave)
1280 return nullptr;
1281
1282 return dontSave->findChildInstanceOf(classDef);
1283 }
1284
getHiddenRoom() const1285 CRoomItem *CGameObject::getHiddenRoom() const {
1286 CProjectItem *root = getRoot();
1287 return root ? root->findHiddenRoom() : nullptr;
1288 }
1289
locateRoom(const CString & name) const1290 CRoomItem *CGameObject::locateRoom(const CString &name) const {
1291 if (name.empty())
1292 return nullptr;
1293
1294 CProjectItem *project = getRoot();
1295 for (CRoomItem *room = project->findFirstRoom(); room; room = project->findNextRoom(room)) {
1296 if (!room->getName().compareToIgnoreCase(name))
1297 return room;
1298 }
1299
1300 return nullptr;
1301 }
1302
getHiddenObject(const CString & name) const1303 CGameObject *CGameObject::getHiddenObject(const CString &name) const {
1304 CRoomItem *room = getHiddenRoom();
1305 return room ? dynamic_cast<CGameObject *>(findUnder(room, name)) : nullptr;
1306 }
1307
findUnder(CTreeItem * parent,const CString & name) const1308 CTreeItem *CGameObject::findUnder(CTreeItem *parent, const CString &name) const {
1309 if (!parent)
1310 return nullptr;
1311
1312 for (CTreeItem *item = parent->getFirstChild(); item; item = item->scan(parent)) {
1313 if (item->getName() == name)
1314 return item;
1315 }
1316
1317 return nullptr;
1318 }
1319
findRoomByName(const CString & name)1320 CRoomItem *CGameObject::findRoomByName(const CString &name) {
1321 CProjectItem *project = getRoot();
1322 for (CRoomItem *room = project->findFirstRoom(); room; room = project->findNextRoom(room)) {
1323 if (!room->getName().compareToIgnoreCase(name))
1324 return room;
1325 }
1326
1327 return nullptr;
1328 }
1329
getMusicRoom() const1330 CMusicRoom *CGameObject::getMusicRoom() const {
1331 CGameManager *gameManager = getGameManager();
1332 return gameManager ? &gameManager->_musicRoom : nullptr;
1333 }
1334
getPassengerClass() const1335 PassengerClass CGameObject::getPassengerClass() const {
1336 CGameManager *gameManager = getGameManager();
1337 return gameManager ? gameManager->_gameState._passengerClass : THIRD_CLASS;
1338 }
1339
getPriorClass() const1340 PassengerClass CGameObject::getPriorClass() const {
1341 CGameManager *gameManager = getGameManager();
1342 return gameManager ? gameManager->_gameState._priorClass : THIRD_CLASS;
1343 }
1344
setPassengerClass(PassengerClass newClass)1345 void CGameObject::setPassengerClass(PassengerClass newClass) {
1346 if (newClass >= 1 && newClass <= 4) {
1347 // Change the passenger class
1348 CGameManager *gameMan = getGameManager();
1349 gameMan->_gameState._priorClass = gameMan->_gameState._passengerClass;
1350 gameMan->_gameState._passengerClass = newClass;
1351
1352 // Setup the PET again, so the new class's PET background can take effect
1353 CPetControl *petControl = getPetControl();
1354 if (petControl)
1355 petControl->reset();
1356 }
1357 }
1358
createCredits()1359 void CGameObject::createCredits() {
1360 _credits = new CCreditText();
1361 CScreenManager *screenManager = getGameManager()->setScreenManager();
1362 _credits->load(this, screenManager, _bounds);
1363 }
1364
setToggleColor(byte r,byte g,byte b)1365 void CGameObject::setToggleColor(byte r, byte g, byte b) {
1366 makeDirty();
1367 _toggleR = r;
1368 _toggleG = g;
1369 _toggleB = b;
1370 }
1371
movieSetPlaying(bool flag)1372 void CGameObject::movieSetPlaying(bool flag) {
1373 if (!_surface && !_resource.empty()) {
1374 loadResource(_resource);
1375 _resource.clear();
1376 }
1377
1378 if (_surface && _surface->_movie)
1379 _surface->_movie->setPlaying(flag);
1380 }
1381
movieEvent(int frameNumber)1382 void CGameObject::movieEvent(int frameNumber) {
1383 if (_surface)
1384 _surface->addMovieEvent(frameNumber, this);
1385 }
1386
movieEvent()1387 void CGameObject::movieEvent() {
1388 if (_surface)
1389 _surface->addMovieEvent(-1, this);
1390 }
1391
getClipDuration(const CString & name,int frameRate) const1392 int CGameObject::getClipDuration(const CString &name, int frameRate) const {
1393 CMovieClip *clip = _movieClips.findByName(name);
1394 return clip ? (clip->_endFrame - clip->_startFrame) * 1000 / frameRate : 0;
1395 }
1396
getTicksCount()1397 uint32 CGameObject::getTicksCount() {
1398 return g_vm->_events->getTicksCount();
1399 }
1400
getResource(const CString & name)1401 Common::SeekableReadStream *CGameObject::getResource(const CString &name) {
1402 return g_vm->_filesManager->getResource(name);
1403 }
1404
compareRoomFlags(RoomFlagsComparison compareType,uint flags1,uint flags2)1405 bool CGameObject::compareRoomFlags(RoomFlagsComparison compareType, uint flags1, uint flags2) {
1406 switch (compareType) {
1407 case RFC_LOCATION:
1408 return CRoomFlags::compareLocation(flags1, flags2);
1409
1410 case RFC_CLASS_ELEVATOR:
1411 return CRoomFlags::compareClassElevator(flags1, flags2);
1412
1413 case RFC_TITANIA:
1414 return CRoomFlags::isTitania(flags1, flags2);
1415
1416 default:
1417 return false;
1418 }
1419 }
1420
stateSetSoundMakerAllowed(bool flag)1421 void CGameObject::stateSetSoundMakerAllowed(bool flag) {
1422 getGameManager()->_gameState._soundMakerAllowed = flag;
1423 }
1424
addMail(uint destRoomFlags)1425 void CGameObject::addMail(uint destRoomFlags) {
1426 CMailMan *mailMan = getMailMan();
1427 if (mailMan) {
1428 makeDirty();
1429 mailMan->addMail(this, destRoomFlags);
1430 }
1431 }
1432
setMailDest(uint roomFlags)1433 void CGameObject::setMailDest(uint roomFlags) {
1434 CMailMan *mailMan = getMailMan();
1435 if (mailMan) {
1436 makeDirty();
1437 mailMan->setMailDest(this, roomFlags);
1438 }
1439 }
1440
mailExists(uint roomFlags) const1441 bool CGameObject::mailExists(uint roomFlags) const {
1442 return findMail(roomFlags) != nullptr;
1443 }
1444
findMail(uint roomFlags) const1445 CGameObject *CGameObject::findMail(uint roomFlags) const {
1446 CMailMan *mailMan = getMailMan();
1447 return mailMan ? mailMan->findMail(roomFlags) : nullptr;
1448 }
1449
sendMail(uint currRoomFlags,uint newRoomFlags)1450 void CGameObject::sendMail(uint currRoomFlags, uint newRoomFlags) {
1451 CMailMan *mailMan = getMailMan();
1452 if (mailMan)
1453 mailMan->sendMail(currRoomFlags, newRoomFlags);
1454 }
1455
resetMail()1456 void CGameObject::resetMail() {
1457 CMailMan *mailMan = getMailMan();
1458 if (mailMan)
1459 mailMan->resetValue();
1460 }
1461
getRandomNumber(int max,int * oldVal)1462 int CGameObject::getRandomNumber(int max, int *oldVal) {
1463 if (oldVal) {
1464 int startingVal = *oldVal;
1465 while (*oldVal == startingVal && max > 0)
1466 *oldVal = g_vm->getRandomNumber(max);
1467
1468 return *oldVal;
1469 } else {
1470 return g_vm->getRandomNumber(max);
1471 }
1472 }
1473
1474 /*------------------------------------------------------------------------*/
1475
getRoom() const1476 CRoomItem *CGameObject::getRoom() const {
1477 CGameManager *gameManager = getGameManager();
1478 return gameManager ? gameManager->getRoom() : nullptr;
1479 }
1480
getNode() const1481 CNodeItem *CGameObject::getNode() const {
1482 CGameManager *gameManager = getGameManager();
1483 return gameManager ? gameManager->getNode() : nullptr;
1484 }
1485
getView() const1486 CViewItem *CGameObject::getView() const {
1487 CGameManager *gameManager = getGameManager();
1488 return gameManager ? gameManager->getView() : nullptr;
1489 }
1490
1491 /*------------------------------------------------------------------------*/
1492
petAddToCarryParcel(CGameObject * obj)1493 void CGameObject::petAddToCarryParcel(CGameObject *obj) {
1494 CPetControl *pet = getPetControl();
1495 if (pet) {
1496 CGameObject *parcel = pet->getHiddenObject("CarryParcel");
1497 if (parcel)
1498 parcel->moveUnder(obj);
1499 }
1500 }
1501
petAddToInventory()1502 void CGameObject::petAddToInventory() {
1503 assert(dynamic_cast<CCarry *>(this));
1504
1505 CPetControl *pet = getPetControl();
1506 if (pet) {
1507 makeDirty();
1508 pet->addToInventory(this);
1509 }
1510 }
1511
petContainerRemove(CGameObject * obj)1512 CTreeItem *CGameObject::petContainerRemove(CGameObject *obj) {
1513 CPetControl *pet = getPetControl();
1514 if (!obj || !pet)
1515 return nullptr;
1516 if (!obj->compareRoomNameTo("CarryParcel"))
1517 return obj;
1518
1519 CGameObject *item = dynamic_cast<CGameObject *>(pet->getLastChild());
1520 if (item)
1521 item->detach();
1522
1523 pet->moveToHiddenRoom(obj);
1524 pet->removeFromInventory(item, false, false);
1525
1526 return item;
1527 }
1528
petCheckNode(const CString & name)1529 bool CGameObject::petCheckNode(const CString &name) {
1530 CPetControl *pet = getPetControl();
1531 return pet ? pet->checkNode(name) : false;
1532 }
1533
petDismissBot(const CString & name)1534 bool CGameObject::petDismissBot(const CString &name) {
1535 CPetControl *pet = getPetControl();
1536 return pet ? pet->dismissBot(name) : false;
1537 }
1538
petDoorOrBellbotPresent() const1539 bool CGameObject::petDoorOrBellbotPresent() const {
1540 CPetControl *pet = getPetControl();
1541 return pet ? pet->isDoorOrBellbotPresent() : false;
1542 }
1543
petDisplayMessage(int unused,StringId stringId)1544 void CGameObject::petDisplayMessage(int unused, StringId stringId) {
1545 petDisplayMessage(stringId);
1546 }
1547
petDisplayMessage(StringId stringId,int param)1548 void CGameObject::petDisplayMessage(StringId stringId, int param) {
1549 CPetControl *pet = getPetControl();
1550 if (pet)
1551 pet->displayMessage(stringId, param);
1552 }
1553
petDisplayMessage(int unused,const CString & msg)1554 void CGameObject::petDisplayMessage(int unused, const CString &msg) {
1555 petDisplayMessage(msg);
1556 }
1557
petDisplayMessage(const CString & msg,int param)1558 void CGameObject::petDisplayMessage(const CString &msg, int param) {
1559 CPetControl *pet = getPetControl();
1560 if (pet)
1561 pet->displayMessage(msg, param);
1562 }
1563
petInvChange()1564 void CGameObject::petInvChange() {
1565 CPetControl *pet = getPetControl();
1566 if (pet)
1567 pet->invChange(this);
1568 }
1569
petLockInput()1570 void CGameObject::petLockInput() {
1571 getPetControl()->incInputLocks();
1572 }
1573
petMoveToHiddenRoom()1574 void CGameObject::petMoveToHiddenRoom() {
1575 CPetControl *pet = getPetControl();
1576 if (pet) {
1577 makeDirty();
1578 pet->moveToHiddenRoom(this);
1579 }
1580 }
1581
petReassignRoom(PassengerClass passClassNum)1582 void CGameObject::petReassignRoom(PassengerClass passClassNum) {
1583 CPetControl *petControl = getPetControl();
1584 if (petControl)
1585 petControl->reassignRoom(passClassNum);
1586 }
1587
petSetArea(PetArea newArea) const1588 void CGameObject::petSetArea(PetArea newArea) const {
1589 CPetControl *pet = getPetControl();
1590 if (pet)
1591 pet->setArea(newArea);
1592 }
1593
petSetRoomsWellEntry(int entryNum)1594 void CGameObject::petSetRoomsWellEntry(int entryNum) {
1595 CPetControl *petControl = getPetControl();
1596 if (petControl)
1597 petControl->setRoomsWellEntry(entryNum);
1598 }
1599
petGetRoomsWellEntry() const1600 int CGameObject::petGetRoomsWellEntry() const {
1601 CPetControl *petControl = getPetControl();
1602 return petControl ? petControl->getRoomsWellEntry() : 0;
1603 }
1604
petSetRoomsElevatorBroken(bool flag)1605 void CGameObject::petSetRoomsElevatorBroken(bool flag) {
1606 CPetControl *pet = getPetControl();
1607 if (pet)
1608 pet->setRoomsElevatorBroken(flag);
1609 }
1610
petOnSummonBot(const CString & name,int val)1611 void CGameObject::petOnSummonBot(const CString &name, int val) {
1612 CPetControl *pet = getPetControl();
1613 if (pet)
1614 pet->onSummonBot(name, val);
1615 }
1616
petUnlockInput()1617 void CGameObject::petUnlockInput() {
1618 getPetControl()->decInputLocks();
1619 }
1620
1621 /*------------------------------------------------------------------------*/
1622
getStarControl() const1623 CStarControl *CGameObject::getStarControl() const {
1624 CStarControl *starControl = dynamic_cast<CStarControl *>(getDontSaveChild(CStarControl::_type));
1625 if (!starControl) {
1626 CViewItem *view = getGameManager()->getView();
1627 if (view)
1628 starControl = dynamic_cast<CStarControl *>(view->findChildInstanceOf(CStarControl::_type));
1629 }
1630
1631 return starControl;
1632 }
1633
starFn(StarControlAction action)1634 void CGameObject::starFn(StarControlAction action) {
1635 CStarControl *starControl = getStarControl();
1636 if (starControl)
1637 starControl->doAction(action);
1638 }
1639
starIsSolved() const1640 bool CGameObject::starIsSolved() const {
1641 CStarControl *starControl = getStarControl();
1642 return starControl ? starControl->isSolved() : false;
1643 }
1644
1645 /*------------------------------------------------------------------------*/
1646
startTalking(const CString & npcName,uint id,CViewItem * view)1647 void CGameObject::startTalking(const CString &npcName, uint id, CViewItem *view) {
1648 CTrueTalkNPC *npc = static_cast<CTrueTalkNPC *>(getRoot()->findByName(npcName));
1649 startTalking(npc, id, view);
1650 }
1651
startTalking(CTrueTalkNPC * npc,uint id,CViewItem * view)1652 void CGameObject::startTalking(CTrueTalkNPC *npc, uint id, CViewItem *view) {
1653 CGameManager *gameManager = getGameManager();
1654 if (gameManager) {
1655 CTrueTalkManager *talkManager = gameManager->getTalkManager();
1656 if (talkManager)
1657 talkManager->start(npc, id, view);
1658 }
1659 }
1660
setTalking(CTrueTalkNPC * npc,bool viewFlag,CViewItem * view)1661 void CGameObject::setTalking(CTrueTalkNPC *npc, bool viewFlag, CViewItem *view) {
1662 CPetControl *pet = getPetControl();
1663 if (pet)
1664 pet->setActiveNPC(npc);
1665
1666 if (viewFlag)
1667 npc->setView(view);
1668
1669 if (pet)
1670 pet->refreshNPC();
1671 }
1672
talkSetDialRegion(const CString & name,int dialNum,int regionNum)1673 void CGameObject::talkSetDialRegion(const CString &name, int dialNum, int regionNum) {
1674 CGameManager *gameManager = getGameManager();
1675 if (gameManager) {
1676 CTrueTalkManager *talkManager = gameManager->getTalkManager();
1677 if (talkManager) {
1678 TTnpcScript *npcScript = talkManager->getTalker(name);
1679 if (npcScript)
1680 npcScript->setDialRegion(dialNum, regionNum);
1681 }
1682 }
1683 }
1684
talkGetDialRegion(const CString & name,int dialNum)1685 int CGameObject::talkGetDialRegion(const CString &name, int dialNum) {
1686 CGameManager *gameManager = getGameManager();
1687 if (gameManager) {
1688 CTrueTalkManager *talkManager = gameManager->getTalkManager();
1689 if (talkManager) {
1690 TTnpcScript *npcScript = talkManager->getTalker(name);
1691 if (npcScript)
1692 return npcScript->getDialRegion(dialNum);
1693 }
1694 }
1695
1696 return 0;
1697 }
1698
1699 /*------------------------------------------------------------------------*/
1700
getNodeChangedCtr() const1701 uint CGameObject::getNodeChangedCtr() const {
1702 return getGameManager()->_gameState.getNodeChangedCtr();
1703 }
1704
getNodeEnterTicks() const1705 uint CGameObject::getNodeEnterTicks() const {
1706 return getGameManager()->_gameState.getNodeEnterTicks();
1707 }
1708
1709
1710 } // End of namespace Titanic
1711