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 /*
24 * This code is based on the original source code of Lord Avalot d'Argent version 1.3.
25 * Copyright (c) 1994-1995 Mike, Mark and Thomas Thurman.
26 */
27
28 /* Original name: CELER The unit for updating the screen pics. */
29
30 #include "avalanche/avalanche.h"
31 #include "avalanche/background.h"
32
33 namespace Avalanche {
34
35 const int16 Background::kOnDisk = -1;
36
Background(AvalancheEngine * vm)37 Background::Background(AvalancheEngine *vm) {
38 _vm = vm;
39 _spriteNum = 0;
40 _nextBell = 0;
41 }
42
~Background()43 Background::~Background() {
44 release();
45 }
46
47 /**
48 * @remarks Originally called 'pics_link'
49 */
update()50 void Background::update() {
51 if (_vm->_dropdown->isActive())
52 return; // No animation when the menus are up.
53
54 switch (_vm->_room) {
55 case kRoomOutsideArgentPub:
56 if ((_vm->_roomCycles % 12) == 0)
57 draw(-1, -1, (_vm->_roomCycles / 12) % 4);
58 break;
59 case kRoomBrummieRoad:
60 if ((_vm->_roomCycles % 2) == 0)
61 draw(-1, -1, (_vm->_roomCycles / 2) % 4);
62 break;
63 case kRoomBridge:
64 if ((_vm->_roomCycles % 2) == 0)
65 draw(-1, -1, 3 + (_vm->_roomCycles / 2) % 4);
66 break;
67 case kRoomYours:
68 if ((!_vm->_avvyIsAwake) && ((_vm->_roomCycles % 4) == 0))
69 draw(-1, -1, (_vm->_roomCycles / 12) % 2);
70 break;
71 case kRoomArgentPub:
72 if (((_vm->_roomCycles % 7) == 1) && (_vm->_malagauche != 177)) {
73 // Malagauche cycle.
74 _vm->_malagauche++;
75 switch (_vm->_malagauche) {
76 case 1:
77 case 11:
78 case 21:
79 draw(-1, -1, 11); // Looks forwards.
80 break;
81 case 8:
82 case 18:
83 case 28:
84 case 32:
85 draw(-1, -1, 10); // Looks at you.
86 break;
87 case 30:
88 draw(-1, -1, 12); // Winks.
89 break;
90 case 33:
91 _vm->_malagauche = 0;
92 break;
93 default:
94 break;
95 }
96 }
97
98 switch (_vm->_roomCycles % 200) {
99 case 179:
100 case 197:
101 draw(-1, -1, 4); // Dogfood's drinking cycle.
102 break;
103 case 182:
104 case 194:
105 draw(-1, -1, 5);
106 break;
107 case 185:
108 draw(-1, -1, 6);
109 break;
110 case 199:
111 _vm->_npcFacing = 177; // Impossible value for this.
112 break;
113 default:
114 if (_vm->_roomCycles % 200 <= 178) { // Normally.
115 byte direction = 1;
116 uint16 angle = _vm->bearing(1);
117 if (((angle >= 1) && (angle <= 90)) || ((angle >= 358) && (angle <= 360)))
118 direction = 3;
119 else if ((angle >= 293) && (angle <= 357))
120 direction = 2;
121 else if ((angle >= 270) && (angle <= 292))
122 direction = 4;
123
124 if (direction != _vm->_npcFacing) { // Dogfood.
125 draw(-1, -1, direction - 1);
126 _vm->_npcFacing = direction;
127 }
128 }
129 }
130 break;
131 case kRoomWestHall:
132 if ((_vm->_roomCycles % 3) == 0) {
133 switch ((_vm->_roomCycles / 3) % 6) {
134 case 4:
135 draw(-1, -1, 0);
136 break;
137 case 1:
138 case 3:
139 case 5:
140 draw(-1, -1, 1);
141 break;
142 case 0:
143 case 2:
144 draw(-1, -1, 2);
145 break;
146 default:
147 break;
148 }
149 }
150 break;
151 case kRoomLustiesRoom:
152 if (!(_vm->_lustieIsAsleep)) {
153 byte direction = 0;
154 uint16 angle = _vm->bearing(1);
155 if ((_vm->_roomCycles % 45) > 42)
156 direction = 4; // du Lustie blinks.
157 // Bearing of Avvy from du Lustie.
158 else if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
159 direction = 1; // Middle.
160 else if ((angle >= 45) && (angle <= 180))
161 direction = 2; // Left.
162 else if ((angle >= 181) && (angle <= 314))
163 direction = 3; // Right.
164
165 if (direction != _vm->_npcFacing) { // du Lustie.
166 draw(-1, -1, direction - 1);
167 _vm->_npcFacing = direction;
168 }
169 }
170 break;
171 case kRoomAylesOffice:
172 if ((!_vm->_aylesIsAwake) && (_vm->_roomCycles % 14 == 0)) {
173 switch ((_vm->_roomCycles / 14) % 2) {
174 case 0:
175 draw(-1, -1, 0); // Frame 2: EGA.
176 break;
177 case 1:
178 draw(-1, -1, 2); // Frame 1: Natural.
179 break;
180 default:
181 break;
182 }
183 }
184 break;
185 case kRoomRobins:
186 if (_vm->_tiedUp) {
187 switch (_vm->_roomCycles % 54) {
188 case 20:
189 draw(-1, -1, 3); // Frame 4: Avalot blinks.
190 break;
191 case 23:
192 draw(-1, -1, 1); // Frame 1: Back to normal.
193 break;
194 default:
195 break;
196 }
197 }
198 break;
199 case kRoomNottsPub: {
200 // Bearing of Avvy from Port.
201 byte direction = 0;
202 uint16 angle = _vm->bearing(4);
203 if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
204 direction = 2; // Middle.
205 else if ((angle >= 45) && (angle <= 180))
206 direction = 6; // Left.
207 else if ((angle >= 181) && (angle <= 314))
208 direction = 8; // Right.
209
210 if ((_vm->_roomCycles % 60) > 57)
211 direction--; // Blinks.
212
213 if (direction != _vm->_npcFacing) { // Port.
214 draw(-1, -1, direction - 1);
215 _vm->_npcFacing = direction;
216 }
217
218 switch (_vm->_roomCycles % 50) {
219 case 45 :
220 draw(-1, -1, 8); // Spurge blinks.
221 break;
222 case 49 :
223 draw(-1, -1, 9);
224 break;
225 default:
226 break;
227 }
228 break;
229 }
230 case kRoomDucks: {
231 if ((_vm->_roomCycles % 3) == 0) // The fire flickers.
232 draw(-1, -1, (_vm->_roomCycles / 3) % 3);
233
234 // Bearing of Avvy from Duck.
235 byte direction = 0;
236 uint16 angle = _vm->bearing(1);
237 if ((angle <= 45) || ((angle >= 315) && (angle <= 360)))
238 direction = 4; // Middle.
239 else if ((angle >= 45) && (angle <= 180))
240 direction = 6; // Left.
241 else if ((angle >= 181) && (angle <= 314))
242 direction = 8; // Right.
243
244 if ((_vm->_roomCycles % 45) > 42)
245 direction++; // Duck blinks.
246
247 if (direction != _vm->_npcFacing) { // Duck.
248 draw(-1, -1, direction - 1);
249 _vm->_npcFacing = direction;
250 }
251 break;
252 }
253 default:
254 break;
255 }
256
257 if ((_vm->_bellsAreRinging) && (_vm->getFlag('B'))) {
258 // They're ringing the bells.
259 switch (_vm->_roomCycles % 4) {
260 case 1:
261 if (_nextBell < 5)
262 _nextBell = 12;
263 _nextBell--;
264 // CHECKME: 2 is a guess. No length in the original?
265 _vm->_sound->playNote(_vm->kNotes[_nextBell], 2);
266 break;
267 case 2:
268 _vm->_sound->stopSound();
269 break;
270 default:
271 break;
272 }
273 }
274 }
275
loadSprites(byte number)276 void Background::loadSprites(byte number) {
277 Common::File f;
278 _filename = _filename.format("chunk%d.avd", number);
279 if (!f.open(_filename))
280 return; // We skip because some rooms don't have sprites in the background.
281
282 f.seek(44);
283 _spriteNum = f.readByte();
284 for (int i = 0; i < _spriteNum; i++)
285 _offsets[i] = f.readSint32LE();
286
287 for (int i = 0; i < _spriteNum; i++) {
288 f.seek(_offsets[i]);
289
290 SpriteType sprite;
291 sprite._type = (PictureType)(f.readByte());
292 sprite._x = f.readSint16LE();
293 sprite._y = f.readSint16LE();
294 sprite._width = f.readSint16LE();
295 sprite._height = f.readSint16LE();
296 sprite._size = f.readSint32LE();
297 bool natural = f.readByte();
298 bool memorize = f.readByte();
299
300 if (memorize) {
301 _sprites[i]._x = sprite._x;
302 _sprites[i]._width = sprite._width;
303 _sprites[i]._y = sprite._y;
304 _sprites[i]._height = sprite._height;
305 _sprites[i]._type = sprite._type;
306
307 if (natural)
308 _vm->_graphics->getNaturalPicture(_sprites[i]);
309 else {
310 _sprites[i]._size = sprite._size;
311 _sprites[i]._picture = _vm->_graphics->loadPictureRaw(f, _sprites[i]._width * 8, _sprites[i]._height + 1);
312 }
313 } else
314 _sprites[i]._x = kOnDisk;
315 }
316 f.close();
317 }
318
release()319 void Background::release() {
320 for (int i = 0; i < _spriteNum; i++) {
321 if (_sprites[i]._x > kOnDisk)
322 _sprites[i]._picture.free();
323 }
324 }
325
326 /**
327 * Draw background animation
328 * @remarks Originally called 'show_one'
329 */
draw(int16 destX,int16 destY,byte sprId)330 void Background::draw(int16 destX, int16 destY, byte sprId) {
331 assert(sprId < 40);
332
333 if (_sprites[sprId]._x > kOnDisk) {
334 if (destX < 0) {
335 destX = _sprites[sprId]._x * 8;
336 destY = _sprites[sprId]._y;
337 }
338 drawSprite(destX, destY, _sprites[sprId]);
339 } else {
340 Common::File f;
341 if (!f.open(_filename)) // Filename was set in loadBackgroundSprites().
342 return; // We skip because some rooms don't have sprites in the background.
343
344 f.seek(_offsets[sprId]);
345
346 SpriteType sprite;
347 sprite._type = (PictureType)(f.readByte());
348 sprite._x = f.readSint16LE();
349 sprite._y = f.readSint16LE();
350 sprite._width = f.readSint16LE();
351 sprite._height = f.readSint16LE();
352 sprite._size = f.readSint32LE();
353 f.skip(2); // Natural and Memorize are used in Load()
354 sprite._picture = _vm->_graphics->loadPictureRaw(f, sprite._width * 8, sprite._height + 1);
355
356 if (destX < 0) {
357 destX = sprite._x * 8;
358 destY = sprite._y;
359 }
360 drawSprite(destX, destY, sprite);
361
362 sprite._picture.free();
363 f.close();
364 }
365 }
366
367 /**
368 * @remarks Originally called 'display_it'
369 */
drawSprite(int16 x,int16 y,SpriteType & sprite)370 void Background::drawSprite(int16 x, int16 y, SpriteType &sprite) {
371 // These pictures are practically parts of the background. -10 is for the drop-down menu.
372 _vm->_graphics->drawBackgroundSprite(x, y - 10, sprite);
373 }
374
resetVariables()375 void Background::resetVariables() {
376 _nextBell = 0;
377 }
378
synchronize(Common::Serializer & sz)379 void Background::synchronize(Common::Serializer &sz) {
380 sz.syncAsByte(_nextBell);
381 }
382 } // End of namespace Avalanche.
383