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 "common/scummsys.h"
24 #include "access/access.h"
25 #include "access/resources.h"
26 #include "access/screen.h"
27 #include "access/amazon/amazon_game.h"
28 #include "access/amazon/amazon_logic.h"
29 #include "access/amazon/amazon_resources.h"
30
31 namespace Access {
32
33 namespace Amazon {
34
PannedScene(AmazonEngine * vm)35 PannedScene::PannedScene(AmazonEngine *vm) : AmazonManager(vm) {
36 for (int i = 0; i < PAN_SIZE; ++i) {
37 _pan[i]._pObject = nullptr;
38 _pan[i]._pImgNum = 0;
39 _pan[i]._pObjX = _pan[i]._pObjY = _pan[i]._pObjZ = 0;
40 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
41 }
42
43 _xCount = 0;
44 _xTrack = _yTrack = _zTrack = 0;
45 _xCam = _yCam = _zCam = 0;
46 _pNumObj = 0;
47 }
48
pan()49 void PannedScene::pan() {
50 _zCam += _zTrack;
51 _xCam += _xTrack;
52 int tx = (_xTrack << 8) / _zCam;
53 _yCam += _yTrack;
54 int ty = (_yTrack << 8) / _zCam;
55
56 if (_vm->_timers[24]._flag != 1) {
57 ++_vm->_timers[24]._flag;
58 for (int i = 0; i < _pNumObj; i++) {
59 _pan[i]._pObjZ += _zTrack;
60 _pan[i]._pObjXl += (_pan[i]._pObjZ * tx) & 0xff;
61 _pan[i]._pObjX += ((_pan[i]._pObjZ * tx) >> 8) + (_pan[i]._pObjXl >> 8);
62 _pan[i]._pObjXl &= 0xff;
63
64 _pan[i]._pObjYl += (_pan[i]._pObjZ * ty) & 0xff;
65 _pan[i]._pObjY += ((_pan[i]._pObjZ * ty) >> 8) + (_pan[i]._pObjYl >> 8);
66 _pan[i]._pObjYl &= 0xff;
67 }
68 }
69
70 for (int i = 0; i < _pNumObj; i++) {
71 ImageEntry ie;
72 ie._flags = IMGFLAG_UNSCALED;
73 ie._position = Common::Point(_pan[i]._pObjX, _pan[i]._pObjY);
74 ie._offsetY = 255;
75 ie._spritesPtr = _pan[i]._pObject;
76 ie._frameNumber = _pan[i]._pImgNum;
77
78 _vm->_images.addToList(ie);
79 }
80 }
81
82 /*------------------------------------------------------------------------*/
83
CampScene(AmazonEngine * vm)84 CampScene::CampScene(AmazonEngine *vm) : PannedScene(vm) {
85 _skipStart = false;
86 }
87
mWhileDoOpen()88 void CampScene::mWhileDoOpen() {
89 Screen &screen = *_vm->_screen;
90 EventsManager &events = *_vm->_events;
91
92 screen.setDisplayScan();
93 events.hideCursor();
94 screen.forceFadeOut();
95 _skipStart = false;
96 if (_vm->_conversation != 2) {
97 // Cutscene at start of chapter 1
98 screen.setPanel(3);
99 _vm->startChapter(1);
100 _vm->establishCenter(0, 1);
101 }
102
103 Resource *data = _vm->_files->loadFile(1, 0);
104 _vm->_objectsTable[1] = new SpriteResource(_vm, data);
105 delete data;
106
107 _vm->_files->_setPaletteFlag = false;
108 _vm->_files->loadScreen(1, 2);
109 _vm->_buffer2.blitFrom(*_vm->_screen);
110 _vm->_buffer1.blitFrom(*_vm->_screen);
111
112 // Load animation data
113 _vm->_animation->freeAnimationData();
114 Resource *animResource = _vm->_files->loadFile(1, 1);
115 _vm->_animation->loadAnimations(animResource);
116 delete animResource;
117
118 _xTrack = 8;
119 _yTrack = -3;
120 _zTrack = 0;
121 _xCam = _yCam = 0;
122 _zCam = 270;
123 _vm->_timers[24]._timer = _vm->_timers[24]._initTm = 1;
124 ++_vm->_timers[24]._flag;
125 _vm->_timers.updateTimers();
126
127 _pNumObj = 10;
128 for (int i = 0; i < _pNumObj; i++) {
129 _pan[i]._pObject = _vm->_objectsTable[1];
130 _pan[i]._pImgNum = OPENING_OBJS[i][0];
131 _pan[i]._pObjX = OPENING_OBJS[i][1];
132 _pan[i]._pObjY = OPENING_OBJS[i][2];
133 _pan[i]._pObjZ = OPENING_OBJS[i][3];
134 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
135 }
136
137 _vm->_oldRects.clear();
138 _vm->_newRects.clear();
139 Animation *anim = _vm->_animation->setAnimation(0);
140 _vm->_animation->setAnimTimer(anim);
141 anim = _vm->_animation->setAnimation(1);
142 _vm->_animation->setAnimTimer(anim);
143 _vm->_midi->newMusic(10, 0);
144
145 bool startFl = false;
146 while (!_vm->shouldQuit()) {
147 _vm->_images.clear();
148 _vm->_animation->animate(0);
149 _vm->_animation->animate(1);
150 pan();
151 _vm->_buffer2.copyFrom(_vm->_buffer1);
152 _vm->_newRects.clear();
153 _vm->plotList();
154 _vm->copyBlocks();
155 if (!startFl) {
156 startFl = true;
157 screen.forceFadeIn();
158 }
159
160 events.pollEventsAndWait();
161
162 if (_vm->_events->isKeyMousePressed()) {
163 _skipStart = true;
164 _vm->_midi->newMusic(10, 1);
165 break;
166 }
167
168 if (_xCam > 680) {
169 events._vbCount = 125;
170
171 while (!_vm->shouldQuit() && !events.isKeyMousePressed() && events._vbCount > 0) {
172 events.pollEventsAndWait();
173 }
174 break;
175 }
176 }
177
178 events.showCursor();
179 _vm->_buffer2.copyFrom(*_vm->_screen);
180 _vm->_buffer1.copyFrom(*_vm->_screen);
181
182 _vm->freeCells();
183 _vm->_oldRects.clear();
184 _vm->_newRects.clear();
185 _vm->_numAnimTimers = 0;
186 _vm->_images.clear();
187
188 if (_vm->isCD()) {
189 if (_vm->_conversation == 2) {
190 // Cutscene at end of Chapter 6
191 Resource *spriteData = _vm->_files->loadFile(28, 37);
192 _vm->_objectsTable[28] = new SpriteResource(_vm, spriteData);
193 delete spriteData;
194
195 _vm->_animation->freeAnimationData();
196 animResource = _vm->_files->loadFile(28, 38);
197 _vm->_animation->loadAnimations(animResource);
198 delete animResource;
199 }
200 } else {
201 _vm->freeCells();
202 _vm->_oldRects.clear();
203 _vm->_newRects.clear();
204 _vm->_numAnimTimers = 0;
205 _vm->_images.clear();
206 }
207 }
208
209 /*------------------------------------------------------------------------*/
210
Opening(AmazonEngine * vm)211 Opening::Opening(AmazonEngine *vm) : CampScene(vm) {
212 _pCount = 0;
213 }
214
doIntroduction()215 void Opening::doIntroduction() {
216 Screen &screen = *_vm->_screen;
217
218 screen.setInitialPalettte();
219 _vm->_events->setCursor(CURSOR_ARROW);
220 _vm->_events->showCursor();
221 screen.setPanel(0);
222 screen.setPalette();
223
224 _vm->_events->setCursor(CURSOR_ARROW);
225 _vm->_events->showCursor();
226 screen.setPanel(3);
227 doTitle();
228
229 if (_vm->shouldQuit() || _skipStart || _vm->isDemo())
230 return;
231
232 screen.setPanel(3);
233 mWhileDoOpen();
234
235 if (_vm->shouldQuit() || _skipStart)
236 return;
237
238 doTent();
239 }
240
doCredit()241 void Opening::doCredit() {
242 if (_pCount < 15)
243 return;
244
245 if (_pCount <= 75)
246 _vm->_buffer2.plotImage(_vm->_objectsTable[0], _vm->isDemo()? 24 : 0, Common::Point(90, 35));
247 else if (_pCount <= 210)
248 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 1, Common::Point(65, 35));
249 else if (_pCount <= 272)
250 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 2, Common::Point(96, 45));
251 else if (_pCount <= 334)
252 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 3, Common::Point(68, 54));
253 else if (_pCount <= 396)
254 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(103, 54));
255 else if (_pCount <= 458) {
256 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 5, Common::Point(8, 5));
257 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 12, Common::Point(88, 55));
258 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 6, Common::Point(194, 98));
259 } else if (_pCount <= 520) {
260 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 7, Common::Point(32, 13));
261 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 8, Common::Point(162, 80));
262 } else if (_pCount <= 580) {
263 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 9, Common::Point(18, 15));
264 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 10, Common::Point(164, 81));
265 } else
266 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 11, Common::Point(106, 55));
267 }
268
doCreditDemo()269 void Opening::doCreditDemo() {
270 if (_pCount < 15)
271 return;
272
273 if (_pCount <= 75)
274 _vm->_buffer2.plotImage(_vm->_objectsTable[0], _vm->isDemo()? 24 : 0, Common::Point(90, 35));
275 else if (_pCount <= 210)
276 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 25, Common::Point(82, 35));
277 else if (_pCount <= 272) {
278 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 23, Common::Point(77, 20));
279 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(50, 35));
280 } else if (_pCount <= 334) {
281 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 16, Common::Point(200, 70));
282 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(170, 85));
283 } else if (_pCount <= 396) {
284 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 15, Common::Point(65, 15));
285 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 2, Common::Point(30, 30));
286 } else if (_pCount <= 458) {
287 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 19, Common::Point(123, 40));
288 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 10, Common::Point(115, 55));
289 } else if (_pCount <= 520) {
290 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 18, Common::Point(50, 15));
291 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 9, Common::Point(40, 30));
292 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 0, Common::Point(40, 55));
293 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 20, Common::Point(198, 95));
294 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 3, Common::Point(160, 110));
295 } else if (_pCount <= 580) {
296 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 21, Common::Point(40, 10));
297 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 6, Common::Point(20, 25));
298 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 22, Common::Point(145, 50));
299 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 7, Common::Point(125, 65));
300 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 12, Common::Point(207, 90));
301 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 5, Common::Point(200, 105));
302 } else {
303 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 11, Common::Point(125, 30));
304 _vm->_buffer2.plotImage(_vm->_objectsTable[0], 4, Common::Point(115, 45));
305 }
306 }
307
scrollTitle()308 void Opening::scrollTitle() {
309 _vm->copyBF1BF2();
310 _vm->_newRects.clear();
311 if (_vm->isDemo())
312 doCreditDemo();
313 else
314 doCredit();
315 _vm->copyRects();
316 _vm->copyBF2Vid();
317 }
318
doTitle()319 void Opening::doTitle() {
320 Screen &screen = *_vm->_screen;
321
322 screen.setDisplayScan();
323
324 screen.forceFadeOut();
325 _vm->_events->hideCursor();
326
327 if (!_vm->isDemo()) {
328 _vm->_sound->loadSoundTable(0, 98, 30);
329 _vm->_sound->loadSoundTable(1, 98, 8);
330
331 _vm->_files->_setPaletteFlag = false;
332 _vm->_files->loadScreen(0, 3);
333
334 _vm->_buffer2.copyFrom(*_vm->_screen);
335 _vm->_buffer1.copyFrom(*_vm->_screen);
336 screen.forceFadeIn();
337
338 _vm->_sound->playSound(1, true);
339
340 Resource *spriteData = _vm->_files->loadFile(0, 2);
341 _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData);
342 delete spriteData;
343
344 _vm->_files->_setPaletteFlag = false;
345 _vm->_files->loadScreen(0, 4);
346
347 _vm->_buffer2.copyFrom(*_vm->_screen);
348 _vm->_buffer1.copyFrom(*_vm->_screen);
349
350 const int COUNTDOWN[6] = { 2, 0x80, 1, 0x7d, 0, 0x87 };
351 for (_pCount = 0; _pCount < 3 && !_vm->shouldQuit(); ++_pCount) {
352 _vm->_buffer2.blitFrom(_vm->_buffer1);
353 int id = COUNTDOWN[_pCount * 2];
354 int xp = COUNTDOWN[_pCount * 2 + 1];
355 _vm->_buffer2.plotImage(_vm->_objectsTable[0], id, Common::Point(xp, 71));
356 _vm->_buffer2.copyTo(_vm->_screen);
357
358 _vm->_events->_vbCount = 70;
359 while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0 && !_skipStart) {
360 _vm->_events->pollEventsAndWait();
361 if (_vm->_events->_rightButton)
362 _skipStart = true;
363 }
364 }
365 if (_vm->shouldQuit())
366 return;
367
368 _vm->_sound->stopSound();
369 _vm->_sound->checkSoundQueue(); // HACK: Clear sound 1 from the queue
370 _vm->_sound->playSound(0);
371 screen.forceFadeOut();
372 _vm->_events->_vbCount = 100;
373 while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0)
374 _vm->_events->pollEventsAndWait();
375 if (_vm->shouldQuit())
376 return;
377
378 _vm->_sound->freeSounds();
379 delete _vm->_objectsTable[0];
380 _vm->_objectsTable[0] = nullptr;
381
382 _vm->_files->_setPaletteFlag = false;
383 _vm->_files->loadScreen(0, 5);
384 _vm->_buffer2.blitFrom(*_vm->_screen);
385 _vm->_buffer1.blitFrom(*_vm->_screen);
386 screen.forceFadeIn();
387 _vm->_midi->newMusic(1, 0);
388 _vm->_events->_vbCount = 950;
389 while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0) && !_vm->_events->isKeyMousePressed()) {
390 _vm->_events->pollEventsAndWait();
391 }
392
393 if (_vm->_events->_rightButton) {
394 _skipStart = true;
395 _vm->_room->clearRoom();
396 _vm->_events->showCursor();
397 return;
398 }
399
400 _vm->_midi->newMusic(1, 1);
401 _vm->_midi->setLoop(false);
402 _vm->_events->zeroKeys();
403 }
404
405 _vm->_buffer1.create(_vm->_screen->w + TILE_WIDTH, _vm->_screen->h);
406 _vm->_room->loadRoom(0);
407 screen.clearScreen();
408 screen.setBufferScan();
409 _vm->_scrollRow = _vm->_scrollCol = 0;
410 _vm->_scrollX = _vm->_scrollY = 0;
411 _vm->_player->_rawPlayer = Common::Point(0, 0);
412 screen.forceFadeOut();
413 _vm->_room->buildScreen();
414 _vm->copyBF2Vid();
415 screen.forceFadeIn();
416 _vm->_oldRects.clear();
417 _vm->_newRects.clear();
418 _vm->_events->clearEvents();
419 _vm->_player->_scrollAmount = 1;
420 _pCount = 0;
421
422 while (!_vm->shouldQuit()) {
423 if (_vm->_events->isKeyMousePressed()) {
424 if (_vm->_events->_rightButton)
425 _skipStart = true;
426 _vm->_room->clearRoom();
427 _vm->_events->showCursor();
428 return;
429 }
430
431 _vm->_events->_vbCount = 4;
432 if (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth) {
433 _vm->_scrollX += _vm->_player->_scrollAmount;
434
435 while (_vm->_scrollX >= TILE_WIDTH) {
436 _vm->_scrollX -= TILE_WIDTH;
437 ++_vm->_scrollCol;
438
439 _vm->_buffer1.moveBufferLeft();
440 _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
441 }
442 scrollTitle();
443 ++_pCount;
444
445 while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0)) {
446 _vm->_events->pollEventsAndWait();
447 }
448 continue;
449 }
450
451 _vm->_events->_vbCount = 120;
452 while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0))
453 _vm->_events->pollEventsAndWait();
454
455 while (!_vm->shouldQuit()) {
456 _pCount = 0;
457 _vm->_events->_vbCount = 3;
458 if (_vm->_scrollRow + screen._vWindowHeight >= _vm->_room->_playFieldHeight) {
459 _vm->_room->clearRoom();
460 _vm->_events->showCursor();
461 return;
462 }
463
464 _vm->_scrollY = _vm->_scrollY + _vm->_player->_scrollAmount;
465
466 while (_vm->_scrollY >= TILE_HEIGHT && !_vm->shouldQuit()) {
467 _vm->_scrollY -= TILE_HEIGHT;
468 ++_vm->_scrollRow;
469 _vm->_buffer1.moveBufferUp();
470
471 // WORKAROUND: the original was using screen._vWindowBytesWide * screen._vWindowLinesTall
472 _vm->_room->buildRow(_vm->_scrollRow + screen._vWindowHeight, screen._vWindowLinesTall);
473
474 if (_vm->_scrollRow + screen._vWindowHeight >= _vm->_room->_playFieldHeight) {
475 _vm->_room->clearRoom();
476 _vm->_events->showCursor();
477 return;
478 }
479 }
480 scrollTitle();
481 while (!_vm->shouldQuit() && (_vm->_events->_vbCount > 0))
482 _vm->_events->pollEventsAndWait();
483 }
484 }
485 }
486
doTent()487 void Opening::doTent() {
488 int step = 0;
489 _vm->_screen->setDisplayScan();
490 _vm->_screen->forceFadeOut();
491 _vm->_events->hideCursor();
492 _vm->_sound->loadSoundTable(0, 98, 39);
493 _vm->_sound->loadSoundTable(1, 98, 14);
494 _vm->_sound->loadSoundTable(2, 98, 15);
495 _vm->_sound->loadSoundTable(3, 98, 16);
496 _vm->_sound->loadSoundTable(4, 98, 31, 2);
497 _vm->_sound->loadSoundTable(5, 98, 52, 2);
498 _vm->_sound->playSound(0);
499
500 _vm->_files->_setPaletteFlag = false;
501 _vm->_files->loadScreen(2, 0);
502 _vm->_buffer2.blitFrom(*_vm->_screen);
503 _vm->_buffer1.blitFrom(*_vm->_screen);
504 _vm->_screen->forceFadeIn();
505
506 _vm->_video->setVideo(_vm->_screen, Common::Point(126, 73), FileIdent(2, 1), 10);
507 int previousFrame = -1;
508 while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) {
509 _vm->_video->playVideo();
510 if (previousFrame != _vm->_video->_videoFrame) {
511 previousFrame = _vm->_video->_videoFrame;
512
513 if ((_vm->_video->_videoFrame == 32) || (_vm->_video->_videoFrame == 34))
514 _vm->_sound->playSound(4);
515 else if (_vm->_video->_videoFrame == 36) {
516 if (step != 2) {
517 _vm->_sound->playSound(2);
518 step = 2;
519 }
520 } else if (_vm->_video->_videoFrame == 18) {
521 if (step != 1) {
522 _vm->_midi->newMusic(73, 1);
523 _vm->_midi->newMusic(11, 0);
524 step = 1;
525 _vm->_sound->playSound(1);
526 }
527 }
528 }
529 _vm->_events->pollEventsAndWait();
530 }
531
532 _vm->_sound->playSound(5);
533 _vm->_video->setVideo(_vm->_screen, Common::Point(43, 11), FileIdent(2, 2), 10);
534 previousFrame = -1;
535 while (!_vm->shouldQuit() && !_vm->_video->_videoEnd) {
536 _vm->_video->playVideo();
537 if (previousFrame != _vm->_video->_videoFrame) {
538 previousFrame = _vm->_video->_videoFrame;
539 if (_vm->_video->_videoFrame == 26) {
540 _vm->_sound->playSound(5);
541 } else if (_vm->_video->_videoFrame == 15) {
542 if (step !=3) {
543 _vm->_sound->playSound(3);
544 step = 3;
545 }
546 }
547 }
548 _vm->_events->pollEventsAndWait();
549 }
550
551 _vm->_events->_vbCount = 200;
552 while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0)
553 _vm->_events->pollEventsAndWait();
554
555 _vm->_events->showCursor();
556 _vm->_midi->newMusic(11, 1);
557 _vm->_sound->_soundTable.clear();
558
559 _vm->establishCenter(0, 4);
560 }
561
562 /*------------------------------------------------------------------------*/
563
Plane(AmazonEngine * vm)564 Plane::Plane(AmazonEngine *vm) : PannedScene(vm) {
565 _pCount = 0;
566 _planeCount = 0;
567 _propCount = 0;
568 }
569
570
doFlyCell()571 void Plane::doFlyCell() {
572 SpriteResource *sprites = _vm->_objectsTable[15];
573
574 if (_pCount <= 40) {
575 _vm->_buffer2.plotImage(sprites, 3, Common::Point(70, 74));
576 } else if (_pCount <= 80) {
577 _vm->_buffer2.plotImage(sprites, 6, Common::Point(70, 74));
578 } else if (_pCount <= 120) {
579 _vm->_buffer2.plotImage(sprites, 2, Common::Point(50, 76));
580 } else if (_pCount <= 160) {
581 _vm->_buffer2.plotImage(sprites, 14, Common::Point(63, 78));
582 } else if (_pCount <= 200) {
583 _vm->_buffer2.plotImage(sprites, 5, Common::Point(86, 74));
584 } else if (_pCount <= 240) {
585 _vm->_buffer2.plotImage(sprites, 0, Common::Point(103, 76));
586 } else if (_pCount <= 280) {
587 _vm->_buffer2.plotImage(sprites, 4, Common::Point(119, 77));
588 } else {
589 _vm->_buffer2.plotImage(sprites, 1, Common::Point(111, 77));
590 }
591
592 if (_planeCount == 11 || _planeCount == 12)
593 ++_position.y;
594 else if (_planeCount >= 28)
595 --_position.y;
596
597 _vm->_buffer2.plotImage(sprites, 7, _position);
598 _vm->_buffer2.plotImage(sprites, 8 + _propCount, Common::Point(
599 _position.x + 99, _position.y + 10));
600 _vm->_buffer2.plotImage(sprites, 11 + _propCount, Common::Point(
601 _position.x + 104, _position.y + 18));
602
603 if (++_planeCount >= 30)
604 _planeCount = 0;
605 if (++_propCount >= 3)
606 _propCount = 0;
607
608 ++_xCount;
609 if (_xCount == 1)
610 ++_position.x;
611 else
612 _xCount = 0;
613 }
614
doFallCell()615 void Plane::doFallCell() {
616 if (_vm->_scaleI <= 20)
617 return;
618
619 SpriteFrame *frame = _vm->_objectsTable[20]->getFrame(_planeCount / 6);
620 Common::Rect r(115, 11, 115 + _vm->_screen->_scaleTable1[frame->w],
621 11 + _vm->_screen->_scaleTable1[frame->h]);
622 _vm->_buffer2.sPlotF(frame, r);
623
624 _vm->_scaleI -= 3;
625 _vm->_scale = _vm->_scaleI;
626 _vm->_screen->setScaleTable(_vm->_scale);
627 ++_xCount;
628 if (_xCount == 5)
629 return;
630 _xCount = 0;
631 if (_planeCount == 18)
632 _planeCount = 0;
633 else
634 _planeCount += 6;
635 }
636
scrollFly()637 void Plane::scrollFly() {
638 _vm->copyBF1BF2();
639 _vm->_newRects.clear();
640 doFlyCell();
641 _vm->copyRects();
642 _vm->copyBF2Vid();
643 }
644
scrollFall()645 void Plane::scrollFall() {
646 _vm->copyBF1BF2();
647 _vm->_newRects.clear();
648 doFallCell();
649 _vm->copyRects();
650 _vm->copyBF2Vid();
651 }
652
mWhileFly()653 void Plane::mWhileFly() {
654 Screen &screen = *_vm->_screen;
655 Player &player = *_vm->_player;
656 EventsManager &events = *_vm->_events;
657
658 events.hideCursor();
659 screen.clearScreen();
660 screen.setBufferScan();
661 screen.fadeOut();
662 _vm->_scrollX = 0;
663
664 _vm->_room->buildScreen();
665 _vm->copyBF2Vid();
666 screen.fadeIn();
667 _vm->_oldRects.clear();
668 _vm->_newRects.clear();
669 _vm->_events->clearEvents();
670
671 _vm->_scrollRow = _vm->_scrollCol = 0;
672 _vm->_scrollX = _vm->_scrollY = 0;
673 player._rawPlayer = Common::Point(0, 0);
674 player._scrollAmount = 1;
675
676 _pCount = 0;
677 _planeCount = 0;
678 _propCount = 0;
679 _xCount = 0;
680 _position = Common::Point(20, 29);
681
682 while (!_vm->shouldQuit() && !events.isKeyMousePressed() &&
683 ((_vm->_scrollCol + screen._vWindowWidth) != _vm->_room->_playFieldWidth)) {
684 events._vbCount = 4;
685 _vm->_scrollX += player._scrollAmount;
686
687 while (_vm->_scrollX >= TILE_WIDTH) {
688 _vm->_scrollX -= TILE_WIDTH;
689 ++_vm->_scrollCol;
690
691 _vm->_buffer1.moveBufferLeft();
692 _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
693 }
694
695 scrollFly();
696 ++_pCount;
697
698 while (!_vm->shouldQuit() && events._vbCount > 0) {
699 _vm->_sound->playSound(0);
700 events.pollEventsAndWait();
701 }
702 }
703
704 events.showCursor();
705 }
706
mWhileFall()707 void Plane::mWhileFall() {
708 Screen &screen = *_vm->_screen;
709 EventsManager &events = *_vm->_events;
710
711 events.hideCursor();
712 screen.clearScreen();
713 screen.setBufferScan();
714 screen.fadeOut();
715 _vm->_scrollX = 0;
716
717 _vm->_room->buildScreen();
718 _vm->copyBF2Vid();
719 screen.fadeIn();
720 _vm->_oldRects.clear();
721 _vm->_newRects.clear();
722 _vm->_events->clearEvents();
723
724 _vm->_scrollRow = _vm->_scrollCol = 0;
725 _vm->_scrollX = _vm->_scrollY = 0;
726 _vm->_player->_scrollAmount = 3;
727 _vm->_scaleI = 255;
728
729 _xCount = 0;
730 _planeCount = 0;
731
732 while (!_vm->shouldQuit() && !events.isKeyMousePressed() &&
733 (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth)) {
734 events._vbCount = 4;
735 _vm->_scrollX += _vm->_player->_scrollAmount;
736
737 while (_vm->_scrollX >= TILE_WIDTH) {
738 _vm->_scrollX -= TILE_WIDTH;
739 ++_vm->_scrollCol;
740
741 _vm->_buffer1.moveBufferLeft();
742 _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
743 }
744
745 scrollFall();
746
747 while (!_vm->shouldQuit() && events._vbCount > 0) {
748 events.pollEventsAndWait();
749 }
750 }
751
752 events.showCursor();
753 }
754
755 /*------------------------------------------------------------------------*/
756
Jungle(AmazonEngine * vm)757 Jungle::Jungle(AmazonEngine *vm) : CampScene(vm) {
758 for (int i = 0; i < JUNGLE_SIZE; ++i) {
759 _jCnt[i] = _jungleX[i] = -1;
760 }
761 }
762
jungleMove()763 void Jungle::jungleMove() {
764 const static int jungleY[3] = { 27, 30, 29 };
765 int count = 1;
766 int frameOffset = 0;
767
768 if (!_vm->_timers[0]._flag) {
769 ++_vm->_timers[0]._flag;
770 _vm->_scrollX += _vm->_player->_scrollAmount;
771
772 for (int i = 0; i < 3; ++i) {
773 int newJCnt = (_jCnt[i] + 1) % 8;
774 _jCnt[i] = newJCnt;
775 _jungleX[i] += 5;
776 }
777
778 frameOffset = 4;
779 count = (_vm->_allenFlag != 1) ? 2 : 3;
780 }
781
782 for (int i = 0; i < count; ++i) {
783 ImageEntry ie;
784 ie._flags = IMGFLAG_UNSCALED;
785 ie._spritesPtr = _vm->_objectsTable[24];
786 ie._frameNumber = _jCnt[i] + frameOffset;
787 ie._position = Common::Point(_jungleX[i], jungleY[i]);
788 ie._offsetY = jungleY[i];
789
790 _vm->_images.addToList(ie);
791 frameOffset += 8;
792 }
793 }
794
initJWalk2()795 void Jungle::initJWalk2() {
796 const int JUNGLE1OBJ[7][4] = {
797 { 2, 470, 0, 20 },
798 { 0, 290, 0, 50 },
799 { 1, 210, 0, 40 },
800 { 0, 500, 0, 30 },
801 { 1, 550, 0, 20 },
802 { 0, 580, 0, 60 },
803 { 1, 650, 0, 30 }
804 };
805
806 Screen &screen = *_vm->_screen;
807 screen.fadeOut();
808 _vm->_events->hideCursor();
809 screen.clearScreen();
810 _vm->_buffer2.clearBuffer();
811 screen.setBufferScan();
812
813 _vm->_scrollX = _vm->_scrollY;
814 _vm->_scrollCol = _vm->_scrollRow;
815 _vm->_room->buildScreen();
816 _vm->copyBF2Vid();
817 screen.fadeIn();
818 _vm->_events->clearEvents();
819
820 _xCount = 2;
821 _vm->_player->_scrollAmount = 5;
822 _xTrack = -10;
823 _yTrack = _zTrack = 0;
824 _xCam = 480;
825 _yCam = 0;
826 _zCam = 80;
827
828 _vm->_timers[24]._timer = 1;
829 _vm->_timers[24]._initTm = 1;
830 ++_vm->_timers[24]._flag;
831
832 _pNumObj = 7;
833 for (int i = 0; i < _pNumObj; i++) {
834 _pan[i]._pObject = _vm->_objectsTable[24];
835 _pan[i]._pImgNum = JUNGLE1OBJ[i][0];
836 _pan[i]._pObjX = JUNGLE1OBJ[i][1];
837 _pan[i]._pObjY = JUNGLE1OBJ[i][2];
838 _pan[i]._pObjZ = JUNGLE1OBJ[i][3];
839 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
840 }
841
842 _jCnt[0] = 0;
843 _jCnt[1] = 3;
844 _jCnt[2] = 5;
845
846 _jungleX[0] = 50;
847 _jungleX[1] = 16;
848 _jungleX[2] = 93;
849 }
850
mWhileJWalk()851 void Jungle::mWhileJWalk() {
852 Screen &screen = *_vm->_screen;
853 EventsManager &events = *_vm->_events;
854 Player &player = *_vm->_player;
855
856 static const int JUNGLE_OBJ[7][4] = {
857 { 2, 77, 0, 40 },
858 { 0, 290, 0, 50 },
859 { 1, 210, 0, 70 },
860 { 0, 50, 0, 30 },
861 { 1, 70, 0, 20 },
862 { 0, -280, 0, 60 },
863 { 1, -150, 0, 30 },
864 };
865
866 screen.fadeOut();
867 events.hideCursor();
868 screen.clearScreen();
869 _vm->_buffer2.clearBuffer();
870 screen.setBufferScan();
871 _vm->_scrollX = 0;
872
873 // Build the initial jungle scene and fade it in
874 _vm->_room->buildScreen();
875 _vm->copyBF2Vid();
876 screen.fadeIn();
877
878 // Set up the player to walk horizontally
879 player._xFlag = 1;
880 player._yFlag = 0;
881 player._moveTo.x = 160;
882 player._playerMove = true;
883
884 _xCount = 2;
885 _xTrack = 10;
886 _yTrack = _zTrack = 0;
887 _xCam = 480;
888 _yCam = 0;
889 _zCam = 80;
890
891 TimerEntry *te = &_vm->_timers[24];
892 te->_initTm = te->_timer = 1;
893 te->_flag++;
894
895 _pNumObj = 7;
896 for (int i = 0; i < _pNumObj; i++) {
897 _pan[i]._pObject = _vm->_objectsTable[24];
898 _pan[i]._pImgNum = JUNGLE_OBJ[i][0];
899 _pan[i]._pObjX = JUNGLE_OBJ[i][1];
900 _pan[i]._pObjY = JUNGLE_OBJ[i][2];
901 _pan[i]._pObjZ = JUNGLE_OBJ[i][3];
902 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
903 }
904
905 while (!_vm->shouldQuit() && !events.isKeyMousePressed() && (player._xFlag != 2)) {
906 _vm->_images.clear();
907 events._vbCount = 6;
908
909 _pan[0]._pImgNum = _xCount;
910 if (_xCount == 2)
911 ++_xCount;
912 else
913 --_xCount;
914
915 player.checkMove();
916 player.checkScroll();
917 pan();
918 scrollJWalk();
919
920 while (!_vm->shouldQuit() && events._vbCount > 0) {
921 events.pollEventsAndWait();
922 }
923 }
924
925 _vm->_images.clear();
926 events.showCursor();
927 }
928
mWhileJWalk2()929 void Jungle::mWhileJWalk2() {
930 Screen &screen = *_vm->_screen;
931
932 initJWalk2();
933
934 while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() &&
935 (_vm->_scrollCol + screen._vWindowWidth) != _vm->_room->_playFieldWidth) {
936 _vm->_images.clear();
937 _vm->_events->_vbCount = 6;
938 _pan[0]._pImgNum = _xCount;
939
940 jungleMove();
941 while (_vm->_scrollX >= TILE_WIDTH) {
942 _vm->_scrollX -= TILE_WIDTH;
943 ++_vm->_scrollCol;
944 _vm->_buffer1.moveBufferLeft();
945 _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
946 }
947
948 if (_xCount == 2)
949 ++_xCount;
950 else
951 --_xCount;
952
953 pan();
954 scrollJWalk();
955
956 while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) {
957 _vm->_events->pollEventsAndWait();
958 }
959 }
960
961 _vm->_events->showCursor();
962 }
963
scrollJWalk()964 void Jungle::scrollJWalk() {
965 _vm->copyBF1BF2();
966 _vm->_newRects.clear();
967 _vm->plotList();
968 _vm->copyRects();
969 _vm->copyBF2Vid();
970 }
971
972 /*------------------------------------------------------------------------*/
973
Guard(AmazonEngine * vm)974 Guard::Guard(AmazonEngine *vm) : PannedScene(vm) {
975 _guardCel = 0;
976 _gCode1 = _gCode2 = 0;
977 _xMid = _yMid = 0;
978 }
979
setVerticalCode()980 void Guard::setVerticalCode() {
981 Screen &screen = *_vm->_screen;
982
983 _gCode1 = 0;
984 _gCode2 = 0;
985 if (_topLeft.x < screen._orgX1)
986 _gCode1 |= 8;
987 else if (_topLeft.x == screen._orgX1) {
988 _gCode1 |= 8;
989 _gCode1 |= 2;
990 } else
991 _gCode1 |= 2;
992
993 if (_bottomRight.x < screen._orgX1)
994 _gCode2 |= 8;
995 else if (_bottomRight.x == screen._orgX1) {
996 _gCode2 |= 8;
997 _gCode2 |= 2;
998 } else
999 _gCode2 |= 2;
1000
1001 if (_topLeft.y < screen._orgY1)
1002 _gCode1 |= 4;
1003 else if (_topLeft.y > screen._orgY2)
1004 _gCode1 |= 1;
1005
1006 if (_bottomRight.y < screen._orgY1)
1007 _gCode2 |= 4;
1008 else if (_bottomRight.y > screen._orgY2)
1009 _gCode2 |= 1;
1010 }
1011
setHorizontalCode()1012 void Guard::setHorizontalCode() {
1013 Screen &screen = *_vm->_screen;
1014
1015 _gCode1 = 0;
1016 _gCode2 = 0;
1017
1018 if (_topLeft.y < screen._orgY1)
1019 _gCode1 |= 4;
1020 else if (_topLeft.x == screen._orgX1) {
1021 _gCode1 |= 4;
1022 _gCode1 |= 1;
1023 } else
1024 _gCode1 |= 1;
1025
1026 if (_bottomRight.y < screen._orgY1)
1027 _gCode2 |= 4;
1028 else if (_bottomRight.x == screen._orgX1) {
1029 _gCode2 |= 4;
1030 _gCode2 |= 1;
1031 } else
1032 _gCode2 |= 1;
1033
1034 if (_topLeft.x < screen._orgX1)
1035 _gCode1 |= 8;
1036 else if (_topLeft.x > screen._orgX2)
1037 _gCode1 |= 2;
1038
1039 if (_bottomRight.x < screen._orgX1)
1040 _gCode2 |= 8;
1041 else if (_bottomRight.x > screen._orgX2)
1042 _gCode2 |= 2;
1043 }
1044
chkVLine()1045 void Guard::chkVLine() {
1046 if (_position.x > _vm->_player->_rawPlayer.x) {
1047 _topLeft = _vm->_player->_rawPlayer;
1048 _bottomRight = _position;
1049 } else {
1050 _topLeft = _position;
1051 _bottomRight = _vm->_player->_rawPlayer;
1052 }
1053
1054 if (_vm->_screen->_orgY1 > _vm->_screen->_orgY2)
1055 SWAP(_vm->_screen->_orgY1, _vm->_screen->_orgY2);
1056
1057 for (;;) {
1058 setVerticalCode();
1059 int code = _gCode1 | _gCode2;
1060 if (code == 10) {
1061 _vm->_guardFind = 0;
1062 return;
1063 }
1064
1065 int code2 = _gCode1 & _gCode2;
1066 code2 &= 5;
1067 if (((code & 10) == 8) || ((code & 10) == 2) || (code2 != 0))
1068 return;
1069
1070 int midX = (_topLeft.x + _bottomRight.x) / 2;
1071 int midY = (_topLeft.y + _bottomRight.y) / 2;
1072
1073 if (midX < _vm->_screen->_orgX1) {
1074 if ((midX == _topLeft.x) && (midY == _topLeft.y))
1075 return;
1076
1077 _topLeft.x = midX;
1078 _topLeft.y = midY;
1079 } else {
1080 if ((midX == _bottomRight.x) && (midY == _bottomRight.y))
1081 return;
1082
1083 _bottomRight.x = midX;
1084 _bottomRight.y = midY;
1085 }
1086 }
1087 }
1088
chkHLine()1089 void Guard::chkHLine() {
1090 if (_position.y > _vm->_player->_rawPlayer.y) {
1091 _topLeft = _vm->_player->_rawPlayer;
1092 _bottomRight = _position;
1093 } else {
1094 _topLeft = _position;
1095 _bottomRight = _vm->_player->_rawPlayer;
1096 }
1097
1098 if (_vm->_screen->_orgX1 > _vm->_screen->_orgX2)
1099 SWAP(_vm->_screen->_orgX1, _vm->_screen->_orgX2);
1100
1101 while (true) {
1102 setHorizontalCode();
1103 int code = _gCode1 | _gCode2;
1104 if (code == 5) {
1105 _vm->_guardFind = 0;
1106 return;
1107 }
1108
1109 int code2 = _gCode1 & _gCode2;
1110 code2 &= 10;
1111 if (((code & 5) == 4) || ((code & 5) == 1) || (code2 != 0))
1112 return;
1113
1114 int midX = (_topLeft.x + _bottomRight.x) / 2;
1115 int midY = (_topLeft.y + _bottomRight.y) / 2;
1116
1117 if (midY < _vm->_screen->_orgY1) {
1118 if ((midX == _topLeft.x) && (midY == _topLeft.y))
1119 return;
1120
1121 _topLeft.x = midX;
1122 _topLeft.y = midY;
1123 } else {
1124 if ((midX == _bottomRight.x) && (midY == _bottomRight.y))
1125 return;
1126
1127 _bottomRight.x = midX;
1128 _bottomRight.y = midY;
1129 }
1130 }
1131 }
1132
guardSee()1133 void Guard::guardSee() {
1134 Screen &screen = *_vm->_screen;
1135 int tmpY = (_vm->_scrollRow << 4) + _vm->_scrollY;
1136 _vm->_flags[140] = 0;
1137 if (tmpY > _position.y)
1138 return;
1139
1140 tmpY += screen._vWindowLinesTall;
1141 tmpY -= 11;
1142
1143 if (tmpY < _position.y)
1144 return;
1145
1146 _vm->_guardFind = 1;
1147 _vm->_flags[140] = 1;
1148
1149 for (uint16 idx = 0; idx < _vm->_room->_plotter._walls.size(); idx++) {
1150 screen._orgX1 = _vm->_room->_plotter._walls[idx].left;
1151 screen._orgY1 = _vm->_room->_plotter._walls[idx].top;
1152 screen._orgX2 = _vm->_room->_plotter._walls[idx].right;
1153 screen._orgY2 = _vm->_room->_plotter._walls[idx].bottom;
1154 if (screen._orgX1 == screen._orgX2) {
1155 chkVLine();
1156 if (_vm->_guardFind == 0)
1157 return;
1158 } else if (screen._orgY1 == screen._orgY2) {
1159 chkHLine();
1160 if (_vm->_guardFind == 0)
1161 return;
1162 }
1163 }
1164 }
1165
setGuardFrame()1166 void Guard::setGuardFrame() {
1167 ImageEntry ie;
1168 ie._flags = IMGFLAG_UNSCALED;
1169
1170 if (_vm->_guardLocation == 4)
1171 ie._flags |= IMGFLAG_BACKWARDS;
1172 ie._spritesPtr = _vm->_objectsTable[37];
1173 ie._frameNumber = _guardCel;
1174 ie._position = _position;
1175 ie._offsetY = 10;
1176 _vm->_images.addToList(ie);
1177 }
1178
doGuard()1179 void Guard::doGuard() {
1180 // Skip the code dealing with the guard on the boat (chapter 8)
1181 // if the cheat mode is activated
1182 if (_vm->_cheatFl)
1183 return;
1184
1185 if (_vm->_timers[8]._flag) {
1186 setGuardFrame();
1187 return;
1188 }
1189
1190 ++_vm->_timers[8]._flag;
1191 ++_guardCel;
1192 int curCel = _guardCel;
1193
1194 switch (_vm->_guardLocation) {
1195 case 1:
1196 // Guard walking down
1197 if (curCel <= 8 || curCel > 13)
1198 _guardCel = curCel = 8;
1199
1200 _position.y += _vm->_player->_walkOffDown[curCel - 8];
1201 guardSee();
1202 if (_position.y >= 272) {
1203 _position.y = 272;
1204 _vm->_guardLocation = 2;
1205 }
1206 break;
1207 case 2:
1208 // Guard walking left
1209 if (curCel <= 43 || curCel > 48)
1210 _guardCel = curCel = 43;
1211
1212 _position.x -= _vm->_player->_walkOffLeft[curCel - 43];
1213 guardSee();
1214 if (_position.x <= 56) {
1215 _position.x = 56;
1216 _vm->_guardLocation = 3;
1217 }
1218 break;
1219 case 3:
1220 // Guard walking up
1221 if (curCel <= 0 || curCel > 5)
1222 _guardCel = curCel = 0;
1223
1224 _position.y -= _vm->_player->_walkOffUp[curCel];
1225 guardSee();
1226 if (_position.y <= 89) {
1227 _position.y = 89;
1228 _vm->_guardLocation = 4;
1229 if (_vm->_flags[121] == 1)
1230 _vm->_guardLocation = 5;
1231 }
1232 break;
1233 default:
1234 // Guard walking right
1235 if (curCel <= 43 || curCel > 48)
1236 _guardCel = curCel = 43;
1237
1238 _position.x += _vm->_player->_walkOffRight[curCel - 43];
1239 guardSee();
1240 if (_position.x >= 127) {
1241 _position.x = 127;
1242 _vm->_guardLocation = 1;
1243 }
1244 break;
1245 }
1246
1247 setGuardFrame();
1248 }
1249
setPosition(const Common::Point & pt)1250 void Guard::setPosition(const Common::Point &pt) {
1251 _position = pt;
1252 }
1253
1254 /*------------------------------------------------------------------------*/
1255
Cast(AmazonEngine * vm)1256 Cast::Cast(AmazonEngine *vm) : PannedScene(vm) {
1257 }
1258
doCast(int param1)1259 void Cast::doCast(int param1) {
1260 Screen &screen = *_vm->_screen;
1261
1262 _vm->_buffer1.create(_vm->_screen->w, _vm->_screen->h);
1263 _vm->_buffer2.create(_vm->_screen->w, _vm->_screen->h);
1264
1265 screen.setDisplayScan();
1266 _vm->_events->hideCursor();
1267 screen.forceFadeOut();
1268 screen._clipHeight = 173;
1269 screen.clearScreen();
1270 _vm->_chapter = 16;
1271 _vm->tileScreen();
1272 _vm->updateSummary(param1);
1273 screen.setPanel(3);
1274 _vm->_chapter = 14;
1275
1276 Resource *spriteData = _vm->_files->loadFile(91, 0);
1277 _vm->_objectsTable[0] = new SpriteResource(_vm, spriteData);
1278 delete spriteData;
1279 spriteData = _vm->_files->loadFile(91, 1);
1280 _vm->_objectsTable[1] = new SpriteResource(_vm, spriteData);
1281 delete spriteData;
1282
1283 _vm->_files->_setPaletteFlag = false;
1284 _vm->_files->loadScreen(58, 1);
1285 _vm->_buffer2.blitFrom(*_vm->_screen);
1286 _vm->_buffer1.blitFrom(*_vm->_screen);
1287
1288 _xTrack = 0;
1289 _yTrack = -6;
1290 _zTrack = 0;
1291 _xCam = _yCam = 0;
1292 _zCam = 60;
1293
1294 _vm->_timers[24]._timer = 1;
1295 _vm->_timers[24]._initTm = 1;
1296 ++_vm->_timers[24]._flag;
1297
1298 _pNumObj = 26;
1299 for (int i = 0; i < _pNumObj; i++) {
1300 _pan[i]._pObject = _vm->_objectsTable[0];
1301 _pan[i]._pImgNum = CAST_END_OBJ[i][0];
1302 _pan[i]._pObjX = CAST_END_OBJ[i][1];
1303 _pan[i]._pObjY = CAST_END_OBJ[i][2];
1304 _pan[i]._pObjZ = CAST_END_OBJ[i][3];
1305 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
1306 }
1307
1308 _pNumObj += 4;
1309 for (int i = 0; i < 4; i++) {
1310 _pan[26 + i]._pObject = _vm->_objectsTable[1];
1311 _pan[26 + i]._pImgNum = CAST_END_OBJ1[i][0];
1312 _pan[26 + i]._pObjX = CAST_END_OBJ1[i][1];
1313 _pan[26 + i]._pObjY = CAST_END_OBJ1[i][2];
1314 _pan[26 + i]._pObjZ = CAST_END_OBJ1[i][3];
1315 _pan[26 + i]._pObjXl = _pan[26 + i]._pObjYl = 0;
1316 }
1317
1318 _vm->_oldRects.clear();
1319 _vm->_newRects.clear();
1320 _vm->_numAnimTimers = 0;
1321
1322 _vm->_midi->newMusic(58, 0);
1323 screen.forceFadeIn();
1324
1325 while (!_vm->shouldQuit()) {
1326 _vm->_images.clear();
1327 pan();
1328 _vm->_buffer2.blitFrom(_vm->_buffer1);
1329 _vm->_newRects.clear();
1330 _vm->plotList();
1331 _vm->copyBlocks();
1332
1333 for (int idx = 0; idx < 5 && !_vm->shouldQuit() &&
1334 !_vm->_events->isKeyMousePressed(); ++idx)
1335 _vm->_events->pollEventsAndWait();
1336
1337 if (_vm->_events->isKeyMousePressed())
1338 break;
1339
1340 if (_yCam < -7550) {
1341 while (!_vm->shouldQuit() && !_vm->_midi->checkMidiDone())
1342 _vm->_events->pollEventsAndWait();
1343 break;
1344 }
1345 }
1346
1347 _vm->_midi->newMusic(58, 1);
1348 _vm->_events->showCursor();
1349
1350 _vm->freeCells();
1351 _vm->_oldRects.clear();
1352 _vm->_newRects.clear();
1353 _vm->_numAnimTimers = 0;
1354 _vm->_images.clear();
1355 screen.forceFadeOut();
1356
1357 _vm->quitGame();
1358 _vm->_events->pollEvents();
1359 }
1360
1361 /*------------------------------------------------------------------------*/
1362
River(AmazonEngine * vm)1363 River::River(AmazonEngine *vm) : PannedScene(vm) {
1364 _chickenOutFl = false;
1365 _rScrollRow = 0;
1366 _rScrollCol = 0;
1367 _rScrollX = 0;
1368 _rScrollY = 0;
1369 _mapOffset = 0;
1370 _screenVertX = 0;
1371 _saveRiver = false;
1372 _deathFlag = false;
1373 _deathCount = 0;
1374 _oldScrollCol = 0;
1375 _maxHits = 0;
1376 _mapPtr = nullptr;
1377 _canoeMoveCount = 0;
1378 _canoeVXPos = 0;
1379 _canoeFrame = 0;
1380 _canoeDir = 0;
1381 _canoeLane = 0;
1382 _canoeYPos = 0;
1383 _hitCount = 0;
1384 _riverIndex = 0;
1385 _topList = _botList = nullptr;
1386 _deathType = 0;
1387 _hitSafe = 0;
1388 }
1389
setRiverPan()1390 void River::setRiverPan() {
1391 int delta = (_vm->_scrollCol * 16) + _vm->_scrollX;
1392
1393 _xTrack = 9;
1394 _yTrack = _zTrack = 0;
1395 _xCam = 160;
1396 _yCam = 0;
1397 _zCam = 80;
1398
1399 _vm->_timers[24]._timer = 1;
1400 _vm->_timers[24]._initTm = 1;
1401 ++_vm->_timers[24]._flag;
1402
1403 _pNumObj = 23;
1404 for (int i = 0; i < _pNumObj; i++) {
1405 _pan[i]._pObject = _vm->_objectsTable[45];
1406 _pan[i]._pImgNum = RIVER1OBJ[i][0];
1407 _pan[i]._pObjX = RIVER1OBJ[i][1] + delta;
1408 _pan[i]._pObjY = RIVER1OBJ[i][2];
1409 _pan[i]._pObjZ = RIVER1OBJ[i][3];
1410 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
1411 }
1412 }
1413
initRiver()1414 void River::initRiver() {
1415 static const int RIVERVXTBL[3] = { 6719, 7039, 8319 };
1416 Screen &screen = *_vm->_screen;
1417
1418 _vm->_events->centerMousePos();
1419 _vm->_events->restrictMouse();
1420 screen.setDisplayScan();
1421 screen.clearScreen();
1422 screen.savePalette();
1423 screen.forceFadeOut();
1424
1425 _vm->_files->_setPaletteFlag = false;
1426 _vm->_files->loadScreen(95, 4);
1427 _vm->_buffer2.blitFrom(*_vm->_screen);
1428
1429 screen.restorePalette();
1430 screen.setBufferScan();
1431 _vm->_destIn = &_vm->_buffer2;
1432 _vm->_room->roomMenu();
1433
1434 if (_saveRiver) {
1435 // Restoring a savegame, so set properties from saved fields
1436 _vm->_scrollRow = _rScrollRow;
1437 _vm->_scrollCol = _rScrollCol;
1438 _vm->_scrollX = _rScrollX;
1439 _vm->_scrollY = _rScrollY;
1440 } else {
1441 // Set initial scene state
1442 _vm->_scrollRow = 0;
1443 _vm->_scrollCol = 140;
1444 _vm->_scrollX = 0;
1445 _vm->_scrollY = 0;
1446 }
1447
1448 _vm->_room->buildScreen();
1449 _vm->copyBF2Vid();
1450 screen.forceFadeIn();
1451
1452 if (!_saveRiver) {
1453 // Reset draw rects
1454 _vm->_oldRects.clear();
1455 _vm->_newRects.clear();
1456 _vm->_events->clearEvents();
1457
1458 }
1459
1460 _vm->_player->_scrollAmount = 2;
1461 setRiverPan();
1462 _vm->_timers[3]._timer = 1;
1463 _vm->_timers[3]._initTm = 1;
1464 ++_vm->_timers[3]._flag;
1465
1466 _canoeFrame = 0;
1467 _mapPtr = (const byte *)MAPTBL[_vm->_riverFlag] + 1;
1468 if (_saveRiver) {
1469 _mapPtr--;
1470 _mapPtr += _mapOffset;
1471 } else {
1472 _screenVertX = RIVERVXTBL[_vm->_riverFlag] - 320;
1473 _canoeLane = 3;
1474 _hitCount = 0;
1475 _hitSafe = 0;
1476 _canoeYPos = 71;
1477 }
1478
1479 _riverIndex = _vm->_riverFlag;
1480 _topList = RIVER_OBJECTS[_riverIndex][RIVER_START];
1481 updateObstacles();
1482 riverSetPhysX();
1483 _canoeDir = 0;
1484 _deathFlag = false;
1485 _deathCount = 0;
1486
1487 _vm->_timers[11]._timer = 1200;
1488 _vm->_timers[11]._initTm = 1200;
1489 ++_vm->_timers[11]._flag;
1490 _vm->_timers[12]._timer = 1500;
1491 _vm->_timers[12]._initTm = 1500;
1492 ++_vm->_timers[12]._flag;
1493
1494 _maxHits = 2 - _vm->_riverFlag;
1495 _saveRiver = false;
1496
1497 // Set font colors for drawing using font2
1498 Font::_fontColors[0] = 0;
1499 Font::_fontColors[1] = 33;
1500 Font::_fontColors[2] = 34;
1501 Font::_fontColors[3] = 35;
1502 }
1503
resetPositions()1504 void River::resetPositions() {
1505 riverSetPhysX();
1506 int val = (_vm->_scrollCol + 1 - _oldScrollCol) * 16;
1507 if (val < 0) {
1508 val |= 0x80;
1509 }
1510
1511 for (int i = 0; i < _pNumObj; i++)
1512 _pan[i]._pObjX += val;
1513 }
1514
checkRiverPan()1515 void River::checkRiverPan() {
1516 int val = _vm->_scrollCol * 16 + 320;
1517
1518 for (int i = 0; i < _pNumObj; i++) {
1519 if (_pan[i]._pObjX < val)
1520 return;
1521 }
1522
1523 setRiverPan();
1524 }
1525
riverJumpTest()1526 bool River::riverJumpTest() {
1527 if (_vm->_scrollCol == 120 || _vm->_scrollCol == 60 || _vm->_scrollCol == 0) {
1528 int val = *++_mapPtr;
1529 if (val == 0xFF)
1530 return true;
1531
1532 _oldScrollCol = _vm->_scrollCol;
1533
1534 if (val == 0) {
1535 _vm->_scrollCol = 139;
1536 _vm->_scrollX = 14;
1537 _vm->_room->buildScreen();
1538 resetPositions();
1539 return false;
1540 }
1541 } else if (_vm->_scrollCol == 105) {
1542 int val1 = _mapPtr[1];
1543 int val2 = _mapPtr[2];
1544 _mapPtr += 3;
1545 if (_canoeLane < 3) {
1546 if (val1 != 0) {
1547 _deathFlag = true;
1548 _deathCount = 300;
1549 _deathType = val2;
1550 }
1551 } else {
1552 if (val1 != 1) {
1553 _deathFlag = true;
1554 _deathCount = 300;
1555 _deathType = val2;
1556 }
1557 _oldScrollCol = _vm->_scrollCol;
1558 _vm->_scrollCol = 44;
1559 _vm->_scrollX = 14;
1560 _vm->_room->buildScreen();
1561 resetPositions();
1562 return false;
1563 }
1564 }
1565
1566 _vm->_scrollX = 14;
1567 --_vm->_scrollCol;
1568 _vm->_buffer1.moveBufferRight();
1569 _vm->_room->buildColumn(_vm->_scrollCol, 0);
1570 checkRiverPan();
1571 return false;
1572 }
1573
riverSound()1574 void River::riverSound() {
1575 if (_vm->_timers[11]._flag == 0) {
1576 ++_vm->_timers[11]._flag;
1577 _vm->_sound->playSound(2);
1578 }
1579
1580 if (_vm->_timers[12]._flag == 0) {
1581 ++_vm->_timers[12]._flag;
1582 _vm->_sound->playSound(3);
1583 }
1584
1585 if ((_xCam >= 1300) && (_xCam <= 1320))
1586 _vm->_sound->playSound(1);
1587 }
1588
moveCanoe()1589 void River::moveCanoe() {
1590 EventsManager &events = *_vm->_events;
1591 Common::Point pt = events.calcRawMouse();
1592 Common::Point mousePos = events.getMousePos();
1593
1594 // Do an event polling
1595 _vm->_canSaveLoad = true;
1596 events.pollEvents();
1597 _vm->_canSaveLoad = false;
1598 if (_vm->_room->_function == FN_CLEAR1)
1599 return;
1600
1601 if (_canoeDir) {
1602 // Canoe movement in progress
1603 moveCanoe2();
1604 } else {
1605 if (events._leftButton && pt.y >= 140) {
1606 if (pt.x < _vm->_room->_rMouse[8][0]) {
1607 // Disk icon wasn't clicked
1608 _vm->_scripts->printString(AMRES.BAR_MESSAGE);
1609 } else {
1610 // Clicked on the Disc icon. Show the ScummVM menu
1611 _vm->_room->handleCommand(9);
1612
1613 if (_vm->_room->_function != FN_CLEAR1) {
1614 _vm->_room->buildScreen();
1615 _vm->copyBF2Vid();
1616 }
1617 }
1618 } else if (events._leftButton && mousePos.x < 35 && mousePos.y < 12) {
1619 // Clicked on the Skip button. So chicken out
1620 _chickenOutFl = true;
1621 } else if ((events._leftButton && pt.y <= _canoeYPos) ||
1622 (!events._leftButton && _vm->_player->_move == UP)) {
1623 // Move canoe up
1624 if (_canoeLane > 0) {
1625 _canoeDir = -1;
1626 _canoeMoveCount = 0;
1627
1628 moveCanoe2();
1629 }
1630 } else if (events._leftButton || _vm->_player->_move == DOWN) {
1631 // Move canoe down
1632 if (_canoeLane < 7) {
1633 _canoeDir = 1;
1634 _canoeMoveCount = 0;
1635
1636 moveCanoe2();
1637 }
1638 }
1639 }
1640 }
1641
moveCanoe2()1642 void River::moveCanoe2() {
1643 _canoeYPos += _canoeDir;
1644
1645 if (++_canoeMoveCount == 5) {
1646 _canoeLane += _canoeDir;
1647 _canoeDir = 0;
1648 }
1649 }
1650
updateObstacles()1651 void River::updateObstacles() {
1652 RiverStruct *cur;
1653 for (cur = _topList; cur < RIVER_OBJECTS[_riverIndex][RIVER_END]; ++cur) {
1654 int val = cur->_riverX + cur->_width - 1;
1655 if (val < _screenVertX)
1656 // Obstacle is not yet on-screen
1657 break;
1658
1659 if (cur->_riverX < (_screenVertX + 319)) {
1660 // Object is now on-screen. So set _topList/_botList to the range
1661 // of river obstacles that are currently visible
1662 _topList = cur;
1663 _botList = cur;
1664
1665 while (cur < RIVER_OBJECTS[_riverIndex][RIVER_END]) {
1666 ++cur;
1667 val = cur->_riverX + cur->_width - 1;
1668 if (val < _screenVertX || (cur->_riverX >= (_screenVertX + 319)))
1669 break;
1670
1671 _botList = cur;
1672 }
1673
1674 return;
1675 }
1676 }
1677
1678 cur = _topList;
1679 cur--;
1680 _botList = cur;
1681 }
1682
riverSetPhysX()1683 void River::riverSetPhysX() {
1684 int xAmt = (_vm->_scrollCol * 16) + _vm->_scrollX;
1685
1686 for (RiverStruct *cur = _topList; cur <= _botList; ++cur) {
1687 cur->_xp = xAmt - (_screenVertX - cur->_riverX);
1688 }
1689 }
1690
checkRiverCollide()1691 bool River::checkRiverCollide() {
1692 if (_hitSafe)
1693 return false;
1694
1695 _canoeVXPos = _screenVertX + 170;
1696
1697 for (RiverStruct *cur = _topList; cur <= _botList; ++cur) {
1698 if (cur->_lane < _canoeLane)
1699 continue;
1700
1701 if ((cur->_lane == _canoeLane) || (cur->_lane == _canoeLane + 1)) {
1702 if ((cur->_riverX + cur->_width - 1) >= _canoeVXPos &&
1703 cur->_riverX < (_canoeVXPos + 124)) {
1704 _vm->_sound->playSound(4);
1705 return true;
1706 }
1707 }
1708 }
1709
1710 return false;
1711 }
1712
plotRiver()1713 void River::plotRiver() {
1714 // Handle cycling through the canoe rowing frames
1715 if (_vm->_timers[3]._flag == 0) {
1716 ++_vm->_timers[3]._flag;
1717
1718 if (_canoeFrame++ == 12)
1719 _canoeFrame = 0;
1720 }
1721
1722 // Draw the canoe
1723 ImageEntry ie;
1724 ie._flags = IMGFLAG_UNSCALED;
1725 ie._spritesPtr = _vm->_objectsTable[45];
1726 ie._frameNumber = _canoeFrame;
1727 ie._position.x = (_vm->_scrollCol * 16) + _vm->_scrollX + 160;
1728 ie._position.y = _canoeYPos - 41;
1729 ie._offsetY = 41;
1730 _vm->_images.addToList(ie);
1731
1732 // Draw any on-screen obstacles
1733 for (RiverStruct *cur = _topList; cur <= _botList; ++cur) {
1734 if (cur->_id != -1) {
1735 ie._flags = IMGFLAG_UNSCALED;
1736 ie._spritesPtr = _vm->_objectsTable[45];
1737 ie._frameNumber = cur->_id;
1738 ie._position.x = cur->_xp;
1739 ie._position.y = (cur->_lane * 5) + 56 - cur->_offsetY;
1740 ie._offsetY = cur->_offsetY;
1741 _vm->_images.addToList(ie);
1742 }
1743 }
1744
1745 // Draw the text for skipping the river
1746 Font &font2 = *_vm->_fonts._font2;
1747 font2.drawString(_vm->_screen, "SKIP", Common::Point(5, 5));
1748 }
1749
mWhileDownRiver()1750 void River::mWhileDownRiver() {
1751 Screen &screen = *_vm->_screen;
1752 _vm->_events->hideCursor();
1753
1754 screen.setDisplayScan();
1755 screen.clearScreen();
1756 screen.savePalette();
1757 if (!_vm->isDemo())
1758 _vm->_files->loadScreen(95, 4);
1759 _vm->_buffer2.blitFrom(*_vm->_screen);
1760 screen.restorePalette();
1761 screen.setPalette();
1762 screen.setBufferScan();
1763
1764 _vm->_scrollX = 0;
1765 _vm->_room->buildScreen();
1766 _vm->copyBF2Vid();
1767
1768 _vm->_player->_scrollAmount = 2;
1769 _vm->_destIn = &_vm->_buffer2;
1770 _xTrack = -7;
1771 _yTrack = _zTrack = 0;
1772 _xCam = _yCam = 0;
1773 _zCam = 80;
1774
1775 _vm->_timers[24]._timer = 1;
1776 _vm->_timers[24]._initTm = 1;
1777 ++_vm->_timers[24]._flag;
1778
1779 _pNumObj = 14;
1780 for (int i = 0; i <_pNumObj; i++) {
1781 _pan[i]._pObject = _vm->_objectsTable[33];
1782 _pan[i]._pImgNum = DOWNRIVEROBJ[i][0];
1783 _pan[i]._pObjX = DOWNRIVEROBJ[i][1];
1784 _pan[i]._pObjY = DOWNRIVEROBJ[i][2];
1785 _pan[i]._pObjZ = DOWNRIVEROBJ[i][3];
1786 _pan[i]._pObjXl = _pan[i]._pObjYl = 0;
1787 }
1788
1789 _vm->_timers[3]._timer = 200;
1790 _vm->_timers[3]._initTm = 200;
1791 ++_vm->_timers[3]._flag;
1792 _vm->_timers[4]._timer = 350;
1793 _vm->_timers[4]._initTm = 350;
1794 ++_vm->_timers[4]._flag;
1795
1796 while (!_vm->shouldQuit() && !_vm->_events->isKeyMousePressed() &&
1797 (_vm->_scrollCol + screen._vWindowWidth != _vm->_room->_playFieldWidth)) {
1798 _vm->_images.clear();
1799 _vm->_events->_vbCount = 6;
1800
1801 _vm->_scrollX += _vm->_player->_scrollAmount;
1802 while (_vm->_scrollX >= TILE_WIDTH) {
1803 _vm->_scrollX -= TILE_WIDTH;
1804 ++_vm->_scrollCol;
1805 _vm->_buffer1.moveBufferLeft();
1806 _vm->_room->buildColumn(_vm->_scrollCol + screen._vWindowWidth, screen._vWindowBytesWide);
1807 }
1808
1809 pan();
1810 scrollRiver();
1811
1812 if (!_vm->_timers[3]._flag) {
1813 ++_vm->_timers[3]._flag;
1814 _vm->_sound->playSound(1);
1815 } else if (!_vm->_timers[4]._flag) {
1816 ++_vm->_timers[4]._flag;
1817 _vm->_sound->playSound(0);
1818 }
1819
1820 while (!_vm->shouldQuit() && _vm->_events->_vbCount > 0) {
1821 _vm->_events->pollEventsAndWait();
1822 }
1823 }
1824
1825 _vm->_events->showCursor();
1826 }
1827
scrollRiver()1828 void River::scrollRiver() {
1829 _vm->copyBF1BF2();
1830 _vm->_newRects.clear();
1831 _vm->_buffer2.plotImage(_vm->_objectsTable[33], 0, Common::Point(66, 30));
1832 _vm->plotList();
1833 _vm->copyRects();
1834 _vm->copyBF2Vid();
1835 }
1836
scrollRiver1()1837 void River::scrollRiver1() {
1838 _vm->copyBF1BF2();
1839 _vm->_newRects.clear();
1840 plotRiver();
1841 _vm->plotList();
1842 _vm->copyRects();
1843 _vm->copyBF2Vid();
1844 }
1845
doRiver()1846 void River::doRiver() {
1847 static const int RIVERDEATH[5] = { 22, 23, 24, 25, 26 };
1848
1849 initRiver();
1850 _vm->_events->showCursor();
1851
1852 while (!_vm->shouldQuit()) {
1853 _vm->_events->_vbCount = 4;
1854
1855 // Move the river position
1856 _screenVertX -= _vm->_player->_scrollAmount;
1857
1858 if (_vm->_scrollX == 0) {
1859 _vm->_midi->midiRepeat();
1860 if (riverJumpTest()) {
1861 _chickenOutFl = false;
1862 return;
1863 }
1864 } else {
1865 _vm->_scrollX -= _vm->_player->_scrollAmount;
1866 }
1867
1868 if (_chickenOutFl) {
1869 _chickenOutFl = false;
1870 return;
1871 }
1872
1873 _vm->_images.clear();
1874 _vm->_animation->animate(0);
1875
1876 riverSound();
1877 pan();
1878 moveCanoe();
1879
1880 if (_vm->_room->_function != FN_CLEAR1) {
1881 updateObstacles();
1882 riverSetPhysX();
1883 bool checkCollide = checkRiverCollide();
1884 if (_hitSafe != 0)
1885 _hitSafe -= 2;
1886
1887 if (checkCollide) {
1888 _vm->dead(RIVERDEATH[0]);
1889 return;
1890 }
1891
1892 if (_deathFlag) {
1893 if (--_deathCount == 0) {
1894 _vm->dead(RIVERDEATH[_deathType]);
1895 return;
1896 }
1897 }
1898
1899 // Scroll the river
1900 scrollRiver1();
1901
1902 // Allow time for new scrolled river position to be shown
1903 _vm->_canSaveLoad = true;
1904 while (!_vm->shouldQuit() && _vm->_room->_function == FN_NONE &&
1905 _vm->_events->_vbCount > 0) {
1906 _vm->_events->pollEventsAndWait();
1907 }
1908 _vm->_canSaveLoad = false;
1909 }
1910
1911 if (_vm->_room->_function == FN_CLEAR1) {
1912 _vm->_scripts->_endFlag = true;
1913 _vm->_scripts->_returnCode = 0;
1914 _chickenOutFl = false;
1915 break;
1916 }
1917 }
1918 }
1919
synchronize(Common::Serializer & s)1920 void River::synchronize(Common::Serializer &s) {
1921 if (_vm->_player->_roomNumber == 45) {
1922 if (s.isSaving()) {
1923 // Set river properties to be saved out
1924 _rScrollRow = _vm->_scrollRow;
1925 _rScrollCol = _vm->_scrollCol;
1926 _rScrollX = _vm->_scrollX;
1927 _rScrollY = _vm->_scrollY;
1928 _mapOffset = _mapPtr - MAPTBL[_vm->_riverFlag];
1929 }
1930
1931 s.syncAsSint16LE(_canoeLane);
1932 s.syncAsSint16LE(_canoeYPos);
1933 s.syncAsSint16LE(_hitCount);
1934 s.syncAsSint16LE(_riverIndex);
1935 s.syncAsSint16LE(_hitSafe);
1936 s.syncAsUint16LE(_rScrollRow);
1937 s.syncAsUint16LE(_rScrollCol);
1938 s.syncAsSint16LE(_rScrollX);
1939 s.syncAsSint16LE(_rScrollY);
1940 s.syncAsUint16LE(_mapOffset);
1941 s.syncAsUint16LE(_screenVertX);
1942
1943 _saveRiver = s.isLoading();
1944 }
1945 }
1946
1947 /*------------------------------------------------------------------------*/
1948
Ant(AmazonEngine * vm)1949 Ant::Ant(AmazonEngine *vm) : AmazonManager(vm) {
1950 _antDirection = ANT_RIGHT;
1951 _pitDirection = ANT_RIGHT;
1952 _antCel = 0;
1953 _torchCel = 0;
1954 _pitCel = 0;
1955 _stabCel = 0;
1956 _antPos = Common::Point(0, 0);
1957 _antDieFl = _antEatFl = false;
1958 _stabFl = false;
1959 _pitPos = Common::Point(0, 0);
1960 }
1961
plotTorchSpear(int indx,const int * & buf)1962 void Ant::plotTorchSpear(int indx, const int *&buf) {
1963 int idx = indx;
1964
1965 ImageEntry ie;
1966 ie._flags = IMGFLAG_UNSCALED;
1967 ie._spritesPtr = _vm->_objectsTable[62];
1968 ie._frameNumber = buf[(idx / 2)];
1969 ie._position = Common::Point(_pitPos.x + buf[(idx / 2) + 1], _pitPos.y + buf[(idx / 2) + 2]);
1970 ie._offsetY = 255;
1971 _vm->_images.addToList(ie);
1972 }
1973
plotPit(int indx,const int * & buf)1974 void Ant::plotPit(int indx, const int *&buf) {
1975 int idx = indx;
1976 ImageEntry ie;
1977 ie._flags = IMGFLAG_UNSCALED;
1978 ie._spritesPtr = _vm->_objectsTable[62];
1979 ie._frameNumber = buf[(idx / 2)];
1980 ie._position = Common::Point(_pitPos.x, _pitPos.y);
1981 ie._offsetY = _pitPos.y;
1982 _vm->_images.addToList(ie);
1983
1984 _vm->_player->_rawPlayer = _pitPos;
1985 if (_vm->_inventory->_inv[INV_TORCH]._value == ITEM_IN_INVENTORY) {
1986 // Player has torch
1987 idx = _torchCel;
1988 buf = Amazon::TORCH;
1989 _vm->_timers[14]._flag = 1;
1990 idx += 6;
1991 if (buf[idx / 2] == -1)
1992 idx = 0;
1993 _torchCel = idx;
1994 plotTorchSpear(idx, buf);
1995 } else if (!_stabFl && (_vm->_inventory->_inv[INV_KNIFE_SPEAR]._value == ITEM_IN_INVENTORY)) {
1996 // Player has spear
1997 idx = 0;
1998 buf = Amazon::SPEAR;
1999 plotTorchSpear(idx, buf);
2000 }
2001 }
2002
antHandleRight(int indx,const int * & buf)2003 int Ant::antHandleRight(int indx, const int *&buf) {
2004 int retval = indx;
2005 if (_pitDirection == ANT_RIGHT) {
2006 _pitDirection = ANT_LEFT;
2007 _pitPos.y = 127;
2008 }
2009 retval = _pitCel;
2010 buf = Amazon::PITWALK;
2011 if (_pitPos.x < 230) {
2012 if (retval == 0) {
2013 retval = 48;
2014 _pitPos.y = 127;
2015 }
2016 retval -= 6;
2017 _pitPos.x -= buf[(retval / 2) + 1];
2018 _pitPos.y -= buf[(retval / 2) + 2];
2019 _pitCel = retval;
2020 }
2021 return retval;
2022 }
2023
antHandleLeft(int indx,const int * & buf)2024 int Ant::antHandleLeft(int indx, const int *&buf) {
2025 int retval = indx;
2026 if (_pitDirection == ANT_LEFT) {
2027 _pitDirection = ANT_RIGHT;
2028 _pitPos.y = 127;
2029 }
2030 retval = _pitCel;
2031 buf = Amazon::PITWALK;
2032 retval += 6;
2033 if (buf[retval / 2] == -1) {
2034 retval = 0;
2035 _pitPos.y = 127;
2036 }
2037 _pitPos.x += buf[(retval / 2) + 1];
2038 _pitPos.y += buf[(retval / 2) + 2];
2039 _pitCel = retval;
2040
2041 return retval;
2042 }
2043
antHandleStab(int indx,const int * & buf)2044 int Ant::antHandleStab(int indx, const int *&buf) {
2045 int retval = indx;
2046 if (_vm->_inventory->_inv[INV_KNIFE_SPEAR]._value == ITEM_IN_INVENTORY) {
2047 if (_stabFl) {
2048 buf = Amazon::PITSTAB;
2049 retval = _stabCel;
2050 if (_vm->_timers[13]._flag == 0) {
2051 _vm->_timers[13]._flag = 1;
2052 retval += 6;
2053 _stabCel = retval;
2054
2055 if (buf[retval] == -1) {
2056 _stabFl = false;
2057 _pitCel = 0;
2058 _pitPos.y = 127;
2059 retval = 0;
2060 buf = Amazon::PITWALK;
2061 } else {
2062 _pitPos.x += buf[(retval / 2) + 1];
2063 _pitPos.y += buf[(retval / 2) + 2];
2064 _pitCel = retval;
2065 }
2066 }
2067 } else {
2068 _stabFl = true;
2069 _pitCel = 0;
2070 retval = 0;
2071 _stabCel = 0;
2072 int dist = _pitPos.x - _antPos.x;
2073 if (_antEatFl && !_antDieFl && (dist <= 80)) {
2074 _antDieFl = true;
2075 _antCel = 0;
2076 _antPos.y = 123;
2077 _vm->_sound->playSound(1);
2078 }
2079 }
2080 }
2081
2082 return retval;
2083 }
2084
doAnt()2085 void Ant::doAnt() {
2086 _antDirection = ANT_RIGHT;
2087 if (_vm->_aniFlag != 1) {
2088 _vm->_aniFlag = 1;
2089 _antCel = 0;
2090 _torchCel = 0;
2091 _pitCel = 0;
2092
2093 _vm->_timers[15]._timer = 16;
2094 _vm->_timers[15]._initTm = 16;
2095 _vm->_timers[15]._flag = 1;
2096
2097 _vm->_timers[13]._timer = 5;
2098 _vm->_timers[13]._initTm = 5;
2099 _vm->_timers[13]._flag = 1;
2100
2101 _vm->_timers[14]._timer = 10;
2102 _vm->_timers[14]._initTm = 10;
2103 _vm->_timers[14]._flag = 1;
2104
2105 _antPos = Common::Point(-40, 123);
2106 _antDieFl = _antEatFl = false;
2107 _stabFl = false;
2108 _pitPos = Common::Point(_vm->_player->_rawPlayer.x, 127);
2109 }
2110
2111 const int *buf = nullptr;
2112 if (_antDieFl) {
2113 buf = Amazon::ANTDIE;
2114 } else if (_antEatFl) {
2115 buf = Amazon::ANTEAT;
2116 } else if (_antPos.x > 120 && _vm->_flags[198] == 1) {
2117 _antEatFl = true;
2118 _vm->_flags[235] = 1;
2119 _antCel = 0;
2120 buf = Amazon::ANTEAT;
2121 } else {
2122 buf = Amazon::ANTWALK;
2123 if (_vm->_inventory->_inv[INV_TORCH]._value == ITEM_IN_INVENTORY)
2124 // Player has burning torch, which scares the Ant
2125 _antDirection = ANT_LEFT;
2126 }
2127
2128 int idx = _antCel;
2129 if (_vm->_timers[15]._flag == 0) {
2130 _vm->_timers[15]._flag = 1;
2131 if (_antDirection == ANT_LEFT) {
2132 if (_antPos.x > 10) {
2133 if (idx == 0)
2134 idx = 36;
2135 else
2136 idx -= 6;
2137
2138 _antPos -= Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]);
2139 _antCel = idx;
2140 }
2141 } else {
2142 idx += 6;
2143 if (buf[(idx / 2)] != -1) {
2144 _antPos += Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]);
2145 _antCel = idx;
2146 } else if (!_antDieFl) {
2147 idx = 0;
2148 _antPos += Common::Point(buf[(idx / 2) + 1], buf[(idx / 2) + 2]);
2149 _antCel = idx;
2150 } else {
2151 idx -= 6;
2152 if (_vm->_flags[200] == 0)
2153 _vm->_flags[200] = 1;
2154 }
2155 }
2156 }
2157
2158 ImageEntry ie;
2159 ie._flags = IMGFLAG_UNSCALED;
2160 ie._spritesPtr = _vm->_objectsTable[61];
2161 ie._frameNumber = buf[(idx / 2)];
2162 ie._position = Common::Point(_antPos.x, _antPos.y);
2163 ie._offsetY = _antPos.y - 70;
2164 _vm->_images.addToList(ie);
2165 _antCel = idx;
2166
2167 if (_vm->_flags[196] != 1) {
2168 idx = _pitCel;
2169 if (_stabFl) {
2170 idx = antHandleStab(idx, buf);
2171 } else {
2172 buf = Amazon::PITWALK;
2173 if (_vm->_timers[13]._flag == 0) {
2174 _vm->_timers[13]._flag = 1;
2175 _vm->_events->pollEvents();
2176 if (_vm->_events->_leftButton) {
2177 // Handle moving the player whilst the mouse button is held down
2178 Common::Point pt = _vm->_events->calcRawMouse();
2179 if (pt.x < _pitPos.x)
2180 idx = antHandleLeft(idx, buf);
2181 else if (pt.x > _pitPos.x)
2182 idx = antHandleRight(idx, buf);
2183 } else {
2184 // Handle movement based on keyboard keys
2185 buf = Amazon::PITWALK;
2186 if (_vm->_player->_move == UP)
2187 idx = antHandleStab(idx, buf);
2188 else if (_vm->_player->_move == LEFT)
2189 idx = antHandleLeft(idx, buf);
2190 else if (_vm->_player->_move == RIGHT)
2191 idx = antHandleRight(idx, buf);
2192 }
2193 }
2194 }
2195 plotPit(idx, buf);
2196 }
2197
2198 if (!_antDieFl) {
2199 int dist = _pitPos.x - _antPos.x;
2200 if ((_antEatFl && (dist <= 45)) || (!_antEatFl && (dist <= 80))) {
2201 _vm->_flags[199] = 1;
2202 _vm->_aniFlag = 0;
2203 }
2204 }
2205 }
2206
synchronize(Common::Serializer & s)2207 void Ant::synchronize(Common::Serializer &s) {
2208 if (_vm->_player->_roomNumber == 61) {
2209 s.syncAsByte(_antDirection);
2210 s.syncAsByte(_pitDirection);
2211 s.syncAsSint16LE(_antCel);
2212 s.syncAsSint16LE(_torchCel);
2213 s.syncAsSint16LE(_pitCel);
2214 s.syncAsSint16LE(_stabCel);
2215 s.syncAsSint16LE(_antPos.x);
2216 s.syncAsSint16LE(_antPos.y);
2217 s.syncAsSint16LE(_pitPos.x);
2218 s.syncAsSint16LE(_pitPos.y);
2219 s.syncAsByte(_antDieFl);
2220 s.syncAsByte(_antEatFl);
2221 s.syncAsByte(_stabFl);
2222 }
2223 }
2224
2225
2226 } // End of namespace Amazon
2227
2228 } // End of namespace Access
2229