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 "hopkins/objects.h"
24
25 #include "hopkins/dialogs.h"
26 #include "hopkins/files.h"
27 #include "hopkins/globals.h"
28 #include "hopkins/hopkins.h"
29
30 #include "common/system.h"
31 #include "graphics/palette.h"
32 #include "common/file.h"
33 #include "common/rect.h"
34 #include "engines/util.h"
35
36 namespace Hopkins {
37
ObjectsManager(HopkinsEngine * vm)38 ObjectsManager::ObjectsManager(HopkinsEngine *vm) {
39 _vm = vm;
40
41 for (int i = 0; i < 6; ++i)
42 Common::fill((byte *)&_sprite[i], (byte *)&_sprite[i] + sizeof(SpriteItem), 0);
43
44 for (int i = 0; i < 36; ++i) {
45 Common::fill((byte *)&_bob[i], (byte *)&_bob[i] + sizeof(BobItem), 0);
46 Common::fill((byte *)&_lockedAnims[i], (byte *)&_lockedAnims[i] + sizeof(LockAnimItem), 0);
47 }
48
49 for (int i = 0; i < 30; ++i) {
50 Common::fill((byte *)&_vBob[i], (byte *)&_vBob[i] + sizeof(VBobItem), 0);
51 }
52
53 for (int i = 0; i < 300; ++i)
54 Common::fill((byte *)&_objectAuthIcons[i], (byte *)&_objectAuthIcons[i] + sizeof(ObjectAuthIcon), 0);
55
56 _sortedDisplayCount = 0;
57 for (int i = 0; i < 51; ++i)
58 Common::fill((byte *)&_sortedDisplay[i], (byte *)&_sortedDisplay[i] + sizeof(SortItem), 0);
59
60 for (int i = 0; i < 25; ++i)
61 Common::fill((byte *)&_hidingItem[i], (byte *)&_hidingItem[i] + sizeof(HidingItem), 0);
62
63 for (int i = 0; i < 6; ++i)
64 _hidingItemData[i] = NULL;
65
66 for (int i = 0; i < 6; ++i)
67 Common::fill((byte *)&_liste[i], (byte *)&_liste[i] + sizeof(ListeItem), 0);
68
69 for (int i = 0; i < 35; ++i)
70 Common::fill((byte *)&_liste2[i], (byte *)&_liste2[i] + sizeof(ListeItem), 0);
71
72 _helicopterFl = false;
73 _priorityFl = false;
74 _oldBorderPos = Common::Point(0, 0);
75 _oldBorderSpriteIndex = 0;
76 _borderPos = Common::Point(0, 0);
77 _borderSpriteIndex = 0;
78 _saveLoadX = _saveLoadY = 0;
79 _oldCharacterPosX = _oldCharacterPosY = 0;
80 _eraseVisibleCounter = 0;
81 _saveLoadSprite = NULL;
82 _saveLoadSprite2 = NULL;
83 _spritePtr = NULL;
84 _oldSpriteData = NULL;
85 _saveLoadFl = false;
86 _visibleFl = false;
87 _zoneNum = 0;
88 _forceZoneFl = false;
89 _changeVerbFl = false;
90 _verb = 0;
91 _changeHeadFl = false;
92 _disableFl = false;
93 _twoCharactersFl = false;
94 _characterPos = Common::Point(0, 0);
95 _startSpriteIndex = 0;
96 _jumpVerb = 0;
97 _jumpZone = 0;
98 _oldSpriteIndex = 0;
99 _oldFrameIndex = 0;
100 _oldFlipFl = false;
101 _curObjectIndex = 0;
102 _forestFl = false;
103 _mapCarPosX = _mapCarPosY = 0;
104 _forestSprite = NULL;
105 _gestureBuf = NULL;
106 _curGestureFile = 0;
107 _headSprites = NULL;
108 _homeRateCounter = 0;
109 _lastDirection = DIR_NONE;
110 _oldDirection = DIR_NONE;
111 _oldDirectionSpriteIdx = 59;
112 _objectWidth = _objectHeight = 0;
113 _hidingActiveFl = false;
114 _curObjectFileNum = 0;
115 _objectDataBuf = NULL;
116 _charactersEnabledFl = false;
117 _refreshBobMode10Fl = false;
118 }
119
~ObjectsManager()120 ObjectsManager::~ObjectsManager() {
121 _vm->_globals->freeMemory(_forestSprite);
122 _vm->_globals->freeMemory(_gestureBuf);
123 _vm->_globals->freeMemory(_headSprites);
124 _vm->_globals->freeMemory(_objectDataBuf);
125 clearVBob();
126
127 for (int idx = 0; idx < 6; ++idx)
128 _hidingItemData[idx] = _vm->_globals->freeMemory(_hidingItemData[idx]);
129 }
130
clearAll()131 void ObjectsManager::clearAll() {
132 _forestFl = false;
133 _forestSprite = _vm->_globals->freeMemory(_forestSprite);
134 _curGestureFile = 0;
135 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
136 _curObjectFileNum = 0;
137
138 for (int idx = 0; idx < 6; ++idx)
139 _hidingItemData[idx] = _vm->_globals->freeMemory(_hidingItemData[idx]);
140
141 _objectDataBuf = _vm->_globals->freeMemory(_objectDataBuf);
142 initVBob();
143 }
144
145 // Load Object
loadObjects()146 void ObjectsManager::loadObjects() {
147 byte *data = _vm->_fileIO->loadFile("OBJET.DAT");
148 byte *srcP = data;
149
150 for (int idx = 0; idx < 300; ++idx) {
151 ObjectAuthIcon *objectAuthIcon = &_objectAuthIcons[idx];
152 objectAuthIcon->_objectFileNum = *srcP++;
153 objectAuthIcon->_idx = *srcP++;
154 objectAuthIcon->_flag1 = *srcP++;
155 objectAuthIcon->_flag2 = *srcP++;
156 objectAuthIcon->_flag3 = *srcP++;
157 objectAuthIcon->_flag4 = *srcP++;
158 objectAuthIcon->_flag5 = *srcP++;
159 objectAuthIcon->_flag6 = *srcP++;
160 }
161
162 _vm->_globals->freeMemory(data);
163 }
164
165 // Reset Hiding Items
resetHidingItems()166 void ObjectsManager::resetHidingItems() {
167 for (int idx = 1; idx <= 5; ++idx) {
168 _hidingItemData[idx] = _vm->_globals->freeMemory(_hidingItemData[idx]);
169 }
170
171 for (int idx = 0; idx <= 20; ++idx) {
172 HidingItem *hid = &_hidingItem[idx];
173 hid->_spriteData = NULL;
174 hid->_x = 0;
175 hid->_y = 0;
176 hid->_spriteIndex = 0;
177 hid->_useCount = 0;
178 hid->_width = 0;
179 hid->_height = 0;
180 hid->_resetUseCount = false;
181 hid->_yOffset = 0;
182 }
183
184 _hidingActiveFl = false;
185 }
186
187 /**
188 * Change Object
189 */
changeObject(int objIndex)190 void ObjectsManager::changeObject(int objIndex) {
191 _vm->_events->_objectBuf = loadObjectFromFile(objIndex, true);
192 _curObjectIndex = objIndex;
193 }
194
loadObjectFromFile(int objIndex,bool mode)195 byte *ObjectsManager::loadObjectFromFile(int objIndex, bool mode) {
196 byte *dataP = NULL;
197 int objectFileNum = _objectAuthIcons[objIndex]._objectFileNum;
198 int idx = _objectAuthIcons[objIndex]._idx;
199
200 if (mode)
201 ++idx;
202
203 if (objectFileNum != _curObjectFileNum) {
204 if (_objectDataBuf)
205 removeObjectDataBuf();
206 if (objectFileNum == 1) {
207 _objectDataBuf = loadSprite("OBJET1.SPR");
208 }
209 _curObjectFileNum = objectFileNum;
210 }
211
212 int width = getWidth(_objectDataBuf, idx);
213 int height = getHeight(_objectDataBuf, idx);
214 _objectWidth = width;
215 _objectHeight = height;
216
217 if (mode) {
218 sprite_alone(_objectDataBuf, _vm->_events->_objectBuf, idx);
219 dataP = _vm->_events->_objectBuf;
220 } else {
221 dataP = _vm->_globals->allocMemory(height * width);
222 if (dataP == NULL)
223 error("CAPTURE_OBJET");
224
225 capture_mem_sprite(_objectDataBuf, dataP, idx);
226 }
227
228 return dataP;
229 }
230
231 /**
232 * Remove an Object from the inventory
233 */
removeObject(int objIndex)234 void ObjectsManager::removeObject(int objIndex) {
235 int idx;
236 for (idx = 1; idx <= 32; ++idx) {
237 if (_vm->_globals->_inventory[idx] == objIndex)
238 break;
239 }
240
241 if (idx <= 32) {
242 if (idx == 32) {
243 _vm->_globals->_inventory[32] = 0;
244 } else {
245 for (int i = idx; i < 32; ++i)
246 _vm->_globals->_inventory[i] = _vm->_globals->_inventory[i + 1];
247 }
248 }
249 changeObject(14);
250
251 }
252
253 /**
254 * Set Offset XY
255 */
setOffsetXY(byte * data,int idx,int xp,int yp,bool isSize)256 void ObjectsManager::setOffsetXY(byte *data, int idx, int xp, int yp, bool isSize) {
257 byte *startP = data + 3;
258 for (int i = idx; i; --i)
259 startP += READ_LE_UINT32(startP) + 16;
260
261 byte *rectP = startP + 8;
262 if (isSize) {
263 // Set size
264 byte *pointP = rectP + 4;
265 WRITE_LE_UINT16(pointP, xp);
266 WRITE_LE_UINT16(pointP + 2, yp);
267 } else {
268 // Set position
269 WRITE_LE_UINT16(rectP, xp);
270 WRITE_LE_UINT16(rectP + 2, yp);
271 }
272 }
273
getOffsetX(const byte * spriteData,int spriteIndex,bool isSize)274 int ObjectsManager::getOffsetX(const byte *spriteData, int spriteIndex, bool isSize) {
275 const byte *data = spriteData + 3;
276 for (int i = spriteIndex; i; --i)
277 data += READ_LE_UINT32(data) + 16;
278
279 int result;
280 if (isSize)
281 result = READ_LE_INT16(data + 12);
282 else
283 result = READ_LE_INT16(data + 8);
284
285 return result;
286 }
287
getOffsetY(const byte * spriteData,int spriteIndex,bool isSize)288 int ObjectsManager::getOffsetY(const byte *spriteData, int spriteIndex, bool isSize) {
289 const byte *data = spriteData + 3;
290 for (int i = spriteIndex; i; --i)
291 data += READ_LE_UINT32(data) + 16;
292
293 int result;
294 if (isSize)
295 result = READ_LE_INT16(data + 14);
296 else
297 result = READ_LE_INT16(data + 10);
298
299 return result;
300 }
301
302 /**
303 * Get Width
304 */
getWidth(const byte * objectData,int idx)305 int ObjectsManager::getWidth(const byte *objectData, int idx) {
306 const byte *rectP = objectData + 3;
307 for (int i = idx; i; --i)
308 rectP += READ_LE_UINT32(rectP) + 16;
309
310 return READ_LE_INT16(rectP + 4);
311 }
312
313 /**
314 * Get height
315 */
getHeight(const byte * objectData,int idx)316 int ObjectsManager::getHeight(const byte *objectData, int idx) {
317 const byte *rectP = objectData + 3;
318 for (int i = idx; i; --i)
319 rectP += READ_LE_UINT32(rectP) + 16;
320
321 return READ_LE_INT16(rectP + 6);
322 }
323
sprite_alone(const byte * objectData,byte * sprite,int objIndex)324 void ObjectsManager::sprite_alone(const byte *objectData, byte *sprite, int objIndex) {
325 const byte *objP = objectData + 3;
326 for (int i = objIndex; i; --i) {
327 objP += READ_LE_UINT32(objP) + 16;
328 }
329
330 objP += 4;
331 int result = READ_LE_INT16(objP) * READ_LE_INT16(objP + 2);
332
333 memcpy(sprite + 3, objP - 4, result + 16);
334 }
335
capture_mem_sprite(const byte * objectData,byte * sprite,int objIndex)336 void ObjectsManager::capture_mem_sprite(const byte *objectData, byte *sprite, int objIndex) {
337 const byte *objP = objectData + 3;
338 for (int i = objIndex; i; --i) {
339 objP += READ_LE_UINT32(objP) + 16;
340 }
341
342 objP += 4;
343 int result = READ_LE_INT16(objP) * READ_LE_INT16(objP + 2);
344 memcpy(sprite, objP + 12, result);
345 }
346
removeObjectDataBuf()347 void ObjectsManager::removeObjectDataBuf() {
348 _curObjectFileNum = 0;
349 _objectDataBuf = _vm->_globals->freeMemory(_objectDataBuf);
350 }
351
352 /**
353 * Load Sprite from file
354 */
loadSprite(const Common::String & file)355 byte *ObjectsManager::loadSprite(const Common::String &file) {
356 return _vm->_fileIO->loadFile(file);
357 }
358
359 /**
360 * Add Object
361 */
addObject(int objIndex)362 void ObjectsManager::addObject(int objIndex) {
363 int arrIndex = 0;
364 for (;;) {
365 ++arrIndex;
366 if ((!_vm->_globals->_inventory[arrIndex]) || (arrIndex == 32))
367 break;
368 }
369
370 _vm->_globals->_inventory[arrIndex] = objIndex;
371 }
372
373 /**
374 * Display Sprite
375 */
displaySprite()376 void ObjectsManager::displaySprite() {
377 int clipX;
378 int clipY;
379 uint16 arr[50];
380
381 // Handle copying any background areas that text are going to be drawn on
382 _sortedDisplayCount = 0;
383 for (int idx = 0; idx <= 10; ++idx) {
384 TxtItemList *curTxtList = &_vm->_fontMan->_textList[idx];
385 if (curTxtList->_enabledFl && _vm->_fontMan->_text[idx]._textType != 2) {
386 clipX = curTxtList->_pos.x - 2;
387
388 if (clipX < _vm->_graphicsMan->_minX)
389 clipX = _vm->_graphicsMan->_minX;
390
391 clipY = curTxtList->_pos.y - 2;
392 if (clipY < _vm->_graphicsMan->_minY)
393 clipY = _vm->_graphicsMan->_minY;
394
395 _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, clipX, clipY,
396 curTxtList->_width + 4, curTxtList->_height + 4, _vm->_graphicsMan->_frontBuffer, clipX, clipY);
397 curTxtList->_enabledFl = false;
398 }
399 }
400
401 if (!_charactersEnabledFl) {
402 for (int idx = 0; idx < MAX_SPRITE; ++idx) {
403 ListeItem *curList = &_liste[idx];
404 if (curList->_visibleFl) {
405 clipX = curList->_posX - 2;
406 if (clipX < _vm->_graphicsMan->_minX)
407 clipX = _vm->_graphicsMan->_minX;
408
409 clipY = curList->_posY - 2;
410 if (clipY < _vm->_graphicsMan->_minY)
411 clipY = _vm->_graphicsMan->_minY;
412
413 _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, clipX, clipY,
414 curList->_width + 4, curList->_height + 4, _vm->_graphicsMan->_frontBuffer, clipX, clipY);
415 curList->_visibleFl = false;
416 }
417 }
418 }
419
420 displayBobAnim();
421 displayVBob();
422
423 if (!_charactersEnabledFl) {
424 // Handle drawing characters on the screen
425 for (int idx = 0; idx < MAX_SPRITE; ++idx) {
426 _liste[idx]._visibleFl = false;
427 SpriteItem *curSpr = &_sprite[idx];
428 if (curSpr->_animationType == 1) {
429 computeSprite(idx);
430 if (curSpr->_activeFl)
431 beforeSort(SORT_SPRITE, idx, curSpr->_height + curSpr->_destY);
432 }
433 }
434
435 if (_hidingActiveFl)
436 checkHidingItem();
437 }
438
439 if (_priorityFl && _sortedDisplayCount) {
440 for (int i = 1; i <= 48; i++)
441 arr[i] = i;
442
443 bool loopCondFl;
444 do {
445 loopCondFl = false;
446 for (int sortIdx = 1; sortIdx < _sortedDisplayCount; sortIdx++) {
447 if (_sortedDisplay[arr[sortIdx]]._priority > _sortedDisplay[arr[sortIdx + 1]]._priority) {
448 SWAP(arr[sortIdx], arr[sortIdx + 1]);
449 loopCondFl = true;
450 }
451 }
452 } while (loopCondFl);
453
454 for (int sortIdx = 1; sortIdx < _sortedDisplayCount + 1; sortIdx++) {
455 int idx = arr[sortIdx];
456 switch (_sortedDisplay[idx]._sortMode) {
457 case SORT_BOB:
458 setBobInfo(_sortedDisplay[idx]._index);
459 break;
460 case SORT_SPRITE:
461 showSprite(_sortedDisplay[idx]._index);
462 break;
463 case SORT_HIDING:
464 displayHiding(_sortedDisplay[idx]._index);
465 break;
466 default:
467 break;
468 }
469 _sortedDisplay[idx]._sortMode = SORT_NONE;
470 }
471 } else {
472 for (int idx = 1; idx < _sortedDisplayCount + 1; ++idx) {
473 switch (_sortedDisplay[idx]._sortMode) {
474 case SORT_BOB:
475 setBobInfo(_sortedDisplay[idx]._index);
476 break;
477 case SORT_SPRITE:
478 showSprite(_sortedDisplay[idx]._index);
479 break;
480 case SORT_HIDING:
481 displayHiding(_sortedDisplay[idx]._index);
482 break;
483 default:
484 break;
485 }
486 _sortedDisplay[idx]._sortMode = SORT_NONE;
487 }
488 }
489
490 // Reset the Sort array
491 for (int idx = 0; idx < 50; ++idx) {
492 SortItem *disp = &_sortedDisplay[idx];
493 disp->_sortMode = SORT_NONE;
494 disp->_index = 0;
495 disp->_priority = 0;
496 }
497
498 _sortedDisplayCount = 0;
499
500 _vm->_dialog->drawInvent(_oldBorderPos, _oldBorderSpriteIndex, _borderPos, _borderSpriteIndex);
501
502 if (_saveLoadFl) {
503 int16 posX = _vm->_events->_startPos.x;
504 _vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, _saveLoadSprite, posX + 183, 60, 274, 353);
505 if (_saveLoadX && _saveLoadY)
506 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _saveLoadSprite2, _saveLoadX + posX + 300, _saveLoadY + 300, 0);
507
508 _vm->_graphicsMan->addDirtyRect(posX + 183, 60, posX + 457, 413);
509 }
510
511 // If the Options dialog is activated, draw the elements
512 if (_vm->_globals->_optionDialogFl) {
513 int16 posX = _vm->_events->_startPos.x;
514 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
515 posX + 464, 407, 0);
516 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
517 posX + 657, 556, _vm->_globals->_menuSpeed);
518 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
519 posX + 731, 495, _vm->_globals->_menuTextOff);
520 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
521 posX + 731, 468, _vm->_globals->_menuVoiceOff);
522 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
523 posX + 731, 441, _vm->_globals->_menuSoundOff);
524 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
525 posX + 731, 414, _vm->_globals->_menuMusicOff);
526 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
527 posX + 600, 522, _vm->_globals->_menuDisplayType);
528 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _vm->_globals->_optionDialogSpr,
529 posX + 611, 502, _vm->_globals->_menuScrollSpeed);
530 _vm->_graphicsMan->addDirtyRect(posX + 164, 107, posX + 498, 320);
531 }
532
533 // Loop to draw any on-screen text
534 for (int idx = 0; idx <= 10; ++idx) {
535 TxtItem *curTxt = &_vm->_fontMan->_text[idx];
536 if (curTxt->_textOnFl) {
537 TxtItemList *curTxtList = &_vm->_fontMan->_textList[idx];
538 if ((curTxt->_textType < 2) || (curTxt->_textType > 3))
539 _vm->_fontMan->box(idx, curTxt->_messageId, curTxt->_filename, _vm->_events->_startPos.x + curTxt->_pos.x, curTxt->_pos.y);
540 else
541 _vm->_fontMan->box(idx, curTxt->_messageId, curTxt->_filename, curTxt->_pos.x, curTxt->_pos.y);
542 curTxtList->_enabledFl = true;
543
544 if ((curTxt->_textType < 2) || (curTxt->_textType > 3))
545 curTxtList->_pos.x = _vm->_events->_startPos.x + curTxt->_pos.x;
546 else
547 curTxtList->_pos.x = curTxt->_pos.x;
548
549 curTxtList->_pos.y = curTxt->_pos.y;
550 curTxtList->_width = curTxt->_width;
551 curTxtList->_height = curTxt->_height;
552
553 if (curTxtList->_pos.x < _vm->_graphicsMan->_minX)
554 curTxtList->_pos.x = _vm->_graphicsMan->_minX - 1;
555 if (curTxtList->_pos.y < _vm->_graphicsMan->_minY)
556 curTxtList->_pos.y = _vm->_graphicsMan->_minY - 1;
557
558 int posX = curTxtList->_pos.x;
559 if (curTxtList->_width + posX > _vm->_graphicsMan->_maxX)
560 curTxtList->_width = _vm->_graphicsMan->_maxX - posX;
561 int posY = curTxtList->_pos.y;
562 if (curTxtList->_height + posY > _vm->_graphicsMan->_maxY)
563 curTxtList->_height = _vm->_graphicsMan->_maxY - posY;
564 if (curTxtList->_width <= 0 || curTxtList->_height <= 0)
565 curTxtList->_enabledFl = false;
566 }
567 }
568
569 _vm->_dialog->inventAnim();
570 }
571
resetBob(int idx)572 void ObjectsManager::resetBob(int idx) {
573 BobItem &bob = _bob[idx];
574 ListeItem &item = _liste2[idx];
575
576 bob._bobMode = 0;
577 bob._spriteData = NULL;
578 bob._xp = 0;
579 bob._yp = 0;
580 bob._frameIndex = 0;
581 bob._animDataIdx = 0;
582 bob._moveChange1 = 0;
583 bob._moveChange2 = 0;
584 bob._disabledAnimationFl = false;
585 bob._animData = NULL;
586 bob._bobMode10 = false;
587 bob._bobModeChange = 0;
588 bob._modeChangeCtr = 0;
589 bob._modeChangeUnused = 0;
590 bob._disableFl = false;
591 bob._zoomFactor = 0;
592 bob._flipFl = false;
593 bob._oldX2 = 0;
594
595 item._visibleFl = false;
596 item._posX = 0;
597 item._posY = 0;
598 item._width = 0;
599 item._height = 0;
600 }
601
setBobInfo(int idx)602 void ObjectsManager::setBobInfo(int idx) {
603 BobItem *curBob = &_bob[idx];
604
605 if (!curBob->_activeFl)
606 return;
607
608 int xp = curBob->_oldX;
609 int yp = curBob->_oldY;
610
611 if (curBob->_isSpriteFl)
612 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, curBob->_spriteData,
613 xp + 300, yp + 300, curBob->_frameIndex);
614 else
615 _vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer,
616 curBob->_spriteData, xp + 300, yp + 300, curBob->_frameIndex,
617 curBob->_zoomOutFactor, curBob->_zooInmFactor, curBob->_flipFl);
618
619 ListeItem *curLst = &_liste2[idx];
620 curLst->_visibleFl = true;
621 curLst->_posX = xp;
622 curLst->_posY = yp;
623
624 curLst->_width = curBob->_oldWidth;
625 curLst->_height = curBob->_oldHeight;
626
627 if (curLst->_posX < _vm->_graphicsMan->_minX) {
628 curLst->_width -= _vm->_graphicsMan->_minX - curLst->_posX;
629 curLst->_posX = _vm->_graphicsMan->_minX;
630 }
631
632 if (curLst->_posY < _vm->_graphicsMan->_minY) {
633 curLst->_height -= _vm->_graphicsMan->_minY - curLst->_posY;
634 curLst->_posY = _vm->_graphicsMan->_minY;
635 }
636
637 if (curLst->_width + curLst->_posX > _vm->_graphicsMan->_maxX)
638 curLst->_width = _vm->_graphicsMan->_maxX - curLst->_posX;
639
640 if (curLst->_height + curLst->_posY > _vm->_graphicsMan->_maxY)
641 curLst->_height = _vm->_graphicsMan->_maxY - curLst->_posY;
642
643 if (curLst->_width <= 0 || curLst->_height <= 0)
644 curLst->_visibleFl = false;
645
646 if (curLst->_visibleFl)
647 _vm->_graphicsMan->addDirtyRect(curLst->_posX, curLst->_posY, curLst->_posX + curLst->_width, curLst->_posY + curLst->_height);
648 }
649
displayBob(int idx)650 void ObjectsManager::displayBob(int idx) {
651 BobItem *curBob = &_bob[idx];
652
653 _priorityFl = true;
654
655 if (curBob->_bobMode)
656 return;
657
658 resetBob(idx);
659
660 const byte *data = _vm->_animMan->_animBqe[idx]._data;
661 int bankIdx = READ_LE_INT16(data);
662 if (!bankIdx)
663 return;
664 if ((!_vm->_animMan->Bank[bankIdx]._loadedFl) || (!READ_LE_UINT16(data + 24)))
665 return;
666
667
668 int16 bobModeChange = READ_LE_INT16(data + 2);
669 int16 modeChangeUnused = READ_LE_INT16(data + 4);
670 // data[6] isn't used, read skipped
671 int16 newModeChangeCtr = READ_LE_INT16(data + 8);
672
673 if (!bobModeChange)
674 bobModeChange = 1;
675 if (!newModeChangeCtr)
676 newModeChangeCtr = -1;
677
678 curBob->_isSpriteFl = false;
679
680 if (_vm->_animMan->Bank[bankIdx]._fileHeader == 1) {
681 curBob->_isSpriteFl = true;
682 curBob->_zoomFactor = 0;
683 curBob->_flipFl = false;
684 }
685
686 curBob->_animData = _vm->_animMan->_animBqe[idx]._data;
687 curBob->_bobMode = 10;
688 curBob->_spriteData = _vm->_animMan->Bank[bankIdx]._data;
689
690 curBob->_bobModeChange = bobModeChange;
691 curBob->_modeChangeCtr = newModeChangeCtr;
692 curBob->_modeChangeUnused = modeChangeUnused;
693 }
694
hideBob(int idx)695 void ObjectsManager::hideBob(int idx) {
696 BobItem *curBob = &_bob[idx];
697 if ((curBob->_bobMode == 3) || (curBob->_bobMode == 10))
698 curBob->_bobMode++;
699 }
700
setBobOffset(int idx,int offset)701 void ObjectsManager::setBobOffset(int idx, int offset) {
702 _bob[idx]._oldX2 = offset;
703 }
704
computeHideCounter(int idx)705 void ObjectsManager::computeHideCounter(int idx) {
706 HidingItem *hid = &_hidingItem[idx];
707 if (hid->_useCount == 0)
708 return;
709
710 for (int i = 0; i <= 20; i++) {
711 BobItem *curBob = &_bob[i];
712 if ((curBob->_bobMode) && (!curBob->_disabledAnimationFl) && (!curBob->_disableFl) && (curBob->_frameIndex != 250)) {
713 int oldRight = curBob->_oldX + curBob->_oldWidth;
714 int oldBottom = curBob->_oldY + curBob->_oldHeight;
715 int hiddenRight = hid->_x + hid->_width;
716
717 if ((oldBottom > hid->_y) && (oldBottom < hid->_yOffset + hid->_height + hid->_y)) {
718 if ((oldRight >= hid->_x && oldRight <= hiddenRight)
719 // CHECKME: The original was doing the test two times. This looks like an
720 // original bug
721 // || (cachedRight >= curBob->_oldWidth && curBob->_oldWidth >= hid->_x)
722 || (hiddenRight >= curBob->_oldWidth && curBob->_oldWidth >= hid->_x)
723 || (curBob->_oldWidth >= hid->_x && oldRight <= hiddenRight)
724 || (curBob->_oldWidth <= hid->_x && oldRight >= hiddenRight))
725 ++hid->_useCount;
726 }
727 }
728 }
729 }
730
initBobVariables(int idx)731 void ObjectsManager::initBobVariables(int idx) {
732 BobItem *bob = &_bob[idx];
733
734 bob->_activeFl = false;
735 if (bob->_isSpriteFl) {
736 bob->_flipFl = false;
737 bob->_zoomFactor = 0;
738 }
739
740 int spriteIdx = bob->_frameIndex;
741 if (spriteIdx == 250)
742 return;
743
744 int deltaY, deltaX;
745 if (bob->_flipFl) {
746 deltaX = getOffsetX(bob->_spriteData, spriteIdx, true);
747 deltaY = getOffsetY(bob->_spriteData, bob->_frameIndex, true);
748 } else {
749 deltaX = getOffsetX(bob->_spriteData, spriteIdx, false);
750 deltaY = getOffsetY(bob->_spriteData, bob->_frameIndex, false);
751 }
752
753 int negZoom = 0;
754 int posZoom = 0;
755 if (bob->_zoomFactor < 0)
756 negZoom = CLIP(-bob->_zoomFactor, 0, 95);
757 else
758 posZoom = bob->_zoomFactor;
759
760 if (posZoom) {
761 if (deltaX >= 0)
762 deltaX = _vm->_graphicsMan->zoomIn(deltaX, posZoom);
763 else
764 deltaX = -_vm->_graphicsMan->zoomIn(-deltaX, posZoom);
765
766 if (deltaY >= 0)
767 deltaY = _vm->_graphicsMan->zoomIn(deltaY, posZoom);
768 else
769 deltaY = -_vm->_graphicsMan->zoomIn(abs(deltaX), posZoom);
770 }
771
772 if (negZoom) {
773 if (deltaX >= 0)
774 deltaX = _vm->_graphicsMan->zoomOut(deltaX, negZoom);
775 else
776 deltaX = -_vm->_graphicsMan->zoomOut(-deltaX, negZoom);
777
778 if (deltaY >= 0)
779 deltaY = _vm->_graphicsMan->zoomOut(deltaY, negZoom);
780 else
781 deltaY = -_vm->_graphicsMan->zoomOut(abs(deltaX), negZoom);
782 }
783
784 int newX = bob->_xp - deltaX;
785 int newY = bob->_yp - deltaY;
786 bob->_activeFl = true;
787 bob->_oldX = newX;
788 bob->_oldY = newY;
789 bob->_zooInmFactor = posZoom;
790 bob->_zoomOutFactor = negZoom;
791
792 ListeItem *curList = &_liste2[idx];
793 curList->_visibleFl = true;
794 curList->_posX = newX;
795 curList->_posY = newY;
796
797 int width = getWidth(bob->_spriteData, bob->_frameIndex);
798 int height = getHeight(bob->_spriteData, bob->_frameIndex);
799
800 if (posZoom) {
801 width = _vm->_graphicsMan->zoomIn(width, posZoom);
802 height = _vm->_graphicsMan->zoomIn(height, posZoom);
803 } else if (negZoom) {
804 width = _vm->_graphicsMan->zoomOut(width, negZoom);
805 height = _vm->_graphicsMan->zoomOut(height, negZoom);
806 }
807
808 curList->_width = width;
809 curList->_height = height;
810 bob->_oldWidth = width;
811 bob->_oldHeight = height;
812 }
813
checkHidingItem()814 void ObjectsManager::checkHidingItem() {
815 for (int hidingItemIdx = 0; hidingItemIdx <= 19; hidingItemIdx++) {
816 HidingItem *hid = &_hidingItem[hidingItemIdx];
817 if (hid->_useCount == 0)
818 continue;
819
820 int _oldUseCount = hid->_useCount;
821 for (int spriteIdx = 0; spriteIdx <= 4; spriteIdx++) {
822 const SpriteItem *spr = &_sprite[spriteIdx];
823 if (spr->_animationType == 1 && spr->_spriteIndex != 250) {
824 int right = spr->_width + spr->_destX;
825 int bottom = spr->_height + spr->_destY;
826 int hidingRight = hid->_width + hid->_x;
827
828 if (bottom > hid->_y && bottom < (hid->_yOffset + hid->_height + hid->_y)) {
829 if ((right >= hid->_x && right <= hidingRight)
830 // CHECKME: The original was doing the test two times. This looks like an
831 // original bug
832 // || (hidingRight >= spr->_destX && hid->_x <= spr->_destX)
833 || (hidingRight >= spr->_destX && hid->_x <= spr->_destX)
834 || (hid->_x <= spr->_destX && right <= hidingRight)
835 || (hid->_x >= spr->_destX && right >= hidingRight))
836 ++hid->_useCount;
837 }
838 }
839 }
840
841 computeHideCounter(hidingItemIdx);
842 if (hid->_useCount != _oldUseCount) {
843 int priority = hid->_yOffset + hid->_height + hid->_y;
844 if (priority > 440)
845 priority = 500;
846
847 beforeSort(SORT_HIDING, hidingItemIdx, priority);
848 hid->_useCount = 1;
849 hid->_resetUseCount = true;
850 } else if (hid->_resetUseCount) {
851 hid->_resetUseCount = false;
852 hid->_useCount = 1;
853 }
854
855 }
856 }
857
showSprite(int idx)858 void ObjectsManager::showSprite(int idx) {
859 SpriteItem *spr = &_sprite[idx];
860 if (!spr->_activeFl)
861 return;
862
863 if (spr->_rleFl)
864 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, spr->_spriteData,
865 spr->_destX + 300, spr->_destY + 300, spr->_spriteIndex);
866 else
867 _vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, spr->_spriteData,
868 spr->_destX + 300, spr->_destY + 300, spr->_spriteIndex, spr->_reducePct, spr->_zoomPct, spr->_flipFl);
869
870 ListeItem *list = &_liste[idx];
871 list->_width = spr->_width;
872 list->_height = spr->_height;
873
874 if (list->_posX < _vm->_graphicsMan->_minX) {
875 list->_width -= _vm->_graphicsMan->_minX - list->_posX;
876 list->_posX = _vm->_graphicsMan->_minX;
877 }
878
879 if (list->_posY < _vm->_graphicsMan->_minY) {
880 list->_height -= _vm->_graphicsMan->_minY - list->_posY;
881 list->_posY = _vm->_graphicsMan->_minY;
882 }
883
884 list->_width = MIN(list->_width, _vm->_graphicsMan->_maxX - list->_posX);
885 list->_height = MIN(list->_height, _vm->_graphicsMan->_maxY - list->_posY);
886
887 if (list->_width <= 0 || list->_height <= 0)
888 list->_visibleFl = false;
889
890 if (list->_visibleFl)
891 _vm->_graphicsMan->addDirtyRect( list->_posX, list->_posY, list->_posX + list->_width, list->_posY + list->_height);
892 }
893
displayHiding(int idx)894 void ObjectsManager::displayHiding(int idx) {
895 HidingItem *hid = &_hidingItem[idx];
896
897 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, _hidingItemData[1],
898 hid->_x + 300, hid->_y + 300, hid->_spriteIndex);
899 _vm->_graphicsMan->addDirtyRect(hid->_x, hid->_y, hid->_x + hid->_width, hid->_y + hid->_height);
900 }
901
902 // Compute Sprite
computeSprite(int idx)903 void ObjectsManager::computeSprite(int idx) {
904 SpriteItem *spr = &_sprite[idx];
905
906 spr->_activeFl = false;
907 int spriteIndex = spr->_spriteIndex;
908 if (spriteIndex == 250)
909 return;
910
911 int offX;
912 int offY;
913 if (spr->_flipFl) {
914 offX = getOffsetX(spr->_spriteData, spriteIndex, true);
915 offY = getOffsetY(spr->_spriteData, spr->_spriteIndex, true);
916 } else {
917 offX = getOffsetX(spr->_spriteData, spriteIndex, false);
918 offY = getOffsetY(spr->_spriteData, spr->_spriteIndex, false);
919 }
920
921 int tmpX = spr->_deltaX + offX;
922 int deltaX = tmpX;
923 int tmpY = spr->_deltaY + offY;
924 int deltaY = tmpY;
925 int zoomPercent = 0;
926 int reducePercent = 0;
927
928 if (spr->_zoomFactor < 0) {
929 reducePercent = -spr->_zoomFactor;
930 if (reducePercent > 95)
931 reducePercent = 95;
932 } else
933 zoomPercent = spr->_zoomFactor;
934
935 if (zoomPercent) {
936 if (tmpX >= 0)
937 deltaX = _vm->_graphicsMan->zoomIn(tmpX, zoomPercent);
938 else
939 deltaX = -_vm->_graphicsMan->zoomIn(-tmpX, zoomPercent);
940
941 if (tmpY >= 0) {
942 deltaY = _vm->_graphicsMan->zoomIn(tmpY, zoomPercent);
943 } else {
944 tmpY = abs(tmpX);
945 deltaY = -_vm->_graphicsMan->zoomIn(tmpY, zoomPercent);
946 }
947 } else if (reducePercent) {
948 if (tmpX >= 0)
949 deltaX = _vm->_graphicsMan->zoomOut(tmpX, reducePercent);
950 else
951 deltaX = -_vm->_graphicsMan->zoomOut(-tmpX, reducePercent);
952
953 if (tmpY >= 0) {
954 deltaY = _vm->_graphicsMan->zoomOut(tmpY, reducePercent);
955 } else {
956 tmpY = abs(tmpX);
957 deltaY = -_vm->_graphicsMan->zoomOut(tmpY, reducePercent);
958 }
959 }
960
961 int newPosX = spr->_spritePos.x - deltaX;
962 int newPosY = spr->_spritePos.y - deltaY;
963 spr->_destX = newPosX;
964 spr->_destY = newPosY;
965 spr->_activeFl = true;
966 spr->_zoomPct = zoomPercent;
967 spr->_reducePct = reducePercent;
968
969 _liste[idx]._visibleFl = true;
970 _liste[idx]._posX = newPosX;
971 _liste[idx]._posY = newPosY;
972
973 int width = getWidth(spr->_spriteData, spr->_spriteIndex);
974 int height = getHeight(spr->_spriteData, spr->_spriteIndex);
975
976 if (zoomPercent) {
977 width = _vm->_graphicsMan->zoomIn(width, zoomPercent);
978 height = _vm->_graphicsMan->zoomIn(height, zoomPercent);
979 } else if (reducePercent) {
980 height = _vm->_graphicsMan->zoomOut(height, reducePercent);
981 width = _vm->_graphicsMan->zoomOut(width, reducePercent);
982 }
983
984 spr->_width = width;
985 spr->_height = height;
986 }
987
988 // Before Sort
beforeSort(SortMode sortMode,int index,int priority)989 void ObjectsManager::beforeSort(SortMode sortMode, int index, int priority) {
990 ++_sortedDisplayCount;
991 assert(_sortedDisplayCount <= 48);
992
993 _sortedDisplay[_sortedDisplayCount]._sortMode = sortMode;
994 _sortedDisplay[_sortedDisplayCount]._index = index;
995 _sortedDisplay[_sortedDisplayCount]._priority = priority;
996 }
997
998 // Display BOB Anim
displayBobAnim()999 void ObjectsManager::displayBobAnim() {
1000 for (int idx = 1; idx <= 35; idx++) {
1001 BobItem *bob = &_bob[idx];
1002 if (idx <= 20 && _charactersEnabledFl) {
1003 bob->_bobMode10 = false;
1004 continue;
1005 }
1006
1007 if (bob->_bobMode != 10)
1008 continue;
1009
1010 bob->_bobMode10 = false;
1011 if (bob->_animData == NULL || bob->_disabledAnimationFl || bob->_modeChangeCtr == 0 || bob->_modeChangeCtr < -1) {
1012 if (bob->_bobModeChange == 1 || bob->_bobModeChange == 2)
1013 bob->_bobMode10 = true;
1014 continue;
1015 }
1016
1017 if (bob->_moveChange1 == bob->_moveChange2) {
1018 bob->_bobMode10 = true;
1019 } else {
1020 bob->_moveChange2++;
1021 bob->_bobMode10 = false;
1022 }
1023
1024 if (!bob->_bobMode10) {
1025 if (bob->_bobModeChange == 1 || bob->_bobModeChange == 2)
1026 bob->_bobMode10 = true;
1027 continue;
1028 }
1029
1030 byte *dataPtr = bob->_animData + 20;
1031 int dataIdx = bob->_animDataIdx;
1032 bob->_xp = READ_LE_INT16(dataPtr + 2 * dataIdx);
1033 if (_lockedAnims[idx]._enableFl)
1034 bob->_xp = _lockedAnims[idx]._posX;
1035 if ( _charactersEnabledFl && idx > 20)
1036 bob->_xp += _vm->_events->_startPos.x;
1037
1038 bob->_yp = READ_LE_INT16(dataPtr + 2 * dataIdx + 2);
1039 bob->_moveChange1 = READ_LE_INT16(dataPtr + 2 * dataIdx + 4);
1040 bob->_zoomFactor = READ_LE_INT16(dataPtr + 2 * dataIdx + 6);
1041 bob->_frameIndex = dataPtr[2 * dataIdx + 8];
1042 bob->_flipFl = (dataPtr[2 * dataIdx + 9] != 0);
1043 bob->_animDataIdx += 5;
1044
1045 if (bob->_moveChange1 > 0) {
1046 bob->_moveChange1 /= _vm->_globals->_speed;
1047 if (bob->_moveChange1 > 0) {
1048 bob->_moveChange2 = 1;
1049 if (bob->_bobModeChange == 1 || bob->_bobModeChange == 2)
1050 bob->_bobMode10 = true;
1051 continue;
1052 }
1053
1054 bob->_moveChange1 = 1;
1055 }
1056 if (!bob->_moveChange1) {
1057 if (bob->_modeChangeCtr > 0)
1058 bob->_modeChangeCtr--;
1059 if (bob->_modeChangeCtr != -1 && bob->_modeChangeCtr <= 0) {
1060 bob->_bobMode = 11;
1061 } else {
1062 bob->_animDataIdx = 0;
1063 byte *bobData = bob->_animData + 20;
1064 bob->_xp = READ_LE_INT16(bobData);
1065
1066 if (_lockedAnims[idx]._enableFl)
1067 bob->_xp = _lockedAnims[idx]._posX;
1068 if (_charactersEnabledFl && idx > 20)
1069 bob->_xp += _vm->_events->_startPos.x;
1070
1071 bob->_yp = READ_LE_INT16(bobData + 2);
1072 bob->_moveChange1 = READ_LE_INT16(bobData + 4);
1073 bob->_zoomFactor = READ_LE_INT16(bobData + 6);
1074 bob->_frameIndex = bobData[8];
1075 bob->_flipFl = (bobData[9] != 0);
1076 bob->_animDataIdx += 5;
1077
1078 if (bob->_moveChange1 > 0) {
1079 bob->_moveChange1 /= _vm->_globals->_speed;
1080 // Original code. It can't be negative, so the check is on == 0
1081 if (bob->_moveChange1 <= 0)
1082 bob->_moveChange1 = 1;
1083 }
1084 }
1085 }
1086
1087 bob->_moveChange2 = 1;
1088 if (bob->_bobModeChange == 1 || bob->_bobModeChange == 2)
1089 bob->_bobMode10 = true;
1090 }
1091
1092 if (!_charactersEnabledFl && _refreshBobMode10Fl) {
1093 for (int i = 0; i < 35; i++) {
1094 BobItem *curBob = &_bob[i];
1095 if (curBob->_bobMode == 10 && !curBob->_disabledAnimationFl)
1096 curBob->_bobMode10 = true;
1097 }
1098 }
1099
1100 _refreshBobMode10Fl = false;
1101
1102 for (int i = 1; i <= 35; i++) {
1103 BobItem *curBob = &_bob[i];
1104 ListeItem *curList = &_liste2[i];
1105 if (i > 20 || !_charactersEnabledFl) {
1106 if ((curBob->_bobMode == 10) && (curBob->_bobMode10)) {
1107 if ((curBob->_bobModeChange != 2) && (curBob->_bobModeChange != 4)) {
1108 if (curList->_visibleFl) {
1109 _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, curList->_posX, curList->_posY,
1110 curList->_width, curList->_height, _vm->_graphicsMan->_frontBuffer, curList->_posX, curList->_posY);
1111 curList->_visibleFl = false;
1112 }
1113 }
1114 }
1115
1116 if (curBob->_bobMode == 11) {
1117 if (curList->_visibleFl) {
1118 _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, curList->_posX, curList->_posY,
1119 curList->_width, curList->_height, _vm->_graphicsMan->_frontBuffer, curList->_posX, curList->_posY);
1120 curList->_visibleFl = false;
1121 }
1122
1123 curBob->_bobMode = 0;
1124 }
1125 }
1126 }
1127
1128 for (int i = 1; i <= 35; i++) {
1129 BobItem *curBob = &_bob[i];
1130 curBob->_oldY = 0;
1131 if (curBob->_bobMode == 10 && !curBob->_disabledAnimationFl && curBob->_bobMode10) {
1132 initBobVariables(i);
1133 int priority = curBob->_oldX2 + curBob->_oldHeight + curBob->_oldY;
1134
1135 if (priority > 450)
1136 priority = 600;
1137
1138 if (curBob->_activeFl)
1139 beforeSort(SORT_BOB, i, priority);
1140 }
1141 }
1142 }
1143
1144 // Display VBOB
displayVBob()1145 void ObjectsManager::displayVBob() {
1146 int width, height;
1147
1148 for (int idx = 0; idx <= 29; idx++) {
1149 VBobItem *vbob = &_vBob[idx];
1150 if (vbob->_displayMode == 4) {
1151 width = getWidth(vbob->_spriteData, vbob->_frameIndex);
1152 height = getHeight(vbob->_spriteData, vbob->_frameIndex);
1153
1154 _vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_backBuffer, vbob->_surface,
1155 vbob->_xp, vbob->_yp, width, height);
1156
1157 _vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, vbob->_surface,
1158 vbob->_xp, vbob->_yp, width, height);
1159
1160 _vm->_graphicsMan->addDirtyRect(vbob->_xp, vbob->_yp, vbob->_xp + width, height + vbob->_yp);
1161 vbob->_surface = _vm->_globals->freeMemory(vbob->_surface);
1162
1163 vbob->_displayMode = 0;
1164 vbob->_spriteData = NULL;
1165 vbob->_xp = 0;
1166 vbob->_yp = 0;
1167 vbob->_oldX = 0;
1168 vbob->_oldY = 0;
1169 vbob->_frameIndex = 0;
1170 vbob->_oldFrameIndex = 0;
1171 vbob->_oldSpriteData = NULL;
1172 }
1173
1174 if (vbob->_displayMode == 3) {
1175 width = getWidth(vbob->_oldSpriteData, vbob->_oldFrameIndex);
1176 height = getHeight(vbob->_oldSpriteData, vbob->_oldFrameIndex);
1177
1178 _vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_backBuffer, vbob->_surface,
1179 vbob->_oldX, vbob->_oldY, width, height);
1180
1181 _vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, vbob->_surface,
1182 vbob->_oldX, vbob->_oldY, width, height);
1183
1184 _vm->_graphicsMan->addDirtyRect(vbob->_oldX, vbob->_oldY, vbob->_oldX + width, vbob->_oldY + height);
1185
1186 vbob->_displayMode = 1;
1187 vbob->_oldSpriteData = vbob->_spriteData;
1188
1189 vbob->_surface = _vm->_globals->freeMemory(vbob->_surface);
1190
1191 vbob->_oldX = vbob->_xp;
1192 vbob->_oldY = vbob->_yp;
1193 vbob->_oldFrameIndex = vbob->_frameIndex;
1194 }
1195
1196 if (vbob->_displayMode == 1) {
1197 width = getWidth(vbob->_spriteData, vbob->_frameIndex);
1198 height = getHeight(vbob->_spriteData, vbob->_frameIndex);
1199
1200 vbob->_surface = _vm->_globals->freeMemory(vbob->_surface);
1201
1202 byte *surface = _vm->_globals->allocMemory(height * width);
1203 vbob->_surface = surface;
1204
1205 _vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_backBuffer, surface,
1206 vbob->_xp, vbob->_yp, width, height);
1207
1208 if (*vbob->_spriteData == 78) {
1209 _vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_backBuffer, vbob->_spriteData,
1210 vbob->_xp + 300, vbob->_yp + 300, vbob->_frameIndex, 0, 0, false);
1211
1212 _vm->_graphicsMan->drawCompressedSprite(_vm->_graphicsMan->_frontBuffer, vbob->_spriteData,
1213 vbob->_xp + 300, vbob->_yp + 300, vbob->_frameIndex, 0, 0, false);
1214 } else {
1215 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_frontBuffer, vbob->_spriteData,
1216 vbob->_xp + 300, vbob->_yp + 300, vbob->_frameIndex);
1217
1218 _vm->_graphicsMan->drawVesaSprite(_vm->_graphicsMan->_backBuffer, vbob->_spriteData,
1219 vbob->_xp + 300, vbob->_yp + 300, vbob->_frameIndex);
1220 }
1221
1222 _vm->_graphicsMan->addDirtyRect(vbob->_xp, vbob->_yp , vbob->_xp + width, vbob->_yp + height);
1223 vbob->_displayMode = 2;
1224 }
1225 }
1226 }
1227
1228 /**
1229 * Get Sprite X coordinate
1230 */
getSpriteX(int idx)1231 int ObjectsManager::getSpriteX(int idx) {
1232 assert(idx <= MAX_SPRITE);
1233 return _sprite[idx]._spritePos.x;
1234 }
1235
1236 /**
1237 * Get Sprite Y coordinate
1238 */
getSpriteY(int idx)1239 int ObjectsManager::getSpriteY(int idx) {
1240 assert(idx <= MAX_SPRITE);
1241 return _sprite[idx]._spritePos.y;
1242 }
1243
1244 /**
1245 * Clear sprite structure
1246 */
clearSprite()1247 void ObjectsManager::clearSprite() {
1248 for (int idx = 0; idx < MAX_SPRITE; idx++) {
1249 _sprite[idx]._spriteData = NULL;
1250 _sprite[idx]._animationType = 0;
1251 }
1252
1253 for (int idx = 0; idx < MAX_SPRITE; idx++) {
1254 ListeItem *list = &_liste[idx];
1255 list->_visibleFl = false;
1256 list->_posX = 0;
1257 list->_posY = 0;
1258 list->_width = 0;
1259 list->_height = 0;
1260 }
1261 }
1262
animateSprite(int idx)1263 void ObjectsManager::animateSprite(int idx) {
1264 assert(idx <= MAX_SPRITE);
1265 _sprite[idx]._animationType = 1;
1266 }
1267
addStaticSprite(const byte * spriteData,Common::Point pos,int idx,int spriteIndex,int zoomFactor,bool flipFl,int deltaX,int deltaY)1268 void ObjectsManager::addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int deltaX, int deltaY) {
1269 assert(idx <= MAX_SPRITE);
1270
1271 SpriteItem *spr = &_sprite[idx];
1272 spr->_spriteData = spriteData;
1273 spr->_spritePos = pos;
1274 spr->_spriteIndex = spriteIndex;
1275 spr->_zoomFactor = zoomFactor;
1276 spr->_flipFl = flipFl;
1277 spr->_deltaX = deltaX;
1278 spr->_deltaY = deltaY;
1279 spr->_animationType = 0;
1280
1281 if (READ_BE_UINT24(spriteData) == MKTAG24('R', 'L', 'E')) {
1282 spr->_rleFl = true;
1283 spr->_zoomFactor = 0;
1284 spr->_flipFl = false;
1285 } else
1286 spr->_rleFl = false;
1287
1288 }
1289
1290 /**
1291 * Freeze sprite animation and free its memory
1292 */
removeSprite(int idx)1293 void ObjectsManager::removeSprite(int idx) {
1294 // Type 3 was also used by freeSprite(), which has been removed as it wasn't used
1295 _sprite[idx]._animationType = 3;
1296 }
1297
1298 /**
1299 * Set Sprite X coordinate
1300 */
setSpriteX(int idx,int xp)1301 void ObjectsManager::setSpriteX(int idx, int xp) {
1302 assert(idx <= MAX_SPRITE);
1303 _sprite[idx]._spritePos.x = xp;
1304 }
1305
1306 /**
1307 * Set Sprite Y coordinate
1308 */
setSpriteY(int idx,int yp)1309 void ObjectsManager::setSpriteY(int idx, int yp) {
1310 assert(idx <= MAX_SPRITE);
1311 _sprite[idx]._spritePos.y = yp;
1312 }
1313
1314 /**
1315 * Set Sprite Index
1316 */
setSpriteIndex(int idx,int spriteIndex)1317 void ObjectsManager::setSpriteIndex(int idx, int spriteIndex) {
1318 assert(idx <= MAX_SPRITE);
1319 _sprite[idx]._spriteIndex = spriteIndex;
1320 }
1321
1322 // Set Sprite Size
setSpriteZoom(int idx,int zoomFactor)1323 void ObjectsManager::setSpriteZoom(int idx, int zoomFactor) {
1324 assert(idx <= MAX_SPRITE);
1325 if (!_sprite[idx]._rleFl)
1326 _sprite[idx]._zoomFactor = zoomFactor;
1327 }
1328
setFlipSprite(int idx,bool flipFl)1329 void ObjectsManager::setFlipSprite(int idx, bool flipFl) {
1330 assert(idx <= MAX_SPRITE);
1331 if (!_sprite[idx]._rleFl)
1332 _sprite[idx]._flipFl = flipFl;
1333 }
1334
goHome()1335 void ObjectsManager::goHome() {
1336 if (_vm->_linesMan->_route == NULL)
1337 return;
1338
1339 if (_homeRateCounter > 1) {
1340 --_homeRateCounter;
1341 return;
1342 }
1343
1344 int newPosX;
1345 int newPosY;
1346 Directions newDirection;
1347
1348 int oldPosX = 0;
1349 int oldPosY = 0;
1350 int oldFrameIdx = 0;
1351 _homeRateCounter = 0;
1352 if (_oldDirection == DIR_NONE) {
1353 computeAndSetSpriteSize();
1354 newPosX = _vm->_linesMan->_route->_x;
1355 newPosY = _vm->_linesMan->_route->_y;
1356 newDirection = _vm->_linesMan->_route->_dir;
1357 _vm->_linesMan->_route++;
1358
1359 if (newPosX != -1 || newPosY != -1) {
1360 _oldDirection = newDirection;
1361 _oldDirectionSpriteIdx = newDirection + 59;
1362 _oldFrameIndex = 0;
1363 _oldCharacterPosX = newPosX;
1364 _oldCharacterPosY = newPosY;
1365 } else {
1366 setSpriteIndex(0, _oldDirection + 59);
1367 _vm->_globals->_actionDirection = DIR_NONE;
1368 int zoneId;
1369 if (_vm->_globals->_actionMoveTo)
1370 zoneId = _vm->_globals->_saveData->_data[svLastZoneNum];
1371 else
1372 zoneId = _zoneNum;
1373 _vm->_linesMan->_route = NULL;
1374 computeAndSetSpriteSize();
1375 setFlipSprite(0, false);
1376 _homeRateCounter = 0;
1377 _vm->_linesMan->_route = NULL;
1378 _oldDirection = DIR_NONE;
1379 if (zoneId > 0) {
1380 ZoneItem *curZone = &_vm->_linesMan->_zone[zoneId];
1381 if (curZone->_destX && curZone->_destY && curZone->_destY != 31) {
1382 if (curZone->_spriteIndex == -1) {
1383 curZone->_destX = 0;
1384 curZone->_destY = 0;
1385 curZone->_spriteIndex = 0;
1386 } else {
1387 setSpriteIndex(0, curZone->_spriteIndex);
1388 _vm->_globals->_actionDirection = curZone->_spriteIndex - 59;
1389 }
1390 }
1391 }
1392 }
1393 _homeRateCounter = 0;
1394 return;
1395 }
1396 if (_oldDirection == DIR_RIGHT) {
1397 if (_oldFrameIndex < 24 || _oldFrameIndex > 35) {
1398 oldPosX = _oldCharacterPosX;
1399 oldPosY = _oldCharacterPosY;
1400 oldFrameIdx = 24;
1401 } else {
1402 int deltaX = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedX;
1403 int deltaY = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY;
1404
1405 if (_sprite[0]._zoomFactor < 0) {
1406 deltaX = _vm->_graphicsMan->zoomOut(deltaX, -_sprite[0]._zoomFactor);
1407 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1408 } else if (_sprite[0]._zoomFactor > 0) {
1409 deltaX = _vm->_graphicsMan->zoomIn(deltaX, _sprite[0]._zoomFactor);
1410 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1411 }
1412 oldPosX = _oldCharacterPosX + deltaX;
1413 oldPosY = _oldCharacterPosY + deltaY;
1414 oldFrameIdx = _oldFrameIndex + 1;
1415 if (oldFrameIdx > 35)
1416 oldFrameIdx = 24;
1417 }
1418 _homeRateCounter = 5 / _vm->_globals->_speed;
1419 }
1420 if (_oldDirection == DIR_LEFT) {
1421 if (_oldFrameIndex < 24 || _oldFrameIndex > 35) {
1422 oldPosX = _oldCharacterPosX;
1423 oldPosY = _oldCharacterPosY;
1424 oldFrameIdx = 24;
1425 } else {
1426 int deltaX = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedX;
1427 int deltaY = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY;
1428 if (_sprite[0]._zoomFactor < 0) {
1429 deltaX = _vm->_graphicsMan->zoomOut(deltaX, -_sprite[0]._zoomFactor);
1430 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1431 } else if (_sprite[0]._zoomFactor > 0) {
1432 deltaX = _vm->_graphicsMan->zoomIn(deltaX, _sprite[0]._zoomFactor);
1433 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1434 }
1435 oldPosX = _oldCharacterPosX - deltaX;
1436 oldPosY = _oldCharacterPosY - deltaY;
1437 oldFrameIdx = _oldFrameIndex + 1;
1438 if (oldFrameIdx > 35)
1439 oldFrameIdx = 24;
1440 }
1441 _homeRateCounter = 5 / _vm->_globals->_speed;
1442 }
1443 if (_oldDirection == DIR_UP) {
1444 if (_oldFrameIndex > 11) {
1445 oldPosX = _oldCharacterPosX;
1446 oldPosY = _oldCharacterPosY;
1447 oldFrameIdx = 0;
1448 } else {
1449 int deltaY = abs(_vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY);
1450 if (_sprite[0]._zoomFactor < 0) {
1451 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1452 } else if (_sprite[0]._zoomFactor > 0) {
1453 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1454 }
1455 oldPosX = _oldCharacterPosX;
1456 oldPosY = _oldCharacterPosY - deltaY;
1457 oldFrameIdx = _oldFrameIndex + 1;
1458 if (oldFrameIdx > 11)
1459 oldFrameIdx = 0;
1460 }
1461 _homeRateCounter = 4 / _vm->_globals->_speed;
1462 }
1463
1464 if (_oldDirection == DIR_DOWN) {
1465 if (_oldFrameIndex < 48 || _oldFrameIndex > 59) {
1466 oldPosX = _oldCharacterPosX;
1467 oldPosY = _oldCharacterPosY;
1468 oldFrameIdx = 48;
1469 } else {
1470 int deltaY = abs(_vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY);
1471 if (_sprite[0]._zoomFactor < 0) {
1472 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1473 } else if (_sprite[0]._zoomFactor > 0) {
1474 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1475 }
1476 oldPosX = _oldCharacterPosX;
1477 oldPosY = deltaY + _oldCharacterPosY;
1478 oldFrameIdx = _oldFrameIndex + 1;
1479 if (oldFrameIdx > 59)
1480 oldFrameIdx = 48;
1481 }
1482 _homeRateCounter = 4 / _vm->_globals->_speed;
1483 }
1484 if (_oldDirection == DIR_UP_RIGHT) {
1485 if (_oldFrameIndex < 12 || _oldFrameIndex > 23) {
1486 oldPosX = _oldCharacterPosX;
1487 oldPosY = _oldCharacterPosY;
1488 oldFrameIdx = 12;
1489 } else {
1490 int deltaX = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedX;
1491 int deltaY = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY;
1492 if (_sprite[0]._zoomFactor < 0) {
1493 deltaX = _vm->_graphicsMan->zoomOut(deltaX, -_sprite[0]._zoomFactor);
1494 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1495 }
1496 if (_sprite[0]._zoomFactor > 0) {
1497 deltaX = _vm->_graphicsMan->zoomIn(deltaX, _sprite[0]._zoomFactor);
1498 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1499 }
1500 oldPosX = deltaX + _oldCharacterPosX;
1501 oldPosY = _oldCharacterPosY + deltaY;
1502 oldFrameIdx = _oldFrameIndex + 1;
1503 if (oldFrameIdx > 23)
1504 oldFrameIdx = 12;
1505 }
1506 _homeRateCounter = 5 / _vm->_globals->_speed;
1507 }
1508 if (_oldDirection == DIR_UP_LEFT) {
1509 if (_oldFrameIndex < 12 || _oldFrameIndex > 23) {
1510 oldPosX = _oldCharacterPosX;
1511 oldPosY = _oldCharacterPosY;
1512 oldFrameIdx = 12;
1513 } else {
1514 int deltaX = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedX;
1515 int deltaY = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY;
1516 if (_sprite[0]._zoomFactor < 0) {
1517 deltaX = _vm->_graphicsMan->zoomOut(deltaX, -_sprite[0]._zoomFactor);
1518 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1519 } else if (_sprite[0]._zoomFactor > 0) {
1520 deltaX = _vm->_graphicsMan->zoomIn(deltaX, _sprite[0]._zoomFactor);
1521 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1522 }
1523 oldPosX = _oldCharacterPosX - deltaX;
1524 oldPosY = _oldCharacterPosY + deltaY;
1525 oldFrameIdx = _oldFrameIndex + 1;
1526 if (oldFrameIdx > 23)
1527 oldFrameIdx = 12;
1528 }
1529 _homeRateCounter = 5 / _vm->_globals->_speed;
1530 }
1531 if (_oldDirection == DIR_DOWN_RIGHT) {
1532 if (_oldFrameIndex < 36 || _oldFrameIndex > 47) {
1533 oldPosX = _oldCharacterPosX;
1534 oldPosY = _oldCharacterPosY;
1535 oldFrameIdx = 36;
1536 } else {
1537 int deltaX = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedX;
1538 int deltaY = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY;
1539 if (_sprite[0]._zoomFactor < 0) {
1540 deltaX = _vm->_graphicsMan->zoomOut(deltaX, -_sprite[0]._zoomFactor);
1541 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1542 }
1543 if (_sprite[0]._zoomFactor > 0) {
1544 deltaX = _vm->_graphicsMan->zoomIn(deltaX, _sprite[0]._zoomFactor);
1545 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1546 }
1547 oldPosX = deltaX + _oldCharacterPosX;
1548 oldPosY = _oldCharacterPosY + deltaY;
1549 oldFrameIdx = _oldFrameIndex + 1;
1550 if (oldFrameIdx > 47)
1551 oldFrameIdx = 36;
1552 }
1553 _homeRateCounter = 5 / _vm->_globals->_speed;
1554 }
1555 if (_oldDirection == DIR_DOWN_LEFT) {
1556 if (_oldFrameIndex < 36 || _oldFrameIndex > 47) {
1557 oldPosX = _oldCharacterPosX;
1558 oldPosY = _oldCharacterPosY;
1559 oldFrameIdx = 36;
1560 } else {
1561 int deltaX = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedX;
1562 int deltaY = _vm->_globals->_hopkinsItem[_oldFrameIndex]._speedY;
1563 if (_sprite[0]._zoomFactor < 0) {
1564 deltaX = _vm->_graphicsMan->zoomOut(deltaX, -_sprite[0]._zoomFactor);
1565 deltaY = _vm->_graphicsMan->zoomOut(deltaY, -_sprite[0]._zoomFactor);
1566 }
1567 if (_sprite[0]._zoomFactor > 0) {
1568 deltaX = _vm->_graphicsMan->zoomIn(deltaX, _sprite[0]._zoomFactor);
1569 deltaY = _vm->_graphicsMan->zoomIn(deltaY, _sprite[0]._zoomFactor);
1570 }
1571 oldPosX = _oldCharacterPosX - deltaX;
1572 oldPosY = _oldCharacterPosY + deltaY;
1573 oldFrameIdx = _oldFrameIndex + 1;
1574 if (oldFrameIdx > 47)
1575 oldFrameIdx = 36;
1576 }
1577 _homeRateCounter = 5 / _vm->_globals->_speed;
1578 }
1579 bool loopCond = false;
1580 do {
1581 newPosX = _vm->_linesMan->_route->_x;
1582 newPosY = _vm->_linesMan->_route->_y;
1583 newDirection = (Directions)_vm->_linesMan->_route->_dir;
1584 _vm->_linesMan->_route++;
1585
1586 if (newPosX == -1 && newPosY == -1) {
1587 int zoneId;
1588 if (_vm->_globals->_actionMoveTo)
1589 zoneId = _vm->_globals->_saveData->_data[svLastZoneNum];
1590 else
1591 zoneId = _zoneNum;
1592 setSpriteIndex(0, _oldDirection + 59);
1593 _vm->_globals->_actionDirection = DIR_NONE;
1594 _vm->_linesMan->_route = NULL;
1595 computeAndSetSpriteSize();
1596 setFlipSprite(0, false);
1597 _homeRateCounter = 0;
1598 _oldDirection = DIR_NONE;
1599 _oldCharacterPosX = getSpriteX(0);
1600 _oldCharacterPosY = getSpriteY(0);
1601
1602 if (zoneId > 0) {
1603 ZoneItem *curZone = &_vm->_linesMan->_zone[zoneId];
1604 if (curZone->_destX && curZone->_destY && curZone->_destY != 31) {
1605 if ( curZone->_spriteIndex == -1) {
1606 curZone->_destX = 0;
1607 curZone->_destY = 0;
1608 curZone->_spriteIndex = 0;
1609 } else {
1610 setSpriteIndex(0, curZone->_spriteIndex);
1611 _vm->_globals->_actionDirection = curZone->_spriteIndex - 59;
1612 }
1613 }
1614 }
1615 _homeRateCounter = 0;
1616 return;
1617 }
1618 if (_oldDirection != newDirection)
1619 break;
1620 if ((newDirection == DIR_RIGHT && newPosX >= oldPosX) || (_oldDirection == DIR_LEFT && newPosX <= oldPosX) ||
1621 (_oldDirection == DIR_UP && newPosY <= oldPosY) || (_oldDirection == DIR_DOWN && newPosY >= oldPosY) ||
1622 (_oldDirection == DIR_UP_RIGHT && newPosX >= oldPosX) || (_oldDirection == DIR_UP_LEFT && newPosX <= oldPosX) ||
1623 (_oldDirection == DIR_DOWN_RIGHT && newPosX >= oldPosX) || (_oldDirection == DIR_DOWN_LEFT && newPosX <= oldPosX))
1624 loopCond = true;
1625 } while (!loopCond);
1626 if (loopCond) {
1627 computeAndSetSpriteSize();
1628 if ((_oldDirection == DIR_DOWN_LEFT) || (_oldDirection == DIR_LEFT) || (_oldDirection == DIR_UP_LEFT))
1629 setFlipSprite(0, true);
1630
1631 if ((_oldDirection == DIR_UP) || (_oldDirection == DIR_UP_RIGHT) || (_oldDirection == DIR_RIGHT) ||
1632 (_oldDirection == DIR_DOWN_RIGHT) || (_oldDirection == DIR_DOWN))
1633 setFlipSprite(0, false);
1634
1635 setSpriteX(0, newPosX);
1636 setSpriteY(0, newPosY);
1637 setSpriteIndex(0, oldFrameIdx);
1638 } else {
1639 if ((_oldDirection == DIR_DOWN_LEFT) || (_oldDirection == DIR_LEFT) || (_oldDirection == DIR_UP_LEFT))
1640 setFlipSprite(0, true);
1641
1642 if ((_oldDirection == DIR_UP) || (_oldDirection == DIR_UP_RIGHT) || (_oldDirection == DIR_RIGHT) ||
1643 (_oldDirection == DIR_DOWN_RIGHT) || (_oldDirection == DIR_DOWN))
1644 setFlipSprite(0, false);
1645 _homeRateCounter = 0;
1646 }
1647 _oldDirection = newDirection;
1648 _oldDirectionSpriteIdx = newDirection + 59;
1649 _oldFrameIndex = oldFrameIdx;
1650 _oldCharacterPosX = newPosX;
1651 _oldCharacterPosY = newPosY;
1652 }
1653
goHome2()1654 void ObjectsManager::goHome2() {
1655 if (_vm->_linesMan->_route == NULL)
1656 return;
1657
1658 int realSpeed = 2;
1659 if (_vm->_globals->_speed == 2)
1660 realSpeed = 4;
1661 else if (_vm->_globals->_speed == 3)
1662 realSpeed = 6;
1663
1664 int countColisionPixel = 0;
1665
1666 for (;;) {
1667 int nexPosX = _vm->_linesMan->_route->_x;
1668 int newPosY = _vm->_linesMan->_route->_y;
1669 Directions newDirection = (Directions)_vm->_linesMan->_route->_dir;
1670 _vm->_linesMan->_route++;
1671
1672 if ((nexPosX == -1) && (newPosY == -1))
1673 break;
1674
1675 ++countColisionPixel;
1676 if (countColisionPixel >= realSpeed) {
1677 _lastDirection = newDirection;
1678 setSpriteX(0, nexPosX);
1679 setSpriteY(0, newPosY);
1680 switch (_lastDirection) {
1681 case DIR_UP:
1682 setSpriteIndex(0, 4);
1683 break;
1684 case DIR_RIGHT:
1685 setSpriteIndex(0, 5);
1686 break;
1687 case DIR_DOWN:
1688 setSpriteIndex(0, 6);
1689 break;
1690 case DIR_LEFT:
1691 setSpriteIndex(0, 7);
1692 break;
1693 default:
1694 break;
1695 }
1696
1697 return;
1698 }
1699 }
1700
1701 switch (_lastDirection) {
1702 case DIR_UP:
1703 setSpriteIndex(0, 0);
1704 break;
1705 case DIR_RIGHT:
1706 setSpriteIndex(0, 1);
1707 break;
1708 case DIR_DOWN:
1709 setSpriteIndex(0, 2);
1710 break;
1711 case DIR_LEFT:
1712 setSpriteIndex(0, 3);
1713 break;
1714 default:
1715 break;
1716 }
1717
1718 _vm->_linesMan->_route = NULL;
1719 }
1720
1721 /**
1722 * Load Zone
1723 */
loadZone(const Common::String & file)1724 void ObjectsManager::loadZone(const Common::String &file) {
1725 for (int i = 1; i <= 100; i++) {
1726 ZoneItem *curZone = &_vm->_linesMan->_zone[i];
1727 curZone->_destX = 0;
1728 curZone->_destY = 0;
1729 curZone->_spriteIndex = 0;
1730 curZone->_verbFl1 = 0;
1731 curZone->_verbFl2 = 0;
1732 curZone->_verbFl3 = 0;
1733 curZone->_verbFl4 = 0;
1734 curZone->_verbFl5 = 0;
1735 curZone->_verbFl6 = 0;
1736 curZone->_verbFl7 = 0;
1737 curZone->_verbFl8 = 0;
1738 curZone->_verbFl9 = 0;
1739 curZone->_verbFl10 = 0;
1740 curZone->_messageId = 0;
1741 curZone->_enabledFl = false;
1742 }
1743
1744 Common::File f;
1745 if (!f.exists(file))
1746 error("File not found : %s", file.c_str());
1747
1748 byte *ptr = _vm->_fileIO->loadFile(file);
1749 int bufId = 0;
1750 int zoneLineIdx = 0;
1751 int bobZoneIdx;
1752 do {
1753 bobZoneIdx = READ_LE_INT16((uint16 *)ptr + bufId);
1754 if (bobZoneIdx != -1) {
1755 _vm->_linesMan->addZoneLine(
1756 zoneLineIdx,
1757 READ_LE_UINT16((uint16 *)ptr + bufId + 1),
1758 READ_LE_UINT16((uint16 *)ptr + bufId + 2),
1759 READ_LE_UINT16((uint16 *)ptr + bufId + 3),
1760 READ_LE_UINT16((uint16 *)ptr + bufId + 4),
1761 bobZoneIdx);
1762 _vm->_linesMan->_zone[bobZoneIdx]._enabledFl = true;
1763 }
1764 bufId += 5;
1765 ++zoneLineIdx;
1766 } while (bobZoneIdx != -1);
1767
1768 for (int i = 1; i <= 100; i++) {
1769 ZoneItem *curZone = &_vm->_linesMan->_zone[i];
1770 curZone->_destX = READ_LE_INT16((uint16 *)ptr + bufId);
1771 curZone->_destY = READ_LE_INT16((uint16 *)ptr + bufId + 1);
1772 curZone->_spriteIndex = READ_LE_INT16((uint16 *)ptr + bufId + 2);
1773 bufId += 3;
1774 }
1775
1776 byte *verbData = (ptr + 10 * zoneLineIdx + 606);
1777 bufId = 0;
1778 for (int i = 1; i <= 100; i++) {
1779 ZoneItem *curZone = &_vm->_linesMan->_zone[i];
1780 curZone->_verbFl1 = verbData[bufId];
1781 curZone->_verbFl2 = verbData[bufId + 1];
1782 curZone->_verbFl3 = verbData[bufId + 2];
1783 curZone->_verbFl4 = verbData[bufId + 3];
1784 curZone->_verbFl5 = verbData[bufId + 4];
1785 curZone->_verbFl6 = verbData[bufId + 5];
1786 curZone->_verbFl7 = verbData[bufId + 6];
1787 curZone->_verbFl8 = verbData[bufId + 7];
1788 curZone->_verbFl9 = verbData[bufId + 8];
1789 curZone->_verbFl10 = verbData[bufId + 9];
1790
1791 bufId += 10;
1792 }
1793 verbData += 1010;
1794 for (int i = 0; i < 100; i++)
1795 _vm->_linesMan->_zone[i + 1]._messageId = READ_LE_UINT16(verbData + 2 * i);
1796
1797 _vm->_globals->freeMemory(ptr);
1798 _vm->_linesMan->initSquareZones();
1799 }
1800
handleCityMap()1801 void ObjectsManager::handleCityMap() {
1802 _vm->_dialog->_inventFl = false;
1803 _vm->_events->_gameKey = KEY_NONE;
1804 _vm->_linesMan->setMaxLineIdx(1);
1805 _vm->_globals->_characterMaxPosY = 440;
1806 _vm->_globals->_cityMapEnabledFl = true;
1807 _vm->_graphicsMan->_noFadingFl = false;
1808 _vm->_globals->_freezeCharacterFl = false;
1809 _spritePtr = NULL;
1810 _vm->_globals->_exitId = 0;
1811 _vm->_globals->_checkDistanceFl = true;
1812 _vm->_soundMan->playSound(31);
1813 _vm->_globals->_eventMode = EVENTMODE_IGNORE;
1814 _vm->_graphicsMan->loadImage("PLAN");
1815 _vm->_linesMan->loadLines("PLAN.OB2");
1816 loadHidingItems("PLAN.CA2");
1817 loadZone("PLAN.ZO2");
1818 _spritePtr = _vm->_fileIO->loadFile("VOITURE.SPR");
1819 _vm->_animMan->loadAnim("PLAN");
1820 _vm->_graphicsMan->displayAllBob();
1821 _vm->_graphicsMan->initScreen("PLAN", 2, false);
1822 for (int i = 0; i <= 15; i++)
1823 disableHidingItem(i);
1824 disableHidingItem(19);
1825 disableHidingItem(20);
1826 enableHidingBehavior();
1827
1828 if (!_mapCarPosX && !_mapCarPosY) {
1829 _mapCarPosX = 900;
1830 _mapCarPosY = 319;
1831 }
1832 addStaticSprite(_spritePtr, Common::Point(_mapCarPosX, _mapCarPosY), 0, 1, 0, false, 5, 5);
1833 _vm->_events->setMouseXY(_mapCarPosX, _mapCarPosY);
1834 _vm->_events->mouseOn();
1835 _vm->_graphicsMan->scrollScreen(getSpriteX(0) - 320);
1836 _vm->_graphicsMan->_scrollOffset = getSpriteX(0) - 320;
1837 animateSprite(0);
1838 _vm->_linesMan->_route = NULL;
1839 _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
1840 _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
1841 _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
1842 _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
1843
1844 for (int i = 0; i <= 4; i++)
1845 _vm->_events->refreshScreenAndEvents();
1846
1847 _vm->_globals->_eventMode = EVENTMODE_IGNORE;
1848 _vm->_graphicsMan->fadeInLong();
1849 _vm->_events->changeMouseCursor(4);
1850 _vm->_graphicsMan->_noFadingFl = false;
1851
1852 bool loopCond = false;
1853 do {
1854 int mouseButton = _vm->_events->getMouseButton();
1855 if (mouseButton) {
1856 // First cop call : Go to the bank and free the hostages
1857 if (_vm->_globals->_saveData->_data[svBankAttackAnimPlayedFl] == 1 && !_vm->_globals->_saveData->_data[svCopCall1PlayedFl]) {
1858 _vm->_globals->_saveData->_data[svCopCall1PlayedFl] = 1;
1859 _vm->_globals->_introSpeechOffFl = true;
1860 _vm->_talkMan->startAnimatedCharacterDialogue("APPEL1.pe2");
1861 _vm->_globals->_introSpeechOffFl = false;
1862 mouseButton = 0;
1863 }
1864 // Second cop call: Helico has been found in the empty lot
1865 if (_vm->_globals->_saveData->_data[svFreedHostageFl] == 1 && !_vm->_globals->_saveData->_data[svCopCall2PlayedFl]) {
1866 _vm->_globals->_saveData->_data[svCopCall2PlayedFl] = 1;
1867 _vm->_globals->_introSpeechOffFl = true;
1868 _vm->_talkMan->startAnimatedCharacterDialogue("APPEL2.pe2");
1869 _vm->_globals->_introSpeechOffFl = false;
1870 mouseButton = 0;
1871 _vm->_events->_curMouseButton = 0;
1872 }
1873 if (mouseButton == 1)
1874 handleLeftButton();
1875 }
1876
1877 _vm->_linesMan->checkZone();
1878 goHome2();
1879
1880 if (_vm->_linesMan->_route == NULL && _vm->_globals->_actionMoveTo)
1881 paradise();
1882 _vm->_events->refreshScreenAndEvents();
1883
1884 if (_vm->_globals->_exitId)
1885 loopCond = true;
1886 } while (!_vm->shouldQuit() && !loopCond);
1887
1888 if (!_vm->_graphicsMan->_noFadingFl)
1889 _vm->_graphicsMan->fadeOutLong();
1890 _vm->_globals->_eventMode = EVENTMODE_DEFAULT;
1891 _vm->_graphicsMan->_noFadingFl = false;
1892 _mapCarPosX = getSpriteX(0);
1893 _mapCarPosY = getSpriteY(0);
1894 removeSprite(0);
1895 _spritePtr = _vm->_globals->freeMemory(_spritePtr);
1896 clearScreen();
1897 _vm->_globals->_cityMapEnabledFl = false;
1898 }
1899
1900 /**
1901 * Handle Left button
1902 */
handleLeftButton()1903 void ObjectsManager::handleLeftButton() {
1904 _vm->_fontMan->hideText(9);
1905 int destX = _vm->_events->getMouseX();
1906 int destY = _vm->_events->getMouseY();
1907
1908 if (!_vm->_dialog->_inventFl && !_vm->_globals->_cityMapEnabledFl &&
1909 destX > _vm->_graphicsMan->_scrollOffset - 30 && destX < _vm->_graphicsMan->_scrollOffset + 50 &&
1910 destY > -30 && destY < 50) {
1911 int oldMouseCursor = _vm->_events->_mouseCursorId;
1912 _vm->_dialog->_inventFl = true;
1913 _vm->_dialog->showInventory();
1914 _vm->_dialog->_inventFl = false;
1915 _vm->_events->_gameKey = KEY_NONE;
1916 if (!_vm->_globals->_exitId) {
1917 _vm->_dialog->_inventFl = false;
1918 _vm->_events->_mouseCursorId = oldMouseCursor;
1919 }
1920 return;
1921 }
1922 if (_vm->_globals->_saveData->_data[svField354] == 1 && !_vm->_globals->_cityMapEnabledFl
1923 && destX >= 533 && destX <= 559 && destY >= 26 && destY <= 59) {
1924 changeCharacterHead(CHARACTER_HOPKINS_CLONE, CHARACTER_HOPKINS);
1925 return;
1926 }
1927 if (_vm->_globals->_saveData->_data[svField356] == 1 && !_vm->_globals->_cityMapEnabledFl
1928 && destX >= 533 && destX <= 559 && destY >= 26 && destY <= 48) {
1929 changeCharacterHead(CHARACTER_SAMANTHA, CHARACTER_HOPKINS);
1930 return;
1931 }
1932 if (_vm->_globals->_saveData->_data[svField357] == 1) {
1933 if (_vm->_globals->_saveData->_data[svField353] == 1 && !_vm->_globals->_cityMapEnabledFl
1934 && destX >= 533 && destX <= 559 && destY >= 26 && destY <= 59) {
1935 changeCharacterHead(CHARACTER_HOPKINS, CHARACTER_HOPKINS_CLONE);
1936 return;
1937 }
1938 if (_vm->_globals->_saveData->_data[svField355] == 1 && !_vm->_globals->_cityMapEnabledFl
1939 && destX >= 567 && destX <= 593 && destY >= 26 && destY <= 59) {
1940 changeCharacterHead(CHARACTER_HOPKINS, CHARACTER_SAMANTHA);
1941 return;
1942 }
1943 }
1944 if (_vm->_globals->_cityMapEnabledFl && _vm->_globals->_actionMoveTo) {
1945 _vm->_linesMan->checkZone();
1946 if (_zoneNum <= 0)
1947 return;
1948 int routeIdx = 0;
1949 do {
1950 _vm->_linesMan->_testRoute2[routeIdx] = _vm->_linesMan->_route[routeIdx];
1951 ++routeIdx;
1952 } while (_vm->_linesMan->_route[routeIdx]._x != -1);
1953
1954 _vm->_linesMan->_testRoute2[routeIdx].invalidate();
1955 }
1956
1957 if (_vm->_globals->_actionMoveTo) {
1958 _vm->_linesMan->checkZone();
1959 _vm->_globals->_actionMoveTo = false;
1960 _vm->_globals->_saveData->_data[svLastMouseCursor] = 0;
1961 _vm->_globals->_saveData->_data[svLastZoneNum] = 0;
1962 }
1963
1964 if (_vm->_globals->_cityMapEnabledFl && (_vm->_events->_mouseCursorId != 4 || _zoneNum <= 0))
1965 return;
1966 if (_zoneNum != -1 && _zoneNum != 0) {
1967 ZoneItem *curZone = &_vm->_linesMan->_zone[_zoneNum];
1968 if (curZone->_destX && curZone->_destY && curZone->_destY != 31) {
1969 destX = curZone->_destX;
1970 destY = curZone->_destY;
1971 }
1972 }
1973 _vm->_globals->_actionMoveTo = false;
1974 RouteItem *oldRoute = _vm->_linesMan->_route;
1975 _vm->_linesMan->_route = NULL;
1976 if (_forestFl && _zoneNum >= 20 && _zoneNum <= 23) {
1977 if (getSpriteY(0) > 374 && getSpriteY(0) <= 410) {
1978 _vm->_linesMan->_route = NULL;
1979 setSpriteIndex(0, _oldDirectionSpriteIdx);
1980 _vm->_globals->_actionDirection = DIR_NONE;
1981 _vm->_linesMan->_route = NULL;
1982 computeAndSetSpriteSize();
1983 setFlipSprite(0, false);
1984 _homeRateCounter = 0;
1985 _oldDirection = DIR_NONE;
1986 } else {
1987 _vm->_linesMan->_route = _vm->_linesMan->findRoute(getSpriteX(0), getSpriteY(0), getSpriteX(0), 390);
1988 if (_vm->_linesMan->_route)
1989 _vm->_linesMan->optimizeRoute(_vm->_linesMan->_route);
1990 _oldCharacterPosX = getSpriteX(0);
1991 _oldCharacterPosY = getSpriteY(0);
1992 _homeRateCounter = 0;
1993 if (_vm->_linesMan->_route || oldRoute == _vm->_linesMan->_route) {
1994 _oldDirection = DIR_NONE;
1995 } else {
1996 _vm->_linesMan->_route = oldRoute;
1997 }
1998 }
1999 } else {
2000 if (!_vm->_globals->_freezeCharacterFl && !_vm->_globals->_cityMapEnabledFl) {
2001 _vm->_linesMan->_route = _vm->_linesMan->findRoute(getSpriteX(0), getSpriteY(0), destX, destY);
2002 if (_vm->_linesMan->_route)
2003 _vm->_linesMan->optimizeRoute(_vm->_linesMan->_route);
2004 _oldCharacterPosX = getSpriteX(0);
2005 _oldCharacterPosY = getSpriteY(0);
2006 _homeRateCounter = 0;
2007 if (_vm->_linesMan->_route || oldRoute == _vm->_linesMan->_route)
2008 _oldDirection = DIR_NONE;
2009 else
2010 _vm->_linesMan->_route = oldRoute;
2011 }
2012 }
2013
2014 if (!_vm->_globals->_freezeCharacterFl && _vm->_globals->_cityMapEnabledFl)
2015 _vm->_linesMan->_route = _vm->_linesMan->cityMapCarRoute(getSpriteX(0), getSpriteY(0), destX, destY);
2016
2017 if (_zoneNum != -1 && _zoneNum != 0) {
2018 if (_vm->_events->_mouseCursorId == 23)
2019 _vm->_globals->_saveData->_data[svLastMouseCursor] = 5;
2020 else
2021 _vm->_globals->_saveData->_data[svLastMouseCursor] = _vm->_events->_mouseCursorId;
2022
2023 if (_vm->_globals->_cityMapEnabledFl)
2024 _vm->_globals->_saveData->_data[svLastMouseCursor] = 6;
2025 _vm->_globals->_saveData->_data[svLastZoneNum] = _zoneNum;
2026 _vm->_globals->_saveData->_data[svLastObjectIndex] = _curObjectIndex;
2027 _vm->_globals->_actionMoveTo = true;
2028 }
2029 _vm->_fontMan->hideText(5);
2030 _vm->_graphicsMan->setColorPercentage2(251, 100, 100, 100);
2031 if (_vm->_globals->_screenId == 20 && _vm->_globals->_saveData->_data[svField132] == 1
2032 && _curObjectIndex == 20 && _zoneNum == 12
2033 && _vm->_events->_mouseCursorId == 23) {
2034 // Special case for throwing darts at the switch in Purgatory - the player shouldn't move
2035 _vm->_linesMan->_route = NULL;
2036 getSpriteX(0);
2037 getSpriteY(0);
2038 }
2039 }
2040
paradise()2041 void ObjectsManager::paradise() {
2042 char result = _vm->_globals->_saveData->_data[svLastMouseCursor];
2043 if (result && _vm->_globals->_saveData->_data[svLastZoneNum] && result != 4 && result > 3) {
2044 _vm->_fontMan->hideText(5);
2045 if (!_forestFl || _zoneNum < 20 || _zoneNum > 23) {
2046 if (_vm->_graphicsMan->_largeScreenFl) {
2047 _vm->_graphicsMan->_scrollStatus = 2;
2048 if (_vm->_events->_startPos.x + 320 - getSpriteX(0) > 160) {
2049 bool loopCond = false;
2050 do {
2051 _vm->_graphicsMan->_scrollPosX -= _vm->_graphicsMan->_scrollSpeed;
2052 if (_vm->_graphicsMan->_scrollPosX < 0) {
2053 _vm->_graphicsMan->_scrollPosX = 0;
2054 loopCond = true;
2055 }
2056 if (_vm->_graphicsMan->_scrollPosX > SCREEN_WIDTH) {
2057 _vm->_graphicsMan->_scrollPosX = SCREEN_WIDTH;
2058 loopCond = true;
2059 }
2060 if (_vm->_events->getMouseX() > _vm->_graphicsMan->_scrollPosX + 620)
2061 _vm->_events->setMouseXY(_vm->_events->_mousePos.x - 4, _vm->_events->getMouseY());
2062
2063 _vm->_events->refreshScreenAndEvents();
2064 } while (!loopCond && _vm->_events->_startPos.x > getSpriteX(0) - 320);
2065 } else if (_vm->_events->_startPos.x + 320 - getSpriteX(0) < -160) {
2066 bool loopCond = false;
2067 do {
2068 _vm->_graphicsMan->_scrollPosX += _vm->_graphicsMan->_scrollSpeed;
2069 if (_vm->_graphicsMan->_scrollPosX < 0) {
2070 _vm->_graphicsMan->_scrollPosX = 0;
2071 loopCond = true;
2072 }
2073 if (_vm->_graphicsMan->_scrollPosX > SCREEN_WIDTH) {
2074 _vm->_graphicsMan->_scrollPosX = SCREEN_WIDTH;
2075 loopCond = true;
2076 }
2077 if (_vm->_events->getMouseX() < _vm->_graphicsMan->_scrollPosX + 10)
2078 _vm->_events->setMouseXY(_vm->_events->_mousePos.x + 4, _vm->_events->getMouseY());
2079
2080 _vm->_events->refreshScreenAndEvents();
2081 } while (!loopCond && _vm->_events->_startPos.x < getSpriteX(0) - 320);
2082 }
2083 if (_vm->_events->getMouseX() > _vm->_graphicsMan->_scrollPosX + 620)
2084 _vm->_events->setMouseXY(_vm->_graphicsMan->_scrollPosX + 610, 0);
2085 if (_vm->_events->getMouseX() < _vm->_graphicsMan->_scrollPosX + 10)
2086 _vm->_events->setMouseXY(_vm->_graphicsMan->_scrollPosX + 10, 0);
2087 _vm->_events->refreshScreenAndEvents();
2088 _vm->_graphicsMan->_scrollStatus = 0;
2089 }
2090 _vm->_talkMan->handleAnswer(_vm->_globals->_saveData->_data[svLastZoneNum], _vm->_globals->_saveData->_data[svLastMouseCursor]);
2091 } else {
2092 _vm->_talkMan->handleForestAnswser(_vm->_globals->_saveData->_data[svLastZoneNum], _vm->_globals->_saveData->_data[svLastMouseCursor]);
2093 }
2094 _vm->_events->changeMouseCursor(4);
2095 if (_zoneNum != -1 && _zoneNum != 0 && !_vm->_linesMan->_zone[_zoneNum]._enabledFl) {
2096 _zoneNum = -1;
2097 _forceZoneFl = true;
2098 }
2099 if (_zoneNum != _vm->_globals->_saveData->_data[svLastZoneNum] || _zoneNum == -1 || _zoneNum == 0) {
2100 _vm->_events->_mouseCursorId = 4;
2101 _changeVerbFl = false;
2102 } else {
2103 _vm->_events->_mouseCursorId = _vm->_globals->_saveData->_data[svLastMouseCursor];
2104 if (_changeVerbFl) {
2105 nextVerbIcon();
2106 _changeVerbFl = false;
2107 }
2108 if (_vm->_events->_mouseCursorId == 5)
2109 _vm->_events->_mouseCursorId = 4;
2110 }
2111 if (_vm->_events->_mouseCursorId != 23)
2112 _vm->_events->changeMouseCursor(_vm->_events->_mouseCursorId);
2113 _zoneNum = 0;
2114 _vm->_globals->_saveData->_data[svLastMouseCursor] = 0;
2115 _vm->_globals->_saveData->_data[svLastZoneNum] = 0;
2116 }
2117 if (_vm->_globals->_cityMapEnabledFl) {
2118 _vm->_events->_mouseCursorId = 0;
2119 _vm->_events->changeMouseCursor(0);
2120 }
2121 if (_vm->_globals->_freezeCharacterFl && _vm->_events->_mouseCursorId == 4) {
2122 if (_zoneNum != -1 && _zoneNum != 0)
2123 handleRightButton();
2124 }
2125 _vm->_globals->_actionMoveTo = false;
2126 }
2127
2128 /**
2129 * Clear Screen
2130 */
clearScreen()2131 void ObjectsManager::clearScreen() {
2132 clearSprite();
2133 _vm->_graphicsMan->endDisplayBob();
2134 _vm->_fontMan->hideText(5);
2135 _vm->_fontMan->hideText(9);
2136 clearVBob();
2137 _vm->_animMan->clearAnim();
2138 _vm->_linesMan->clearAllZones();
2139 _vm->_linesMan->resetLines();
2140 resetHidingItems();
2141
2142 for (int i = 0; i <= 48; i++) {
2143 _vm->_linesMan->_bobZone[i] = 0;
2144 _vm->_linesMan->_bobZoneFl[i] = false;
2145 }
2146 _vm->_events->_mouseCursorId = 4;
2147 _verb = 4;
2148 _zoneNum = 0;
2149 _forceZoneFl = true;
2150 _vm->_linesMan->resetLinesNumb();
2151 _vm->_linesMan->resetLastLine();
2152 _vm->_linesMan->_route = NULL;
2153 _vm->_globals->_answerBuffer = _vm->_globals->freeMemory(_vm->_globals->_answerBuffer);
2154 _vm->_globals->_levelSpriteBuf = _vm->_globals->freeMemory(_vm->_globals->_levelSpriteBuf);
2155 _vm->_events->_startPos.x = 0;
2156 _vm->_events->_mouseSpriteId = 0;
2157 _vm->_globals->_saveData->_data[svLastMouseCursor] = 0;
2158 _vm->_globals->_saveData->_data[svLastZoneNum] = 0;
2159 _vm->_globals->_actionMoveTo = false;
2160 _forceZoneFl = true;
2161 _changeVerbFl = false;
2162 _vm->_linesMan->_route = NULL;
2163 _oldDirection = DIR_NONE;
2164 _vm->_graphicsMan->resetDirtyRects();
2165 }
2166
2167 /**
2168 * Change the currently active player face / Head
2169 * @param oldCharacter Previously played character
2170 * @param newCharacter New character to play
2171 */
changeCharacterHead(PlayerCharacter oldCharacter,PlayerCharacter newCharacter)2172 void ObjectsManager::changeCharacterHead(PlayerCharacter oldCharacter, PlayerCharacter newCharacter) {
2173 CharacterLocation *loc;
2174
2175 _changeHeadFl = true;
2176 _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, 532, 25, 65, 40, _vm->_graphicsMan->_frontBuffer, 532, 25);
2177 _vm->_graphicsMan->addDirtyRect(532, 25, 597, 65);
2178 _vm->_globals->_checkDistanceFl = true;
2179 _vm->_linesMan->_route = NULL;
2180
2181 if (oldCharacter == CHARACTER_SAMANTHA && newCharacter == CHARACTER_HOPKINS
2182 && _vm->_globals->_saveData->_realHopkins._location == _vm->_globals->_screenId) {
2183 _changeHeadFl = false;
2184 loc = &_vm->_globals->_saveData->_samantha;
2185 loc->_pos.x = getSpriteX(0);
2186 loc->_pos.y = getSpriteY(0);
2187 loc->_startSpriteIndex = 64;
2188 loc->_location = _vm->_globals->_screenId;
2189 loc->_zoomFactor = _sprite[0]._zoomFactor;
2190
2191 removeSprite(1);
2192 addStaticSprite(_headSprites, loc->_pos, 1, 3, loc->_zoomFactor, false, 20, 127);
2193 animateSprite(1);
2194 removeSprite(0);
2195
2196 _vm->_globals->_saveData->_data[svField354] = 0;
2197 _vm->_globals->_saveData->_data[svField356] = 0;
2198 _vm->_globals->_saveData->_data[svField357] = 1;
2199
2200 loc = &_vm->_globals->_saveData->_realHopkins;
2201 _vm->_globals->_characterSpriteBuf = _vm->_fileIO->loadFile("PERSO.SPR");
2202 _vm->_globals->_characterType = CHARACTER_HOPKINS;
2203 addStaticSprite(_vm->_globals->_characterSpriteBuf, loc->_pos, 0, 64, loc->_zoomFactor, false, 34, 190);
2204 animateSprite(0);
2205 _vm->_globals->loadCharacterData();
2206 } else if (oldCharacter == CHARACTER_HOPKINS && newCharacter == CHARACTER_SAMANTHA
2207 && _vm->_globals->_saveData->_samantha._location == _vm->_globals->_screenId) {
2208 _changeHeadFl = false;
2209 loc = &_vm->_globals->_saveData->_realHopkins;
2210 loc->_pos.x = getSpriteX(0);
2211 loc->_pos.y = getSpriteY(0);
2212 loc->_startSpriteIndex = 64;
2213 loc->_location = _vm->_globals->_screenId;
2214 loc->_zoomFactor = _sprite[0]._zoomFactor;
2215
2216 removeSprite(1);
2217 addStaticSprite(_headSprites, loc->_pos, 1, 2, loc->_zoomFactor, false, 34, 190);
2218 animateSprite(1);
2219 removeSprite(0);
2220
2221 _vm->_globals->_saveData->_data[svField354] = 0;
2222 _vm->_globals->_saveData->_data[svField356] = 1;
2223 _vm->_globals->_saveData->_data[svField357] = 0;
2224
2225 loc = &_vm->_globals->_saveData->_samantha;
2226 _vm->_globals->_characterSpriteBuf = _vm->_fileIO->loadFile("PSAMAN.SPR");
2227 _vm->_globals->_characterType = CHARACTER_SAMANTHA;
2228 addStaticSprite(_vm->_globals->_characterSpriteBuf, loc->_pos, 0, 64, loc->_zoomFactor, false, 20, 127);
2229 animateSprite(0);
2230 _vm->_globals->loadCharacterData();
2231 } else {
2232 switch (oldCharacter) {
2233 case CHARACTER_HOPKINS:
2234 loc = &_vm->_globals->_saveData->_realHopkins;
2235 loc->_pos.x = getSpriteX(0);
2236 loc->_pos.y = getSpriteY(0);
2237 loc->_startSpriteIndex = 64;
2238 loc->_location = _vm->_globals->_screenId;
2239 loc->_zoomFactor = _sprite[0]._zoomFactor;
2240 break;
2241 case CHARACTER_HOPKINS_CLONE:
2242 loc = &_vm->_globals->_saveData->_cloneHopkins;
2243 loc->_pos.x = getSpriteX(0);
2244 loc->_pos.y = getSpriteY(0);
2245 loc->_startSpriteIndex = 64;
2246 loc->_location = _vm->_globals->_screenId;
2247 loc->_zoomFactor = _sprite[0]._zoomFactor;
2248 break;
2249 case CHARACTER_SAMANTHA:
2250 loc = &_vm->_globals->_saveData->_samantha;
2251 loc->_pos.x = getSpriteX(0);
2252 loc->_pos.y = getSpriteY(0);
2253 loc->_startSpriteIndex = 64;
2254 loc->_location = _vm->_globals->_screenId;
2255 loc->_zoomFactor = _sprite[0]._zoomFactor;
2256 break;
2257 default:
2258 break;
2259 }
2260
2261 switch (newCharacter) {
2262 case CHARACTER_HOPKINS:
2263 _vm->_globals->_saveData->_data[svHopkinsCloneFl] = 0;
2264 _vm->_globals->_saveData->_data[svField354] = 0;
2265 _vm->_globals->_saveData->_data[svField356] = 0;
2266 _vm->_globals->_saveData->_data[svField357] = 1;
2267 _vm->_globals->_exitId = _vm->_globals->_saveData->_realHopkins._location;
2268 break;
2269 case CHARACTER_HOPKINS_CLONE:
2270 _vm->_globals->_saveData->_data[svHopkinsCloneFl] = 1;
2271 _vm->_globals->_saveData->_data[svField354] = 1;
2272 _vm->_globals->_saveData->_data[svField356] = 0;
2273 _vm->_globals->_saveData->_data[svField357] = 0;
2274 _vm->_globals->_exitId = _vm->_globals->_saveData->_cloneHopkins._location;
2275 break;
2276 case CHARACTER_SAMANTHA:
2277 _vm->_globals->_saveData->_data[svHopkinsCloneFl] = 0;
2278 _vm->_globals->_saveData->_data[svField354] = 0;
2279 _vm->_globals->_saveData->_data[svField356] = 1;
2280 _vm->_globals->_saveData->_data[svField357] = 0;
2281 _vm->_globals->_exitId = _vm->_globals->_saveData->_samantha._location;
2282 break;
2283 default:
2284 break;
2285 }
2286 }
2287 }
2288
2289 // Check Size
computeAndSetSpriteSize()2290 void ObjectsManager::computeAndSetSpriteSize() {
2291 int size = _vm->_globals->_spriteSize[getSpriteY(0)];
2292 if (_vm->_globals->_characterType == CHARACTER_HOPKINS_CLONE) {
2293 size = 20 * (5 * abs(size) - 100) / -80;
2294 } else if (_vm->_globals->_characterType == CHARACTER_SAMANTHA) {
2295 size = 20 * (5 * abs(size) - 165) / -67;
2296 }
2297 setSpriteZoom(0, size);
2298 }
2299
2300 /**
2301 * Get next verb icon (or text)
2302 */
nextVerbIcon()2303 void ObjectsManager::nextVerbIcon() {
2304 _vm->_events->_mouseCursorId++;
2305
2306 for(;;) {
2307 if (_vm->_events->_mouseCursorId == 4) {
2308 if (!_vm->_globals->_freezeCharacterFl || _zoneNum == -1 || _zoneNum == 0)
2309 return;
2310
2311 ++_vm->_events->_mouseCursorId;
2312 }
2313
2314 if (_vm->_events->_mouseCursorId == 5 || _vm->_events->_mouseCursorId == 6) {
2315 _vm->_events->_mouseCursorId = 6;
2316 if (_vm->_linesMan->_zone[_zoneNum]._verbFl1 == 1)
2317 return;
2318
2319 ++_vm->_events->_mouseCursorId;
2320 }
2321
2322 if (_vm->_events->_mouseCursorId == 7) {
2323 if (_vm->_linesMan->_zone[_zoneNum]._verbFl2 == 1)
2324 return;
2325
2326 ++_vm->_events->_mouseCursorId;
2327 }
2328
2329 if (_vm->_events->_mouseCursorId == 8) {
2330 if (_vm->_linesMan->_zone[_zoneNum]._verbFl3 == 1)
2331 return;
2332
2333 ++_vm->_events->_mouseCursorId;
2334 }
2335
2336 if (_vm->_events->_mouseCursorId == 9) {
2337 if (_vm->_linesMan->_zone[_zoneNum]._verbFl4 == 1)
2338 return;
2339
2340 ++_vm->_events->_mouseCursorId;
2341 }
2342
2343 if (_vm->_events->_mouseCursorId == 10) {
2344 if (_vm->_linesMan->_zone[_zoneNum]._verbFl5 == 1)
2345 return;
2346 ++_vm->_events->_mouseCursorId;
2347 }
2348
2349 if (_vm->_events->_mouseCursorId == 11) {
2350 if (_vm->_linesMan->_zone[_zoneNum]._verbFl6 == 1)
2351 return;
2352
2353 ++_vm->_events->_mouseCursorId;
2354 }
2355
2356 if (_vm->_events->_mouseCursorId == 12) {
2357 if (_vm->_linesMan->_zone[_zoneNum]._verbFl7 == 1)
2358 return;
2359
2360 ++_vm->_events->_mouseCursorId;
2361 }
2362
2363 if (_vm->_events->_mouseCursorId == 13) {
2364 if (_vm->_linesMan->_zone[_zoneNum]._verbFl8 == 1)
2365 return;
2366
2367 ++_vm->_events->_mouseCursorId;
2368 }
2369
2370 if (_vm->_events->_mouseCursorId == 14) {
2371 if (_vm->_linesMan->_zone[_zoneNum]._verbFl9 == 1)
2372 return;
2373
2374 ++_vm->_events->_mouseCursorId;
2375 }
2376
2377 if (_vm->_events->_mouseCursorId == 15) {
2378 if (_vm->_linesMan->_zone[_zoneNum]._verbFl10 == 1)
2379 return;
2380
2381 ++_vm->_events->_mouseCursorId;
2382 }
2383
2384 if (_vm->_events->_mouseCursorId == 16) {
2385 if (_vm->_linesMan->_zone[_zoneNum]._verbFl1 == 2)
2386 return;
2387
2388 ++_vm->_events->_mouseCursorId;
2389 }
2390
2391 if (_vm->_events->_mouseCursorId == 17) {
2392 if (_vm->_linesMan->_zone[_zoneNum]._verbFl4 == 2)
2393 return;
2394
2395 ++_vm->_events->_mouseCursorId;
2396 }
2397
2398 if (_vm->_events->_mouseCursorId == 18) {
2399 if (_vm->_linesMan->_zone[_zoneNum]._verbFl5 == 2)
2400 return;
2401
2402 ++_vm->_events->_mouseCursorId;
2403 }
2404
2405 if (_vm->_events->_mouseCursorId == 19) {
2406 if (_vm->_linesMan->_zone[_zoneNum]._verbFl6 == 2)
2407 return;
2408
2409 ++_vm->_events->_mouseCursorId;
2410 }
2411
2412 if (_vm->_events->_mouseCursorId == 20) {
2413 if (_vm->_linesMan->_zone[_zoneNum]._verbFl7 == 2)
2414 return;
2415
2416 ++_vm->_events->_mouseCursorId;
2417 }
2418
2419 if (_vm->_events->_mouseCursorId == 21) {
2420 if (_vm->_linesMan->_zone[_zoneNum]._verbFl10 == 2)
2421 return;
2422
2423 ++_vm->_events->_mouseCursorId;
2424 }
2425
2426 if (_vm->_events->_mouseCursorId == 22) {
2427 if (_vm->_linesMan->_zone[_zoneNum]._verbFl8 == 2)
2428 return;
2429
2430 ++_vm->_events->_mouseCursorId;
2431 }
2432
2433 if (_vm->_events->_mouseCursorId == 23) {
2434 if (_vm->_linesMan->_zone[_zoneNum]._verbFl3 == 2)
2435 return;
2436
2437 ++_vm->_events->_mouseCursorId;
2438 }
2439
2440 if (_vm->_events->_mouseCursorId == 24) {
2441 if (_vm->_linesMan->_zone[_zoneNum]._verbFl4 == 3)
2442 return;
2443
2444 ++_vm->_events->_mouseCursorId;
2445 }
2446
2447 if (_vm->_events->_mouseCursorId == 25) {
2448 if (_vm->_linesMan->_zone[_zoneNum]._verbFl9 == 2)
2449 return;
2450 }
2451 _vm->_events->_mouseCursorId = 4;
2452 }
2453 }
2454
2455 /**
2456 * Handle Right button
2457 */
handleRightButton()2458 void ObjectsManager::handleRightButton() {
2459 if (_zoneNum != -1 && _zoneNum != 0) {
2460 nextVerbIcon();
2461 if (_vm->_events->_mouseCursorId != 23)
2462 _vm->_events->changeMouseCursor(_vm->_events->_mouseCursorId);
2463 _verb = _vm->_events->_mouseCursorId;
2464 }
2465 }
2466
2467 /**
2468 * Prepare border used to highlight the place below mouse cursor, in the inventory.
2469 * Also set the mouse cursor
2470 */
initBorder(int zoneIdx)2471 void ObjectsManager::initBorder(int zoneIdx) {
2472 _oldBorderPos = _borderPos;
2473 _oldBorderSpriteIndex = _borderSpriteIndex;
2474 if (zoneIdx >= 1 && zoneIdx <= 6)
2475 _borderPos.y = 120;
2476 else if (zoneIdx >= 7 && zoneIdx <= 12)
2477 _borderPos.y = 158;
2478 else if (zoneIdx >= 13 && zoneIdx <= 18)
2479 _borderPos.y = 196;
2480 else if (zoneIdx >= 19 && zoneIdx <= 24)
2481 _borderPos.y = 234;
2482 else if (zoneIdx >= 25 && zoneIdx <= 29)
2483 _borderPos.y = 272;
2484 else if (zoneIdx == 30)
2485 _borderPos.y = 272;
2486 else if (zoneIdx == 31)
2487 _borderPos.y = 290;
2488
2489 if (zoneIdx == 1 || zoneIdx == 7 || zoneIdx == 13 || zoneIdx == 19 || zoneIdx == 25)
2490 _borderPos.x = _vm->_graphicsMan->_scrollOffset + 158;
2491 else if (zoneIdx == 2 || zoneIdx == 8 || zoneIdx == 14 || zoneIdx == 20 || zoneIdx == 26)
2492 _borderPos.x = _vm->_graphicsMan->_scrollOffset + 212;
2493 else if (zoneIdx == 3 || zoneIdx == 9 || zoneIdx == 15 || zoneIdx == 21 || zoneIdx == 27)
2494 _borderPos.x = _vm->_graphicsMan->_scrollOffset + 266;
2495 else if (zoneIdx == 4 || zoneIdx == 10 || zoneIdx == 16 || zoneIdx == 22 || zoneIdx == 28)
2496 _borderPos.x = _vm->_graphicsMan->_scrollOffset + 320;
2497 else if (zoneIdx == 5 || zoneIdx == 11 || zoneIdx == 17 || zoneIdx == 23 || zoneIdx == 29)
2498 _borderPos.x = _vm->_graphicsMan->_scrollOffset + 374;
2499 else if (zoneIdx == 6 || zoneIdx == 12 || zoneIdx == 18 || zoneIdx == 24 || zoneIdx == 30 || zoneIdx == 31)
2500 _borderPos.x = _vm->_graphicsMan->_scrollOffset + 428;
2501
2502 if (zoneIdx >= 1 && zoneIdx <= 29)
2503 _borderSpriteIndex = 0;
2504 else if (zoneIdx == 30 || zoneIdx == 31)
2505 _borderSpriteIndex = 2;
2506 else if (!zoneIdx || zoneIdx == 32) {
2507 _borderPos = Common::Point(0, 0);
2508 _borderSpriteIndex = 0;
2509 }
2510
2511 if (!zoneIdx)
2512 _vm->_events->_mouseCursorId = 0;
2513 else if (zoneIdx >= 1 && zoneIdx <= 28)
2514 _vm->_events->_mouseCursorId = 8;
2515 else if (zoneIdx == 29)
2516 _vm->_events->_mouseCursorId = 1;
2517 else if (zoneIdx == 30)
2518 _vm->_events->_mouseCursorId = 2;
2519 else if (zoneIdx == 31)
2520 _vm->_events->_mouseCursorId = 3;
2521 else if (zoneIdx == 32)
2522 _vm->_events->_mouseCursorId = 16;
2523
2524 if (zoneIdx >= 1 && zoneIdx <= 28 && !_vm->_globals->_inventory[zoneIdx]) {
2525 _vm->_events->_mouseCursorId = 0;
2526 _borderPos = Common::Point(0, 0);
2527 _borderSpriteIndex = 0;
2528 }
2529
2530 if (_vm->_events->_mouseCursorId != 23)
2531 _vm->_events->changeMouseCursor(_vm->_events->_mouseCursorId);
2532 _vm->_events->getMouseX();
2533 _vm->_events->getMouseY();
2534 }
2535
2536 /**
2537 * Get next icon for an object in the inventory
2538 */
nextObjectIcon(int idx)2539 void ObjectsManager::nextObjectIcon(int idx) {
2540 int cursorId = _vm->_events->_mouseCursorId;
2541 ObjectAuthIcon *curAuthIco = &_objectAuthIcons[_vm->_globals->_inventory[idx]];
2542
2543 if (cursorId == 0 || cursorId == 2 || cursorId == 3 || cursorId == 16)
2544 return;
2545
2546 int nextCursorId = cursorId + 1;
2547 if (nextCursorId > 25)
2548 nextCursorId = 6;
2549
2550 do {
2551 if (nextCursorId == 2 || nextCursorId == 5 || nextCursorId == 6) {
2552 _vm->_events->_mouseCursorId = 6;
2553 if (curAuthIco->_flag1 == 1)
2554 return;
2555 nextCursorId++;
2556 }
2557 if (nextCursorId == 7) {
2558 _vm->_events->_mouseCursorId = 7;
2559 if (curAuthIco->_flag2 == 1)
2560 return;
2561 nextCursorId++;
2562 }
2563 if (nextCursorId == 8) {
2564 _vm->_events->_mouseCursorId = 8;
2565 return;
2566 }
2567 if (nextCursorId == 9 || nextCursorId == 10) {
2568 _vm->_events->_mouseCursorId = 10;
2569 if (curAuthIco->_flag6 == 1)
2570 return;
2571 nextCursorId = 11;
2572 }
2573
2574 if (nextCursorId == 11) {
2575 _vm->_events->_mouseCursorId = 11;
2576 if (curAuthIco->_flag3 == 1)
2577 return;
2578 nextCursorId++;
2579 }
2580
2581 if (nextCursorId == 12 || nextCursorId == 13) {
2582 _vm->_events->_mouseCursorId = 13;
2583 if (curAuthIco->_flag4 == 1)
2584 return;
2585 nextCursorId = 14;
2586 }
2587
2588 if (nextCursorId == 14 || nextCursorId == 15) {
2589 _vm->_events->_mouseCursorId = 15;
2590 if (curAuthIco->_flag5 == 1)
2591 return;
2592 nextCursorId = 23;
2593 }
2594
2595 if (nextCursorId >= 16 && nextCursorId <= 23) {
2596 _vm->_events->_mouseCursorId = 23;
2597 if (curAuthIco->_flag5 == 2)
2598 return;
2599 nextCursorId = 24;
2600 }
2601
2602 if (nextCursorId == 24 || nextCursorId == 25) {
2603 _vm->_events->_mouseCursorId = 25;
2604 }
2605
2606 nextCursorId = 6;
2607 } while (curAuthIco->_flag6 != 2);
2608 }
2609
takeInventoryObject(int idx)2610 void ObjectsManager::takeInventoryObject(int idx) {
2611 if (_vm->_events->_mouseCursorId == 8)
2612 changeObject(idx);
2613 }
2614
loadObjectIniFile()2615 void ObjectsManager::loadObjectIniFile() {
2616 byte *data;
2617 Common::String file;
2618 int lastOpcodeResult = 1;
2619
2620 file = "OBJET1.ini";
2621 bool fileFoundFl = false;
2622 data = _vm->_fileIO->searchCat(file, RES_INI, fileFoundFl);
2623 if (!fileFoundFl) {
2624 data = _vm->_fileIO->loadFile(file);
2625 if (data == NULL)
2626 error("INI file %s not found", file.c_str());
2627 }
2628
2629 if (READ_BE_UINT24(data) != MKTAG24('I', 'N', 'I'))
2630 error("File %s is not an INI file", file.c_str());
2631
2632 for (;;) {
2633 int opcodeType = _vm->_script->handleOpcode(data + 20 * lastOpcodeResult);
2634 if (opcodeType == -1 || _vm->shouldQuit())
2635 return;
2636
2637 if (opcodeType == 2)
2638 lastOpcodeResult = _vm->_script->handleGoto(data + 20 * lastOpcodeResult);
2639 else if (opcodeType == 3)
2640 lastOpcodeResult = _vm->_script->handleIf(data, lastOpcodeResult);
2641
2642 if (lastOpcodeResult == -1)
2643 error("defective IFF function");
2644
2645 if (opcodeType == 1 || opcodeType == 4)
2646 ++lastOpcodeResult;
2647 else if (!opcodeType || opcodeType == 5)
2648 break;
2649 }
2650
2651 _vm->_globals->freeMemory(data);
2652 }
2653
handleSpecialGames()2654 void ObjectsManager::handleSpecialGames() {
2655 byte *oldPalette;
2656
2657 switch (_vm->_globals->_screenId) {
2658 case 5:
2659 if ((getSpriteY(0) > 399) || _vm->_globals->_saveData->_data[svField173])
2660 break;
2661
2662 _vm->_globals->_saveData->_data[svField173] = 1;
2663 _vm->_globals->_introSpeechOffFl = true;
2664 _vm->_talkMan->startAnimatedCharacterDialogue("flicspe1.pe2");
2665 _vm->_globals->_introSpeechOffFl = false;
2666
2667 if (_vm->_globals->_censorshipFl)
2668 break;
2669
2670 oldPalette = _vm->_globals->allocMemory(1000);
2671 memcpy(oldPalette, _vm->_graphicsMan->_palette, 769);
2672
2673 _vm->_graphicsMan->backupScreen();
2674
2675 if (!_vm->_graphicsMan->_lineNbr)
2676 _vm->_graphicsMan->_scrollOffset = 0;
2677 _vm->_graphicsMan->displayScreen(true);
2678 _vm->_soundMan->_specialSoundNum = 198;
2679 _charactersEnabledFl = true;
2680 _vm->_animMan->unsetClearAnimFlag();
2681 _vm->_animMan->playAnim("OTAGE.ANM", "OTAGE.ANM", 1, 24, 500, true);
2682 _vm->_soundMan->_specialSoundNum = 0;
2683 _vm->_graphicsMan->displayScreen(false);
2684
2685 _vm->_graphicsMan->restoreScreen();
2686
2687 _charactersEnabledFl = false;
2688 memcpy(_vm->_graphicsMan->_palette, oldPalette, 769);
2689 _vm->_graphicsMan->setPaletteVGA256(_vm->_graphicsMan->_palette);
2690 _vm->_globals->freeMemory(oldPalette);
2691 _vm->_graphicsMan->display8BitRect(_vm->_graphicsMan->_backBuffer, _vm->_events->_startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0);
2692 memcpy(_vm->_graphicsMan->_frontBuffer, _vm->_graphicsMan->_backBuffer, 614399);
2693
2694 _vm->_graphicsMan->_scrollStatus = 0;
2695 _vm->_graphicsMan->updateScreen();
2696 break;
2697 case 20:
2698 _vm->_globals->_saveData->_data[svField132] = (getSpriteX(0) > 65 && getSpriteX(0) <= 124 && getSpriteY(0) > 372 && getSpriteY(0) <= 398) ? 1 : 0;
2699 break;
2700 case 35:
2701 if (_vm->_globals->_prevScreenId == 16)
2702 handleForest(35, 500, 555, 100, 440, 1);
2703 else if (_vm->_globals->_prevScreenId == 36)
2704 handleForest(35, 6, 84, 100, 440, 4);
2705 break;
2706 case 36:
2707 if (_vm->_globals->_prevScreenId == 35)
2708 handleForest(36, 551, 633, 100, 440, 2);
2709 else if (_vm->_globals->_prevScreenId == 37)
2710 handleForest(36, 6, 84, 100, 440, 4);
2711 break;
2712 case 37:
2713 if (_vm->_globals->_prevScreenId == 36)
2714 handleForest(37, 551, 633, 100, 440, 1);
2715 else if (_vm->_globals->_prevScreenId == 38)
2716 handleForest(37, 392, 529, 100, 440, 2);
2717 break;
2718 case 38:
2719 if (_vm->_globals->_prevScreenId == 37)
2720 handleForest(38, 133, 252, 100, 440, 4);
2721 else if (_vm->_globals->_prevScreenId == 39)
2722 handleForest(38, 6, 84, 100, 440, 3);
2723 break;
2724 case 39:
2725 if (_vm->_globals->_prevScreenId == 38)
2726 handleForest(39, 551, 633, 100, 440, 2);
2727 else if (_vm->_globals->_prevScreenId == 40)
2728 handleForest(39, 6, 84, 100, 440, 3);
2729 break;
2730 case 40:
2731 if (_vm->_globals->_prevScreenId == 39)
2732 handleForest(40, 133, 252, 100, 440, 4);
2733 else if (_vm->_globals->_prevScreenId == 41)
2734 handleForest(40, 392, 529, 100, 440, 2);
2735 break;
2736 case 41:
2737 if (_vm->_globals->_prevScreenId == 40)
2738 handleForest(41, 551, 633, 100, 440, 1);
2739 else if (_vm->_globals->_prevScreenId == 17)
2740 handleForest(41, 6, 84, 100, 440, 3);
2741 break;
2742 case 57:
2743 _vm->_globals->_disableInventFl = true;
2744 if (_vm->_globals->_saveData->_data[svField261] == 1 && getBobAnimDataIdx(5) == 37) {
2745 stopBobAnimation(5);
2746 setBobAnimDataIdx(5, 0);
2747 setBobAnimation(6);
2748 _vm->_globals->_saveData->_data[svField261] = 2;
2749 _vm->_linesMan->disableZone(15);
2750 _vm->_soundMan->playSoundFile("SOUND75.WAV");
2751 }
2752 if (_vm->_globals->_saveData->_data[svField261] == 2 && getBobAnimDataIdx(6) == 6) {
2753 stopBobAnimation(6);
2754 setBobAnimDataIdx(6, 0);
2755 setBobAnimation(7);
2756 _vm->_linesMan->enableZone(14);
2757 _vm->_globals->_saveData->_data[svField261] = 3;
2758 }
2759 _vm->_globals->_disableInventFl = false;
2760 break;
2761 case 93:
2762 if (_vm->_globals->_saveData->_data[svField333])
2763 break;
2764
2765 _vm->_globals->_disableInventFl = true;
2766 do {
2767 _vm->_events->refreshScreenAndEvents();
2768 } while (getBobAnimDataIdx(8) != 3);
2769 _vm->_globals->_introSpeechOffFl = true;
2770 _vm->_talkMan->startAnimatedCharacterDialogue("GM3.PE2");
2771 stopBobAnimation(8);
2772 _vm->_globals->_saveData->_data[svField333] = 1;
2773 _vm->_globals->_disableInventFl = false;
2774 break;
2775 default:
2776 break;
2777 }
2778 }
2779
quickDisplayBobSprite(int idx)2780 void ObjectsManager::quickDisplayBobSprite(int idx) {
2781 int startPos = 10 * idx;
2782 if (!READ_LE_UINT16(_vm->_talkMan->_characterAnim + startPos + 4))
2783 return;
2784
2785 int xp = READ_LE_INT16(_vm->_talkMan->_characterAnim + startPos);
2786 int yp = READ_LE_INT16(_vm->_talkMan->_characterAnim + startPos + 2);
2787 int spriteIndex = _vm->_talkMan->_characterAnim[startPos + 8];
2788
2789 _vm->_graphicsMan->fastDisplay(_vm->_talkMan->_characterSprite, xp, yp, spriteIndex);
2790 }
2791
initVbob(const byte * src,int idx,int xp,int yp,int frameIndex)2792 void ObjectsManager::initVbob(const byte *src, int idx, int xp, int yp, int frameIndex) {
2793 if (idx > 29)
2794 error("MAX_VBOB exceeded");
2795
2796 VBobItem *vbob = &_vBob[idx];
2797 if (vbob->_displayMode <= 1) {
2798 vbob->_displayMode = 1;
2799 vbob->_xp = xp;
2800 vbob->_yp = yp;
2801 vbob->_frameIndex = frameIndex;
2802 vbob->_oldX = xp;
2803 vbob->_oldY = yp;
2804 vbob->_oldFrameIndex = frameIndex;
2805 vbob->_spriteData = src;
2806 vbob->_oldSpriteData = src;
2807 vbob->_surface = _vm->_globals->freeMemory(vbob->_surface);
2808 } else if (vbob->_displayMode == 2 || vbob->_displayMode == 4) {
2809 vbob->_displayMode = 3;
2810 vbob->_oldX = vbob->_xp;
2811 vbob->_oldY = vbob->_yp;
2812 vbob->_oldSpriteData = vbob->_spriteData;
2813 vbob->_oldFrameIndex = vbob->_frameIndex;
2814 vbob->_xp = xp;
2815 vbob->_yp = yp;
2816 vbob->_frameIndex = frameIndex;
2817 vbob->_spriteData = src;
2818 }
2819 }
2820
disableVbob(int idx)2821 void ObjectsManager::disableVbob(int idx) {
2822 if (idx > 29)
2823 error("MAX_VBOB exceeded");
2824
2825 VBobItem *vbob = &_vBob[idx];
2826 if (vbob->_displayMode <= 1)
2827 vbob->_displayMode = 0;
2828 else
2829 vbob->_displayMode = 4;
2830 }
2831
doActionBack(int idx)2832 void ObjectsManager::doActionBack(int idx) {
2833 if (_curGestureFile != 1) {
2834 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
2835 _curGestureFile = 1;
2836 _gestureBuf = _vm->_fileIO->loadFile("DOS.SPR");
2837 }
2838
2839 switch (idx) {
2840 case 1:
2841 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 8, false);
2842 break;
2843 case 2:
2844 showSpecialActionAnimationWithFlip(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,13,-1,", 8, false);
2845 break;
2846 case 3:
2847 showSpecialActionAnimation(_gestureBuf, "12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8);
2848 break;
2849 case 4:
2850 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,8,9,10,11,12,13,12,11,12,13,12,11,12,13,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8, false);
2851 break;
2852 case 5:
2853 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,21,-1,", 8, false);
2854 break;
2855 case 6:
2856 showSpecialActionAnimation(_gestureBuf, "20,19,18,17,16,15,-1,", 8);
2857 break;
2858 case 7:
2859 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,21,22,23,24,-1,", 8, false);
2860 break;
2861 case 8:
2862 showSpecialActionAnimation(_gestureBuf, "23,22,21,20,19,18,17,16,15,-1,", 8);
2863 break;
2864 case 9:
2865 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,21,22,23,24,-1,", 8, false);
2866 break;
2867 case 10:
2868 showSpecialActionAnimation(_gestureBuf, "23,22,21,20,19,18,17,16,15,-1,", 8);
2869 break;
2870 default:
2871 break;
2872 }
2873 }
2874
doActionRight(int idx)2875 void ObjectsManager::doActionRight(int idx) {
2876 if (_curGestureFile != 3) {
2877 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
2878 _curGestureFile = 3;
2879 _gestureBuf = _vm->_fileIO->loadFile("PROFIL.SPR");
2880 }
2881
2882 switch (idx) {
2883 case 1:
2884 showActionAnimation(_gestureBuf, "20,19,18,17,16,15,14,13,13,13,13,13,14,15,16,17,18,19,20,-1,", 8, false);
2885 break;
2886 case 2:
2887 showSpecialActionAnimationWithFlip(_gestureBuf, "1,2,3,4,5,6,7,8,-1,", 8, false);
2888 break;
2889 case 3:
2890 showSpecialActionAnimation(_gestureBuf, "9,10,11,12,13,14,15,16,17,18,19,20,-1,", 8);
2891 break;
2892 case 4:
2893 showActionAnimation(_gestureBuf, "1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,-1,", 8, false);
2894 break;
2895 case 5:
2896 showSpecialActionAnimationWithFlip(_gestureBuf, "23,24,25,-1,", 8, false);
2897 break;
2898 case 6:
2899 showSpecialActionAnimation(_gestureBuf, "24,23,-1,", 8);
2900 break;
2901 case 7:
2902 showSpecialActionAnimationWithFlip(_gestureBuf, "23,24,25,26,27,-1,", 8, false);
2903 break;
2904 case 8:
2905 showSpecialActionAnimation(_gestureBuf, "26,25,24,23,-1,", 8);
2906 break;
2907 case 9:
2908 showSpecialActionAnimationWithFlip(_gestureBuf, "23,24,25,26,27,28,29,-1,", 8, false);
2909 break;
2910 case 10:
2911 showSpecialActionAnimation(_gestureBuf, "28,27,26,25,24,23,-1,", 8);
2912 break;
2913 default:
2914 break;
2915 }
2916 }
2917
doActionDiagRight(int idx)2918 void ObjectsManager::doActionDiagRight(int idx) {
2919 if (_curGestureFile != 4) {
2920 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
2921 _curGestureFile = 4;
2922 _gestureBuf = _vm->_fileIO->loadFile("3Q.SPR");
2923 }
2924
2925 switch (idx) {
2926 case 1:
2927 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 8, false);
2928 break;
2929 case 2:
2930 showSpecialActionAnimationWithFlip(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,-1,", 8, false);
2931 break;
2932 case 3:
2933 showSpecialActionAnimation(_gestureBuf, "11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8);
2934 break;
2935 case 4:
2936 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,11,12,11,12,11,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8, false);
2937 break;
2938 case 5:
2939 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,-1,", 8, false);
2940 break;
2941 case 6:
2942 showSpecialActionAnimation(_gestureBuf, "17,16,15,-1,", 8);
2943 break;
2944 case 7:
2945 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,-1,", 8, false);
2946 break;
2947 case 8:
2948 showSpecialActionAnimation(_gestureBuf, "19,18,17,16,15,-1,", 8);
2949 break;
2950 case 9:
2951 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,21,-1,", 8, false);
2952 break;
2953 case 10:
2954 showSpecialActionAnimation(_gestureBuf, "20,19,18,17,15,-1,", 8);
2955 break;
2956 default:
2957 break;
2958 }
2959 }
2960
doActionFront(int idx)2961 void ObjectsManager::doActionFront(int idx) {
2962 if (_curGestureFile != 2) {
2963 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
2964 _curGestureFile = 2;
2965 _gestureBuf = _vm->_fileIO->loadFile("FACE.SPR");
2966 }
2967
2968 switch (idx) {
2969 case 1:
2970 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,9,9,9,9,9,9,7,6,5,4,3,2,1,0,-1,", 8, false);
2971 break;
2972 case 2:
2973 showSpecialActionAnimationWithFlip(_gestureBuf, "0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,-1,", 8, false);
2974 break;
2975 case 3:
2976 showSpecialActionAnimation(_gestureBuf, "14,13,12,11,10,9,7,6,5,4,3,2,1,0,-1,", 8);
2977 break;
2978 case 4:
2979 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,9,10,11,12,13,14,13,12,11,10,9,7,6,5,4,3,2,1,0,-1,", 8, false);
2980 break;
2981 default:
2982 break;
2983 }
2984 }
2985
doActionDiagLeft(int idx)2986 void ObjectsManager::doActionDiagLeft(int idx) {
2987 if (_curGestureFile != 4) {
2988 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
2989 _curGestureFile = 4;
2990 _gestureBuf = _vm->_fileIO->loadFile("3Q.SPR");
2991 }
2992
2993 switch (idx) {
2994 case 1:
2995 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 8, true);
2996 break;
2997 case 2:
2998 showSpecialActionAnimationWithFlip(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,-1,", 8, true);
2999 break;
3000 case 3:
3001 showSpecialActionAnimation(_gestureBuf, "11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8);
3002 break;
3003 case 4:
3004 showActionAnimation(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,11,12,11,12,11,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8, true);
3005 break;
3006 case 5:
3007 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,-1,", 8, true);
3008 break;
3009 case 6:
3010 showSpecialActionAnimation(_gestureBuf, "17,16,15,-1,", 8);
3011 break;
3012 case 7:
3013 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,-1,", 8, true);
3014 break;
3015 case 8:
3016 showSpecialActionAnimation(_gestureBuf, "19,18,17,16,15,-1,", 8);
3017 break;
3018 case 9:
3019 showSpecialActionAnimationWithFlip(_gestureBuf, "15,16,17,18,19,20,21,-1,", 8, true);
3020 break;
3021 case 10:
3022 showSpecialActionAnimation(_gestureBuf, "20,19,18,17,15,-1,", 8);
3023 break;
3024 default:
3025 break;
3026 }
3027 }
3028
doActionLeft(int idx)3029 void ObjectsManager::doActionLeft(int idx) {
3030 if (_curGestureFile != 3) {
3031 _gestureBuf = _vm->_globals->freeMemory(_gestureBuf);
3032 _curGestureFile = 3;
3033 _gestureBuf = _vm->_fileIO->loadFile("PROFIL.SPR");
3034 }
3035
3036 switch (idx) {
3037 case 1:
3038 showActionAnimation(_gestureBuf, "20,19,18,17,16,15,14,13,13,13,13,13,14,15,16,17,18,19,20,-1,", 8, true);
3039 break;
3040 case 2:
3041 showSpecialActionAnimationWithFlip(_gestureBuf, "1,2,3,4,5,6,7,8,-1,", 8, true);
3042 break;
3043 case 3:
3044 showSpecialActionAnimation(_gestureBuf, "9,10,11,12,13,14,15,16,17,18,19,20,-1,", 8);
3045 break;
3046 case 4:
3047 showActionAnimation(_gestureBuf, "1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,-1,", 8, true);
3048 break;
3049 case 5:
3050 showSpecialActionAnimationWithFlip(_gestureBuf, "23,24,25,-1,", 8, true);
3051 break;
3052 case 6:
3053 showSpecialActionAnimation(_gestureBuf, "24,23,-1,", 8);
3054 break;
3055 case 7:
3056 showSpecialActionAnimationWithFlip(_gestureBuf, "23,24,25,26,27,-1,", 8, true);
3057 break;
3058 case 8:
3059 showSpecialActionAnimation(_gestureBuf, "26,25,24,23,-1,", 8);
3060 break;
3061 case 9:
3062 showSpecialActionAnimationWithFlip(_gestureBuf, "23,24,25,26,27,28,29,-1,", 8, true);
3063 break;
3064 case 10:
3065 showSpecialActionAnimation(_gestureBuf, "28,27,26,25,24,23,-1,", 8);
3066 break;
3067 default:
3068 break;
3069 }
3070 }
3071
setAndPlayAnim(int idx,int animIdx,int destPosi,bool animAction)3072 void ObjectsManager::setAndPlayAnim(int idx, int animIdx, int destPosi, bool animAction) {
3073 // Set Hopkins animation and position
3074 setBobAnimation(idx);
3075 setBobAnimDataIdx(idx, animIdx);
3076
3077 // Make Hopkins walk to the expected place
3078 do {
3079 _vm->_events->refreshScreenAndEvents();
3080 } while (destPosi != getBobAnimDataIdx(idx));
3081
3082 if (!animAction)
3083 stopBobAnimation(idx);
3084 else {
3085 BobItem *bob = &_bob[idx];
3086 _vm->_graphicsMan->fastDisplay(bob->_spriteData, bob->_oldX, bob->_oldY, bob->_frameIndex);
3087 stopBobAnimation(idx);
3088 _vm->_events->refreshScreenAndEvents();
3089 }
3090 }
3091
getBobAnimDataIdx(int idx)3092 int ObjectsManager::getBobAnimDataIdx(int idx) {
3093 return _bob[idx]._animDataIdx / 5;
3094 }
3095
setBobAnimDataIdx(int idx,int animIdx)3096 void ObjectsManager::setBobAnimDataIdx(int idx, int animIdx) {
3097 BobItem *bob = &_bob[idx];
3098 bob->_animDataIdx = 5 * animIdx;
3099 bob->_moveChange1 = 0;
3100 bob->_moveChange2 = 0;
3101 }
3102
3103 /**
3104 * Set Hopkins animation
3105 */
setBobAnimation(int idx)3106 void ObjectsManager::setBobAnimation(int idx) {
3107 assert(idx < 36);
3108 BobItem *bob = &_bob[idx];
3109 if (!bob->_disabledAnimationFl)
3110 return;
3111
3112 bob->_disabledAnimationFl = false;
3113 bob->_animDataIdx = 5;
3114 bob->_frameIndex = 250;
3115 bob->_moveChange1 = 0;
3116 bob->_moveChange2 = 0;
3117 }
3118
3119 /**
3120 * Stop Hopkins animation
3121 */
stopBobAnimation(int idx)3122 void ObjectsManager::stopBobAnimation(int idx) {
3123 assert(idx < 36);
3124 _bob[idx]._disabledAnimationFl = true;
3125 }
3126
3127 /**
3128 * Get X position
3129 */
getBobPosX(int idx)3130 int ObjectsManager::getBobPosX(int idx) {
3131 return _bob[idx]._xp;
3132 }
3133
loadLinkFile(const Common::String & file,bool skipDetails)3134 void ObjectsManager::loadLinkFile(const Common::String &file, bool skipDetails) {
3135 Common::File f;
3136 Common::String filename = file + ".LNK";
3137 bool fileFoundFl = false;
3138 byte *ptr = _vm->_fileIO->searchCat(filename, RES_LIN, fileFoundFl);
3139 size_t nbytes = _vm->_fileIO->_catalogSize;
3140 if (!fileFoundFl) {
3141 if (!f.open(filename))
3142 error("Error opening file - %s", filename.c_str());
3143
3144 nbytes = f.size();
3145 ptr = _vm->_globals->allocMemory(nbytes);
3146 if (ptr == NULL)
3147 error("INILINK");
3148 _vm->_fileIO->readStream(f, ptr, nbytes);
3149 f.close();
3150 }
3151 if (!skipDetails) {
3152 for (int idx = 0; idx < 500; ++idx)
3153 _vm->_globals->_spriteSize[idx] = READ_LE_INT16((uint16 *)ptr + idx);
3154
3155 resetHidingItems();
3156
3157 Common::String filename2 = Common::String((const char *)ptr + 1000);
3158 if (!filename2.empty()) {
3159 fileFoundFl = false;
3160 _hidingItemData[1] = _vm->_fileIO->searchCat(filename2, RES_SLI, fileFoundFl);
3161
3162 if (!fileFoundFl) {
3163 _hidingItemData[1] = _vm->_fileIO->loadFile(filename2);
3164 } else {
3165 _hidingItemData[1] = _vm->_fileIO->loadFile("RES_SLI.RES");
3166 }
3167
3168 int curDataCacheId = 60;
3169 byte *curDataPtr = ptr + 1000;
3170 for (int hidingIdx = 0; hidingIdx <= 21; hidingIdx++) {
3171 HidingItem *hid = &_hidingItem[hidingIdx];
3172 int curSpriteId = READ_LE_INT16(curDataPtr + 2 * curDataCacheId);
3173 hid->_spriteIndex = curSpriteId;
3174 hid->_x = READ_LE_INT16(curDataPtr + 2 * curDataCacheId + 2);
3175 hid->_y = READ_LE_INT16(curDataPtr + 2 * curDataCacheId + 4);
3176 hid->_yOffset = READ_LE_INT16(curDataPtr + 2 * curDataCacheId + 8);
3177
3178 if (!_hidingItemData[1]) {
3179 hid->_useCount = 0;
3180 } else {
3181 hid->_spriteData = _hidingItemData[1];
3182 hid->_width = getWidth(_hidingItemData[1], curSpriteId);
3183 hid->_height = getHeight(_hidingItemData[1], curSpriteId);
3184 hid->_useCount = 1;
3185 }
3186 if (!hid->_x && !hid->_y && !hid->_spriteIndex)
3187 hid->_useCount = 0;
3188
3189 curDataCacheId += 5;
3190 }
3191 enableHidingBehavior();
3192 }
3193 }
3194
3195 _vm->_linesMan->resetLines();
3196 for (size_t idx = 0; idx < nbytes - 3; idx++) {
3197 if (READ_BE_UINT24(&ptr[idx]) == MKTAG24('O', 'B', '2')) {
3198 byte *curDataPtr = &ptr[idx + 4];
3199 int lineDataIdx = 0;
3200 int curLineIdx = 0;
3201 _vm->_linesMan->resetLinesNumb();
3202 Directions curDirection;
3203 do {
3204 curDirection = (Directions)READ_LE_INT16(curDataPtr + 2 * lineDataIdx);
3205 if (curDirection != DIR_NONE) {
3206 _vm->_linesMan->addLine(
3207 curLineIdx,
3208 curDirection,
3209 READ_LE_INT16(curDataPtr + 2 * lineDataIdx + 2),
3210 READ_LE_INT16(curDataPtr + 2 * lineDataIdx + 4),
3211 READ_LE_INT16(curDataPtr + 2 * lineDataIdx + 6),
3212 READ_LE_INT16(curDataPtr + 2 * lineDataIdx + 8));
3213 }
3214 lineDataIdx += 5;
3215 ++curLineIdx;
3216 } while (curDirection != DIR_NONE);
3217 _vm->_linesMan->initRoute();
3218 }
3219 }
3220
3221 if (!skipDetails) {
3222 for (size_t idx = 0; idx < nbytes - 3; idx++) {
3223 if (READ_BE_UINT24(&ptr[idx]) == MKTAG24('Z', 'O', '2')) {
3224 byte *curDataPtr = &ptr[idx + 4];
3225 int curDataIdx = 0;
3226 for (int i = 1; i <= 100; i++) {
3227 ZoneItem *curZone = &_vm->_linesMan->_zone[i];
3228 curZone->_destX = 0;
3229 curZone->_destY = 0;
3230 curZone->_spriteIndex = 0;
3231 curZone->_verbFl1 = 0;
3232 curZone->_verbFl2 = 0;
3233 curZone->_verbFl3 = 0;
3234 curZone->_verbFl4 = 0;
3235 curZone->_verbFl5 = 0;
3236 curZone->_verbFl6 = 0;
3237 curZone->_verbFl7 = 0;
3238 curZone->_verbFl8 = 0;
3239 curZone->_verbFl9 = 0;
3240 curZone->_verbFl10 = 0;
3241 curZone->_messageId = 0;
3242 }
3243
3244 int curLineIdx = 0;
3245 for (;;) {
3246 int bobZoneId = READ_LE_INT16(curDataPtr + 2 * curDataIdx);
3247 if (bobZoneId != -1) {
3248 _vm->_linesMan->addZoneLine(
3249 curLineIdx,
3250 READ_LE_INT16(curDataPtr + 2 * curDataIdx + 2),
3251 READ_LE_INT16(curDataPtr + 2 * curDataIdx + 4),
3252 READ_LE_INT16(curDataPtr + 2 * curDataIdx + 6),
3253 READ_LE_INT16(curDataPtr + 2 * curDataIdx + 8),
3254 bobZoneId);
3255 _vm->_linesMan->_zone[bobZoneId]._enabledFl = true;
3256 }
3257 curDataIdx += 5;
3258 ++curLineIdx;
3259 if (bobZoneId == -1)
3260 break;
3261 }
3262 for (int i = 1; i <= 100; i++) {
3263 ZoneItem *curZone = &_vm->_linesMan->_zone[i];
3264 curZone->_destX = READ_LE_INT16(curDataPtr + 2 * curDataIdx);
3265 curZone->_destY = READ_LE_INT16(curDataPtr + 2 * curDataIdx + 2);
3266 curZone->_spriteIndex = READ_LE_INT16(curDataPtr + 2 * curDataIdx + 4);
3267 curDataIdx += 3;
3268 }
3269
3270 byte *verbData = ptr + idx + (10 * curLineIdx + 606) + 4;
3271 for (int i = 1; i <= 100; i++) {
3272 int j = (i - 1) * 10;
3273 ZoneItem *curZone = &_vm->_linesMan->_zone[i];
3274 curZone->_verbFl1 = verbData[j];
3275 curZone->_verbFl2 = verbData[j + 1];
3276 curZone->_verbFl3 = verbData[j + 2];
3277 curZone->_verbFl4 = verbData[j + 3];
3278 curZone->_verbFl5 = verbData[j + 4];
3279 curZone->_verbFl6 = verbData[j + 5];
3280 curZone->_verbFl7 = verbData[j + 6];
3281 curZone->_verbFl8 = verbData[j + 7];
3282 curZone->_verbFl9 = verbData[j + 8];
3283 curZone->_verbFl10 = verbData[j + 9];
3284 }
3285 int dep = 1010;
3286 for (int i = 1; i <= 100; i++) {
3287 _vm->_linesMan->_zone[i]._messageId = READ_LE_INT16(verbData + dep);
3288 dep += 2;
3289 }
3290 _vm->_linesMan->initSquareZones();
3291 }
3292 }
3293 }
3294 _vm->_globals->freeMemory(ptr);
3295 }
3296
sceneSpecialIni()3297 void ObjectsManager::sceneSpecialIni() {
3298 switch (_vm->_globals->_screenId) {
3299 case 17:
3300 if (_vm->_globals->_prevScreenId == 20) {
3301 _vm->_globals->_disableInventFl = true;
3302 _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
3303 _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
3304 _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
3305 _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
3306 for (int i = 0; i <= 4; i++)
3307 _vm->_events->refreshScreenAndEvents();
3308 _vm->_graphicsMan->fadeInLong();
3309 animateSprite(0);
3310 for (int i = 0; i <= 4; i++)
3311 _vm->_events->refreshScreenAndEvents();
3312 initVbob(_vm->_globals->_levelSpriteBuf, 5, 15, 28, 1);
3313 _vm->_fontMan->hideText(9);
3314 bool displayedTxtFl = false;
3315 if (!_vm->_soundMan->_textOffFl) {
3316 _vm->_fontMan->initTextBuffers(9, 383, _vm->_globals->_textFilename, 220, 72, 6, 36, 253);
3317 _vm->_fontMan->showText(9);
3318 displayedTxtFl = true;
3319 }
3320 if (!_vm->_soundMan->_voiceOffFl)
3321 _vm->_soundMan->mixVoice(383, 4, displayedTxtFl);
3322 _vm->_globals->_saveData->_data[svField270] = 1;
3323 _vm->_globals->_saveData->_data[svField300] = 1;
3324 _vm->_globals->_saveData->_data[svField320] = 1;
3325 if (_vm->_soundMan->_voiceOffFl) {
3326 for (int i = 0; i <= 199; i++)
3327 _vm->_events->refreshScreenAndEvents();
3328 }
3329 _vm->_fontMan->hideText(9);
3330 disableVbob(5);
3331 for (int i = 0; i <= 3; i++)
3332 _vm->_events->refreshScreenAndEvents();
3333 _vm->_graphicsMan->_noFadingFl = true;
3334 _vm->_globals->_disableInventFl = false;
3335 }
3336 break;
3337
3338 case 18:
3339 if (_vm->_globals->_prevScreenId == 17) {
3340 _vm->_events->_mouseSpriteId = 4;
3341 for (int i = 0; i <= 4; i++)
3342 _vm->_events->refreshScreenAndEvents();
3343 _vm->_graphicsMan->fadeInLong();
3344 _vm->_globals->_eventMode = EVENTMODE_IGNORE;
3345 _vm->_globals->_disableInventFl = false;
3346 _vm->_graphicsMan->_noFadingFl = true;
3347 _vm->_globals->_introSpeechOffFl = true;
3348 _vm->_talkMan->startAnimatedCharacterDialogue("MAGE1.pe2");
3349 _vm->_graphicsMan->_noFadingFl = true;
3350 _vm->_globals->_disableInventFl = false;
3351 }
3352 break;
3353
3354 case 35:
3355 case 36:
3356 case 37:
3357 case 38:
3358 case 39:
3359 case 40:
3360 case 41:
3361 _vm->_linesMan->_bobZone[20] = 1;
3362 _vm->_linesMan->_bobZone[21] = 2;
3363 _vm->_linesMan->_bobZone[22] = 3;
3364 _vm->_linesMan->_bobZone[23] = 4;
3365 _vm->_linesMan->_bobZoneFl[20] = true;
3366 _vm->_linesMan->_bobZoneFl[21] = true;
3367 _vm->_linesMan->_bobZoneFl[22] = true;
3368 _vm->_linesMan->_bobZoneFl[23] = true;
3369 enableVerb(20, 5);
3370 enableVerb(21, 5);
3371 enableVerb(22, 5);
3372 enableVerb(23, 5);
3373 _vm->_linesMan->_zone[20]._messageId = 30;
3374 _vm->_linesMan->_zone[21]._messageId = 30;
3375 _vm->_linesMan->_zone[22]._messageId = 30;
3376 _vm->_linesMan->_zone[23]._messageId = 30;
3377 for (int i = svField200; i <= svField214; i++) {
3378 if (_vm->_globals->_saveData->_data[i] != 2)
3379 _vm->_globals->_saveData->_data[i] = 0;
3380 }
3381 break;
3382
3383 case 73:
3384 if (!_vm->_globals->_saveData->_data[svSecondElevatorAvailableFl]) {
3385 resetHidingUseCount(0);
3386 resetHidingUseCount(1);
3387 }
3388 break;
3389
3390 case 93:
3391 if (!_vm->_globals->_saveData->_data[svField333])
3392 setBobAnimation(8);
3393 break;
3394
3395 default:
3396 break;
3397 }
3398 }
3399
setMultiBobAnim(int idx1,int idx2,int anim1Idx,int anim2Idx)3400 void ObjectsManager::setMultiBobAnim(int idx1, int idx2, int anim1Idx, int anim2Idx) {
3401 if (idx1 != -1)
3402 setBobAnimation(idx1);
3403 if (idx2 != -1)
3404 setBobAnimation(idx2);
3405 if (idx1 != -1)
3406 setBobAnimDataIdx(idx1, anim1Idx);
3407 if (idx2 != -1)
3408 setBobAnimDataIdx(idx2, anim2Idx);
3409 }
3410
checkEventBobAnim(int idx,int animIdx,int animDataIdx,int a4)3411 void ObjectsManager::checkEventBobAnim(int idx, int animIdx, int animDataIdx, int a4) {
3412 _vm->_events->_curMouseButton = 0;
3413 _vm->_events->_mouseButton = 0;
3414
3415 if (a4 != 3) {
3416 setBobAnimation(idx);
3417 setBobAnimDataIdx(idx, animIdx);
3418 }
3419
3420 do {
3421 _vm->_events->refreshScreenAndEvents();
3422 if (_vm->_events->_curMouseButton)
3423 break;
3424 } while (animDataIdx != getBobAnimDataIdx(idx));
3425 if (!a4)
3426 stopBobAnimation(idx);
3427 }
3428
disableVerb(int idx,int a2)3429 void ObjectsManager::disableVerb(int idx, int a2) {
3430 ZoneItem *curZone = &_vm->_linesMan->_zone[idx];
3431 switch (a2) {
3432 case 6:
3433 case 16:
3434 curZone->_verbFl1 = 0;
3435 break;
3436 case 7:
3437 curZone->_verbFl2 = 0;
3438 break;
3439 case 5:
3440 case 8:
3441 curZone->_verbFl3 = 0;
3442 break;
3443 case 9:
3444 case 17:
3445 case 24:
3446 curZone->_verbFl4 = 0;
3447 break;
3448 case 10:
3449 case 18:
3450 curZone->_verbFl5 = 0;
3451 break;
3452 case 11:
3453 case 19:
3454 curZone->_verbFl6 = 0;
3455 break;
3456 case 12:
3457 case 20:
3458 curZone->_verbFl7 = 0;
3459 break;
3460 case 13:
3461 case 22:
3462 curZone->_verbFl8 = 0;
3463 break;
3464 case 14:
3465 case 21:
3466 case 25:
3467 curZone->_verbFl9 = 0;
3468 break;
3469 case 15:
3470 curZone->_verbFl10 = 0;
3471 break;
3472 default:
3473 break;
3474 }
3475 _changeVerbFl = true;
3476 }
3477
enableVerb(int idx,int a2)3478 void ObjectsManager::enableVerb(int idx, int a2) {
3479 ZoneItem *curZone = &_vm->_linesMan->_zone[idx];
3480
3481 switch (a2) {
3482 case 5:
3483 curZone->_verbFl3 = 2;
3484 break;
3485 case 6:
3486 curZone->_verbFl1 = 1;
3487 break;
3488 case 7:
3489 curZone->_verbFl2 = 1;
3490 break;
3491 case 8:
3492 curZone->_verbFl3 = 1;
3493 break;
3494 case 9:
3495 curZone->_verbFl4 = 1;
3496 break;
3497 case 10:
3498 curZone->_verbFl5 = 1;
3499 break;
3500 case 11:
3501 curZone->_verbFl6 = 1;
3502 break;
3503 case 12:
3504 curZone->_verbFl7 = 1;
3505 break;
3506 case 13:
3507 curZone->_verbFl8 = 1;
3508 break;
3509 case 14:
3510 curZone->_verbFl8 = 1;
3511 break;
3512 case 15:
3513 curZone->_verbFl9 = 1;
3514 break;
3515 case 16:
3516 curZone->_verbFl1 = 2;
3517 break;
3518 case 17:
3519 curZone->_verbFl4 = 2;
3520 break;
3521 case 18:
3522 curZone->_verbFl5 = 2;
3523 break;
3524 case 19:
3525 curZone->_verbFl6 = 2;
3526 break;
3527 case 20:
3528 curZone->_verbFl7 = 2;
3529 break;
3530 case 21:
3531 curZone->_verbFl9 = 2;
3532 break;
3533 case 22:
3534 curZone->_verbFl8 = 2;
3535 break;
3536 case 24:
3537 curZone->_verbFl4 = 3;
3538 break;
3539 case 25:
3540 curZone->_verbFl9 = 2;
3541 break;
3542 default:
3543 break;
3544 }
3545 }
3546
showActionAnimation(const byte * spriteData,const Common::String & actionStr,int speed,bool flipFl)3547 void ObjectsManager::showActionAnimation(const byte *spriteData, const Common::String &actionStr, int speed, bool flipFl) {
3548 Common::String tmpStr = "";
3549 int realSpeed = speed;
3550 if (_vm->_globals->_speed == 2)
3551 realSpeed = speed / 2;
3552 else if (_vm->_globals->_speed == 3)
3553 realSpeed = speed / 3;
3554 const byte *oldSpriteData = _sprite[0]._spriteData;
3555 int spriteIndex = _sprite[0]._spriteIndex;
3556 bool oldFlipFl = _sprite[0]._flipFl;
3557 _sprite[0]._flipFl = flipFl;
3558
3559 int idx = 0;
3560 for (int strPos = 0; ; strPos++) {
3561 bool tokenCompleteFl = false;
3562 char curChar = actionStr[strPos];
3563 if (curChar == ',') {
3564 idx = atoi(tmpStr.c_str());
3565 tmpStr = "";
3566 tokenCompleteFl = true;
3567 } else {
3568 tmpStr += curChar;
3569 }
3570
3571 if (tokenCompleteFl) {
3572 if (idx == -1) {
3573 _sprite[0]._spriteData = oldSpriteData;
3574 _sprite[0]._spriteIndex = spriteIndex;
3575 _sprite[0]._flipFl = oldFlipFl;
3576 } else {
3577 _sprite[0]._spriteData = spriteData;
3578 _sprite[0]._spriteIndex = idx;
3579 }
3580 for (int i = 0; i < realSpeed; i++)
3581 _vm->_events->refreshScreenAndEvents();
3582 if (idx == -1)
3583 break;
3584 }
3585 }
3586 }
3587
showSpecialActionAnimationWithFlip(const byte * spriteData,const Common::String & animationSeq,int speed,bool flipFl)3588 void ObjectsManager::showSpecialActionAnimationWithFlip(const byte *spriteData, const Common::String &animationSeq, int speed, bool flipFl) {
3589 Common::String tmpStr = "";
3590
3591 int realSpeed = speed;
3592 if (_vm->_globals->_speed == 2)
3593 realSpeed = speed / 2;
3594 else if (_vm->_globals->_speed == 3)
3595 realSpeed = speed / 3;
3596
3597 _oldSpriteData = _sprite[0]._spriteData;
3598 _oldSpriteIndex = _sprite[0]._spriteIndex;
3599 _oldFlipFl = _sprite[0]._flipFl;
3600 _sprite[0]._flipFl = flipFl;
3601
3602 uint strPos = 0;
3603 int spriteIndex = 0;
3604 do {
3605 bool completeTokenFl = false;
3606 do {
3607 char nextChar = animationSeq[strPos];
3608 if ((animationSeq[strPos] == ',') || (strPos == animationSeq.size() - 1)) {
3609 // Safeguard: if the sequence doesn't end with a coma, simulate it's present.
3610 if (animationSeq[strPos] != ',')
3611 tmpStr += nextChar;
3612 spriteIndex = atoi(tmpStr.c_str());
3613 tmpStr = "";
3614 completeTokenFl = true;
3615 } else {
3616 tmpStr += nextChar;
3617 }
3618 ++strPos;
3619 } while (!completeTokenFl);
3620
3621 if (spriteIndex != -1) {
3622 _sprite[0]._spriteData = spriteData;
3623 _sprite[0]._spriteIndex = spriteIndex;
3624 }
3625 for (int i = 0; i < realSpeed; i++)
3626 _vm->_events->refreshScreenAndEvents();
3627 } while (spriteIndex != -1);
3628 }
3629
showSpecialActionAnimation(const byte * spriteData,const Common::String & animString,int speed)3630 void ObjectsManager::showSpecialActionAnimation(const byte *spriteData, const Common::String &animString, int speed) {
3631 Common::String tmpStr = "";
3632 int realSpeed = speed;
3633 if (_vm->_globals->_speed == 2)
3634 realSpeed = speed / 2;
3635 else if (_vm->_globals->_speed == 3)
3636 realSpeed = speed / 3;
3637
3638 int spriteIndex = 0;
3639
3640 for (int idx = 0; ; idx++) {
3641 bool completeTokenFl = false;
3642 char nextChar = animString[idx];
3643 if (nextChar == ',') {
3644 spriteIndex = atoi(tmpStr.c_str());
3645 tmpStr = "";
3646 completeTokenFl = true;
3647 } else {
3648 tmpStr += nextChar;
3649 }
3650
3651 if (completeTokenFl) {
3652 if (spriteIndex == -1) {
3653 _sprite[0]._spriteData = _oldSpriteData;
3654 _sprite[0]._spriteIndex = _oldSpriteIndex;
3655 _sprite[0]._flipFl = _oldFlipFl;
3656 } else {
3657 _sprite[0]._spriteData = spriteData;
3658 _sprite[0]._spriteIndex = spriteIndex;
3659 }
3660
3661 for (int i = 0; i < realSpeed; i++)
3662 _vm->_events->refreshScreenAndEvents();
3663
3664 if (spriteIndex == -1)
3665 break;
3666 }
3667 }
3668 }
3669
handleForest(int screenId,int minX,int maxX,int minY,int maxY,int idx)3670 void ObjectsManager::handleForest(int screenId, int minX, int maxX, int minY, int maxY, int idx) {
3671 int savegameIdx = screenId;
3672 if (_vm->_globals->_screenId != screenId)
3673 return;
3674
3675 switch (_vm->_globals->_screenId) {
3676 case 35:
3677 if (idx > 2)
3678 savegameIdx = 201;
3679 else
3680 savegameIdx = 200;
3681 break;
3682 case 36:
3683 if (idx > 2)
3684 savegameIdx = 203;
3685 else
3686 savegameIdx = 202;
3687 break;
3688 case 37:
3689 if (idx > 2)
3690 savegameIdx = 205;
3691 else
3692 savegameIdx = 204;
3693 break;
3694 case 38:
3695 if (idx > 2)
3696 savegameIdx = 207;
3697 else
3698 savegameIdx = 206;
3699 break;
3700 case 39:
3701 if (idx > 2)
3702 savegameIdx = 209;
3703 else
3704 savegameIdx = 208;
3705 break;
3706 case 40:
3707 if (idx > 2)
3708 savegameIdx = 211;
3709 else
3710 savegameIdx = 210;
3711 break;
3712 case 41:
3713 if (idx > 2)
3714 savegameIdx = 213;
3715 else
3716 savegameIdx = 212;
3717 break;
3718 default:
3719 break;
3720 }
3721
3722 if (_vm->_globals->_saveData->_data[savegameIdx] == 2)
3723 return;
3724
3725 if (_vm->_globals->_saveData->_data[savegameIdx]) {
3726 if (_vm->_globals->_saveData->_data[savegameIdx] == 1) {
3727 if (((idx == 1 || idx == 2) && getBobAnimDataIdx(idx) == 26) || ((idx == 3 || idx == 4) && getBobAnimDataIdx(idx) == 27)) {
3728 _vm->_dialog->disableInvent();
3729 _vm->_soundMan->playSample(1);
3730 _vm->_globals->_saveData->_data[savegameIdx] = 4;
3731 }
3732 }
3733 if (_vm->_globals->_saveData->_data[savegameIdx] == 4) {
3734 if (idx >= 1 && idx <= 4 && getBobAnimDataIdx(idx) > 30)
3735 _vm->_globals->_saveData->_data[savegameIdx] = 3;
3736 }
3737 if (_vm->_globals->_saveData->_data[savegameIdx] == 3) {
3738 _vm->_graphicsMan->_fadingFl = true;
3739 _vm->_animMan->playAnim("CREVE2.ANM", "CREVE2.ANM", 100, 24, 500);
3740 _vm->_globals->_exitId = 150;
3741 _vm->_graphicsMan->_noFadingFl = true;
3742 hideBob(1);
3743 hideBob(2);
3744 hideBob(3);
3745 hideBob(4);
3746 }
3747 } else if (minX < getSpriteX(0)
3748 && maxX > getSpriteX(0)
3749 && minY < getSpriteY(0)
3750 && maxY > getSpriteY(0)) {
3751 if (idx >= 1 && idx <= 4)
3752 setBobAnimation(idx);
3753 _vm->_globals->_saveData->_data[savegameIdx] = 1;
3754 }
3755 }
3756
lockAnimX(int idx,int x)3757 void ObjectsManager::lockAnimX(int idx, int x) {
3758 _lockedAnims[idx]._enableFl = true;
3759 _lockedAnims[idx]._posX = x;
3760 }
3761
3762 /**
3763 * Game scene control method
3764 */
sceneControl(const Common::String & backgroundFile,const Common::String & linkFile,const Common::String & animFile,const Common::String & s4,int soundNum,bool initializeScreen)3765 void ObjectsManager::sceneControl(const Common::String &backgroundFile, const Common::String &linkFile,
3766 const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen) {
3767 _vm->_dialog->_inventFl = false;
3768 _vm->_events->_gameKey = KEY_NONE;
3769 _vm->_dialog->enableInvent();
3770 _vm->_graphicsMan->_scrollOffset = 0;
3771 _vm->_globals->_cityMapEnabledFl = false;
3772 _vm->_globals->_eventMode = EVENTMODE_IGNORE;
3773 _vm->_soundMan->playSound(soundNum);
3774 _vm->_linesMan->_route = NULL;
3775 _vm->_globals->_freezeCharacterFl = true;
3776 _vm->_globals->_exitId = 0;
3777 if (!backgroundFile.empty())
3778 _vm->_graphicsMan->loadImage(backgroundFile);
3779 if (!linkFile.empty())
3780 loadLinkFile(linkFile);
3781 if (!animFile.empty())
3782 _vm->_animMan->loadAnim(animFile);
3783 _vm->_graphicsMan->displayAllBob();
3784 if (!s4.empty()) {
3785 if (initializeScreen)
3786 _vm->_graphicsMan->initScreen(s4, 0, initializeScreen);
3787 else
3788 _vm->_graphicsMan->initScreen(s4, 2, initializeScreen);
3789 }
3790 _vm->_events->mouseOn();
3791 if (_vm->_globals->_screenId == 61) {
3792 addStaticSprite(_vm->_globals->_characterSpriteBuf, Common::Point(330, 418), 0, 60, 0, false, 34, 190);
3793 animateSprite(0);
3794 _vm->_linesMan->_route = NULL;
3795 computeAndSetSpriteSize();
3796 }
3797 _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
3798 _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
3799 _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
3800 _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
3801 _vm->_events->changeMouseCursor(4);
3802 for (int i = 0; i <= 4; i++)
3803 _vm->_events->refreshScreenAndEvents();
3804 _vm->_graphicsMan->fadeInLong();
3805 if (_vm->_globals->_screenId == 61) {
3806 _vm->_animMan->playSequence("OUVRE.SEQ", 10, 4, 10, false, false);
3807 stopBobAnimation(3);
3808 _vm->_globals->_checkDistanceFl = true;
3809 _oldCharacterPosX = getSpriteX(0);
3810 _oldDirection = DIR_NONE;
3811 _homeRateCounter = 0;
3812 _vm->_linesMan->_route = NULL;
3813 _vm->_linesMan->_route = _vm->_linesMan->findRoute(getSpriteX(0), getSpriteY(0), 330, 345);
3814 _vm->_globals->_checkDistanceFl = true;
3815 do {
3816 goHome();
3817 _vm->_events->refreshScreenAndEvents();
3818 } while (_vm->_linesMan->_route);
3819 setSpriteIndex(0, 64);
3820 }
3821 do {
3822 int mouseButton = _vm->_events->getMouseButton();
3823 if (mouseButton == 1) {
3824 handleLeftButton();
3825 mouseButton = 1;
3826 } else if (mouseButton == 2)
3827 handleRightButton();
3828 _vm->_dialog->testDialogOpening();
3829 _vm->_linesMan->checkZone();
3830 if (_vm->_globals->_actionMoveTo)
3831 paradise();
3832 if (!_vm->_globals->_exitId)
3833 _vm->_events->refreshScreenAndEvents();
3834
3835 if (_vm->_globals->_exitId)
3836 break;
3837 } while (!_vm->shouldQuit());
3838 if (_vm->shouldQuit())
3839 return;
3840
3841 _vm->_graphicsMan->fadeOutLong();
3842 if (!animFile.empty())
3843 _vm->_graphicsMan->endDisplayBob();
3844 if (_vm->_globals->_screenId == 61)
3845 removeSprite(0);
3846 clearScreen();
3847 _vm->_globals->_eventMode = EVENTMODE_DEFAULT;
3848 }
3849
3850 /**
3851 * Game scene control method
3852 */
sceneControl2(const Common::String & backgroundFile,const Common::String & linkFile,const Common::String & animFile,const Common::String & s4,int soundNum,bool initializeScreen)3853 void ObjectsManager::sceneControl2(const Common::String &backgroundFile, const Common::String &linkFile,
3854 const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen) {
3855 _vm->_dialog->_inventFl = false;
3856 _vm->_events->_gameKey = KEY_NONE;
3857 _verb = 4;
3858 _vm->_graphicsMan->_scrollOffset = 0;
3859 _vm->_dialog->enableInvent();
3860 _vm->_globals->_cityMapEnabledFl = false;
3861 _vm->_graphicsMan->_noFadingFl = false;
3862 _vm->_globals->_freezeCharacterFl = false;
3863 _vm->_globals->_exitId = 0;
3864 _vm->_globals->_checkDistanceFl = true;
3865 _vm->_soundMan->playSound(soundNum);
3866 _vm->_globals->_eventMode = EVENTMODE_IGNORE;
3867 if (!backgroundFile.empty())
3868 _vm->_graphicsMan->loadImage(backgroundFile);
3869 if (!linkFile.empty())
3870 loadLinkFile(linkFile);
3871 if (!animFile.empty()) {
3872 _vm->_animMan->loadAnim(animFile);
3873 _vm->_graphicsMan->displayAllBob();
3874 }
3875 if (!s4.empty()) {
3876 if (initializeScreen)
3877 _vm->_graphicsMan->initScreen(s4, 0, initializeScreen);
3878 else
3879 _vm->_graphicsMan->initScreen(s4, 2, initializeScreen);
3880 }
3881 _vm->_events->mouseOn();
3882 _vm->_events->_mouseCursorId = 4;
3883 _vm->_graphicsMan->setColorPercentage(252, 100, 100, 100);
3884 _vm->_graphicsMan->setColorPercentage(253, 100, 100, 100);
3885 _vm->_graphicsMan->setColorPercentage(251, 100, 100, 100);
3886 _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
3887 if (_vm->_globals->_characterType != CHARACTER_HOPKINS && !_vm->_globals->_saveData->_data[svAlternateSpriteFl] && !_vm->_globals->_saveData->_data[svField356]) {
3888 _vm->_globals->_characterSpriteBuf = _vm->_fileIO->loadFile("PERSO.SPR");
3889 _vm->_globals->_characterType = CHARACTER_HOPKINS;
3890 }
3891
3892 if (_vm->_globals->_characterType == CHARACTER_HOPKINS && _vm->_globals->_saveData->_data[svAlternateSpriteFl] == 1) {
3893 _vm->_globals->_characterSpriteBuf = _vm->_fileIO->loadFile("HOPFEM.SPR");
3894 _vm->_globals->_characterType = CHARACTER_HOPKINS_CLONE;
3895 }
3896
3897 if (_vm->_globals->_characterType != CHARACTER_SAMANTHA && _vm->_globals->_saveData->_data[svField356] == 1) {
3898 _vm->_globals->_characterSpriteBuf = _vm->_fileIO->loadFile("PSAMAN.SPR");
3899 _vm->_globals->_characterType = CHARACTER_SAMANTHA;
3900 }
3901 _vm->_globals->loadCharacterData();
3902 switch (_vm->_globals->_characterType) {
3903 case CHARACTER_HOPKINS:
3904 addStaticSprite(_vm->_globals->_characterSpriteBuf, _characterPos, 0, _startSpriteIndex, 0, false, 34, 190);
3905 break;
3906 case CHARACTER_HOPKINS_CLONE:
3907 addStaticSprite(_vm->_globals->_characterSpriteBuf, _characterPos, 0, _startSpriteIndex, 0, false, 28, 155);
3908 break;
3909 case CHARACTER_SAMANTHA:
3910 addStaticSprite(_vm->_globals->_characterSpriteBuf, _characterPos, 0, _startSpriteIndex, 0, false, 20, 127);
3911 break;
3912 default:
3913 break;
3914 }
3915 _vm->_events->setMouseXY(_characterPos);
3916 if (_vm->_graphicsMan->_largeScreenFl)
3917 _vm->_graphicsMan->_scrollPosX = (int16)getSpriteX(0) - 320;
3918 computeAndSetSpriteSize();
3919 animateSprite(0);
3920 enableHidingBehavior();
3921 _vm->_linesMan->_route = NULL;
3922 computeAndSetSpriteSize();
3923 sceneSpecialIni();
3924 _vm->_events->_mouseSpriteId = 4;
3925 _oldCharacterPosX = _characterPos.x;
3926 _oldCharacterPosY = _characterPos.y;
3927 _oldDirection = DIR_NONE;
3928 _homeRateCounter = 0;
3929
3930 for (int idx = 0; idx < 5; ++idx)
3931 _vm->_events->refreshScreenAndEvents();
3932
3933 _vm->_globals->_eventMode = EVENTMODE_IGNORE;
3934 if (!_vm->_graphicsMan->_noFadingFl)
3935 _vm->_graphicsMan->fadeInLong();
3936 _vm->_graphicsMan->_noFadingFl = false;
3937 _vm->_events->changeMouseCursor(4);
3938
3939 int xCheck = 0;
3940 int yCheck = 0;
3941
3942 bool breakFlag = false;
3943 while (!_vm->shouldQuit() && !breakFlag) {
3944 int mouseButtons = _vm->_events->getMouseButton();
3945 if (mouseButtons) {
3946 if (mouseButtons == 1) {
3947 if (_verb == 16 && _vm->_events->_mouseCursorId == 16) {
3948 int xp = _vm->_events->getMouseX();
3949 int yp = _vm->_events->getMouseY();
3950
3951 if ((xCheck == xp) && (yCheck == yp)) {
3952 _vm->_linesMan->_route = NULL;
3953 paradise();
3954 if (_vm->_globals->_exitId)
3955 breakFlag = true;
3956 }
3957 xCheck = xp;
3958 yCheck = yp;
3959 }
3960 handleLeftButton();
3961 } else if (mouseButtons == 2) {
3962 handleRightButton();
3963 }
3964 }
3965 if (!_vm->_globals->_exitId) {
3966 _vm->_dialog->testDialogOpening();
3967 _vm->_linesMan->checkZone();
3968 if (_vm->_linesMan->_route == NULL
3969 || (goHome(), _vm->_linesMan->_route == NULL)) {
3970 if (_vm->_globals->_actionMoveTo)
3971 paradise();
3972 }
3973 handleSpecialGames();
3974 _vm->_events->refreshScreenAndEvents();
3975 if (!_vm->_globals->_exitId)
3976 continue;
3977 }
3978 breakFlag = true;
3979 }
3980
3981 if (_vm->_globals->_exitId != 8 || _vm->_globals->_screenId != 5 || !_helicopterFl) {
3982 if (!_vm->_graphicsMan->_noFadingFl)
3983 _vm->_graphicsMan->fadeOutLong();
3984 _vm->_graphicsMan->_noFadingFl = false;
3985 removeSprite(0);
3986 if (_twoCharactersFl) {
3987 removeSprite(1);
3988 _twoCharactersFl = false;
3989 }
3990 if (!animFile.empty())
3991 _vm->_graphicsMan->endDisplayBob();
3992 clearScreen();
3993 } else {
3994 _helicopterFl = false;
3995 }
3996 _vm->_globals->_eventMode = EVENTMODE_DEFAULT;
3997 }
3998
setVerb(int id)3999 void ObjectsManager::setVerb(int id) {
4000 _verb = id;
4001 }
4002
resetHidingUseCount(int idx)4003 void ObjectsManager::resetHidingUseCount(int idx) {
4004 _hidingItem[idx]._useCount = 0;
4005 }
4006
setHidingUseCount(int idx)4007 void ObjectsManager::setHidingUseCount(int idx) {
4008 _hidingItem[idx]._useCount = 1;
4009 }
4010
4011 // Load Hiding Items
loadHidingItems(const Common::String & file)4012 void ObjectsManager::loadHidingItems(const Common::String &file) {
4013 resetHidingItems();
4014 byte *ptr = _vm->_fileIO->loadFile(file);
4015 Common::String filename = Common::String((const char *)ptr);
4016
4017 Common::File f;
4018 if (!f.exists(filename))
4019 return;
4020
4021 byte *spriteData = _vm->_fileIO->loadFile(filename);
4022 _hidingItemData[1] = spriteData;
4023 int curBufIdx = 60;
4024 for (int i = 0; i <= 21; i++) {
4025 HidingItem *hid = &_hidingItem[i];
4026 hid->_spriteIndex = READ_LE_INT16((uint16 *)ptr + curBufIdx);
4027 hid->_x = READ_LE_INT16((uint16 *)ptr + curBufIdx + 1);
4028 hid->_y = READ_LE_INT16((uint16 *)ptr + curBufIdx + 2);
4029 hid->_yOffset = READ_LE_INT16((uint16 *)ptr + curBufIdx + 4);
4030 if (spriteData == NULL) {
4031 hid->_useCount = 0;
4032 } else {
4033 hid->_spriteData = spriteData;
4034 hid->_width = getWidth(spriteData, hid->_spriteIndex);
4035 hid->_height = getHeight(spriteData, hid->_spriteIndex);
4036 hid->_useCount = 1;
4037 }
4038
4039 if ( !hid->_x && !hid->_y && !hid->_spriteIndex)
4040 hid->_useCount = 0;
4041 curBufIdx += 5;
4042 }
4043 enableHidingBehavior();
4044 _vm->_globals->freeMemory(ptr);
4045 }
4046
initVBob()4047 void ObjectsManager::initVBob() {
4048 for (int idx = 0; idx < 30; ++idx) {
4049 VBobItem *vbob = &_vBob[idx];
4050 vbob->_displayMode = 0;
4051 vbob->_xp = 0;
4052 vbob->_yp = 0;
4053 vbob->_frameIndex = 0;
4054 vbob->_surface = NULL;
4055 vbob->_spriteData = NULL;
4056 vbob->_oldSpriteData = NULL;
4057 }
4058 }
4059
clearVBob()4060 void ObjectsManager::clearVBob() {
4061 for (int idx = 0; idx < 30; ++idx) {
4062 VBobItem *vbob = &_vBob[idx];
4063 vbob->_displayMode = 0;
4064 vbob->_xp = 0;
4065 vbob->_yp = 0;
4066 vbob->_frameIndex = 0;
4067 vbob->_surface = _vm->_globals->freeMemory(vbob->_surface);
4068 vbob->_spriteData = NULL;
4069 vbob->_oldSpriteData = NULL;
4070 }
4071 }
4072
disableHidingItem(int idx)4073 void ObjectsManager::disableHidingItem(int idx) {
4074 assert(idx < 36);
4075 _bob[idx]._disableFl = true;
4076 }
4077
enableHidingBehavior()4078 void ObjectsManager::enableHidingBehavior() {
4079 _hidingActiveFl = true;
4080 }
4081
disableHidingBehavior()4082 void ObjectsManager::disableHidingBehavior() {
4083 _hidingActiveFl = false;
4084 }
4085
4086 } // End of namespace Hopkins
4087