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 "audio/audiostream.h"
24 #include "audio/decoders/wave.h"
25 #include "audio/mixer.h"
26 #include "common/file.h"
27 #include "common/system.h"
28
29 #include "cryomni3d/fixed_image.h"
30
31 #include "cryomni3d/versailles/engine.h"
32
33 namespace CryOmni3D {
34 namespace Versailles {
35
36 static const char *kImagesObjects[] = {
37 "PAMP.gif", // 0: 96
38 "PAPT_2.gif", // 1: 98
39 "PAML.gif", // 2: 101
40 "ESQ1.gif", // 3: 105a, 106b
41 "ESQ2.gif", // 4: 105b, 106c
42 "ESQ3.gif", // 5: 105c
43 "ESQ4.gif", // 6: 105d, 106a, 107a
44 "ESQ4T.gif", // 7: 107b
45 "ESQ4D.gif", // 8: 109
46 "PAMA.gif", // 9: 115
47 "PAMM1.gif", // 10: 118a
48 "PAMM2.gif", // 11: 118b
49 "MEDP.gif", // 12: 121a
50 "MEDP2.gif", // 13: 121b
51 "PAMR1.gif", // 14: 125a
52 "PAMR4.gif", // 15: 125b
53 "EPIL.gif", // 16: 126
54 "PAMG.gif", // 17: 127
55 "PBETE.gif", // 18: 129
56 "VAU2.gif", // 19: 131
57 "VAU3.gif", // 20: 132
58 "GRAV2.gif", // 21: 134
59 "MEM.gif", // 22: 137
60 "VS1.gif", // 23: 138
61 "VS2.gif", // 24: 139
62 "FAB.gif", // 25: 141
63 "LABYR.gif", // 26: 142
64 };
65
setupObjects()66 void CryOmni3DEngine_Versailles::setupObjects() {
67 _objects.reserve(51);
68 #define SET_OBJECT(cursorId, nameId) _objects.push_back(Object(_sprites, cursorId, nameId))
69 #define SET_OBJECT_AND_CB(cursorId, nameId, cb) do { \
70 _objects.push_back(Object(_sprites, cursorId, nameId)); \
71 _objects.back().setViewCallback(new Common::Functor0Mem<void, CryOmni3DEngine_Versailles>(this, &CryOmni3DEngine_Versailles::cb)); \
72 } while (false)
73 #define SET_OBJECT_GENERIC_CB(cursorId, nameId, imageId) SET_OBJECT_AND_CB(cursorId, nameId, genericDisplayObject<imageId>)
74 #define SET_OBJECT_CB(cursorId, nameId) SET_OBJECT_AND_CB(cursorId, nameId, obj_ ## nameId)
75 SET_OBJECT(161, 93); // 0
76 SET_OBJECT(107, 94);
77 SET_OBJECT(69, 95);
78 SET_OBJECT_GENERIC_CB(230, 96, 0);
79 SET_OBJECT(64, 97);
80 SET_OBJECT_GENERIC_CB(250, 98, 1); // 5
81 SET_OBJECT(202, 99);
82 SET_OBJECT(235, 100);
83 SET_OBJECT_GENERIC_CB(167, 101, 2);
84 SET_OBJECT(191, 102);
85 SET_OBJECT(171, 103); // 10
86 SET_OBJECT(47, 104);
87 SET_OBJECT_CB(205, 105);
88 SET_OBJECT_CB(214, 106);
89 SET_OBJECT_CB(6, 107);
90 SET_OBJECT(58, 108); // 15
91 SET_OBJECT_GENERIC_CB(5, 109, 8);
92 SET_OBJECT(38, 110);
93 SET_OBJECT(119, 113);
94 SET_OBJECT(186, 114);
95 SET_OBJECT_GENERIC_CB(246, 115, 9); // 20
96 SET_OBJECT(80, 116);
97 SET_OBJECT(180, 117);
98 SET_OBJECT_CB(34, 118);
99 SET_OBJECT(173, 119);
100 SET_OBJECT(81, 120); // 25
101 SET_OBJECT_CB(156, 121);
102 SET_OBJECT(143, 122);
103 SET_OBJECT(101, 123);
104 SET_OBJECT(204, 124);
105 SET_OBJECT_CB(10, 125); // 30
106 SET_OBJECT_CB(112, 126);
107 SET_OBJECT_GENERIC_CB(90, 127, 17);
108 SET_OBJECT(216, 128);
109 SET_OBJECT_CB(32, 129);
110 SET_OBJECT(37, 130); // 35
111 SET_OBJECT_GENERIC_CB(134, 131, 19);
112 SET_OBJECT_GENERIC_CB(150, 132, 20);
113 SET_OBJECT(28, 133);
114 SET_OBJECT_GENERIC_CB(22, 134, 21);
115 SET_OBJECT(92, 135); // 40
116 SET_OBJECT_GENERIC_CB(16, 137, 22);
117 SET_OBJECT_GENERIC_CB(237, 138, 23);
118 SET_OBJECT_GENERIC_CB(0, 139, 24);
119 SET_OBJECT(31, 140);
120 SET_OBJECT_GENERIC_CB(87, 141, 25); // 45
121 SET_OBJECT_CB(95, 142);
122 SET_OBJECT(115, 136); // Out of order in EXE
123 SET_OBJECT(157, 143);
124 SET_OBJECT(168, 144);
125 SET_OBJECT(65, 145); // 50
126 #undef SET_OBJECT_CB
127 #undef SET_OBJECT_GENERIC_CB
128 #undef SET_OBJECT_AND_CB
129 #undef SET_OBJECT
130 }
131
132 template<uint ID>
genericDisplayObject()133 void CryOmni3DEngine_Versailles::genericDisplayObject() {
134 displayObject(kImagesObjects[ID]);
135 }
136
obj_105()137 void CryOmni3DEngine_Versailles::obj_105() {
138 displayObject(kImagesObjects[3]);
139 displayObject(kImagesObjects[4]);
140 displayObject(kImagesObjects[5]);
141 displayObject(kImagesObjects[6]);
142 }
143
obj_106()144 void CryOmni3DEngine_Versailles::obj_106() {
145 displayObject(kImagesObjects[6]);
146 displayObject(kImagesObjects[3]);
147 displayObject(kImagesObjects[4]);
148 }
149
obj_107()150 void CryOmni3DEngine_Versailles::obj_107() {
151 if (_gameVariables[GameVariables::kSketchState] == 3) {
152 displayObject(kImagesObjects[7]);
153 } else {
154 displayObject(kImagesObjects[6]);
155 }
156 }
157
obj_118()158 void CryOmni3DEngine_Versailles::obj_118() {
159 if (_gameVariables[GameVariables::kDecipherScore]) {
160 displayObject(kImagesObjects[11]);
161 } else {
162 displayObject(kImagesObjects[10]);
163 }
164 }
165
obj_121()166 void CryOmni3DEngine_Versailles::obj_121() {
167 if (_gameVariables[GameVariables::kGotMedalsSolution]) {
168 displayObject(kImagesObjects[13]);
169 } else {
170 displayObject(kImagesObjects[12]);
171 }
172 }
173
obj_125()174 void CryOmni3DEngine_Versailles::obj_125() {
175 if (_gameVariables[GameVariables::kStateLampoonReligion]) {
176 displayObject(kImagesObjects[15]);
177 } else {
178 displayObject(kImagesObjects[14]);
179 }
180 }
181
obj_126()182 void CryOmni3DEngine_Versailles::obj_126() {
183 displayObject(kImagesObjects[16], &CryOmni3DEngine_Versailles::obj_126hk);
184 }
185
obj_126hk(Graphics::ManagedSurface & surface)186 void CryOmni3DEngine_Versailles::obj_126hk(Graphics::ManagedSurface &surface) {
187 Graphics::Surface bmpLetters[28];
188 loadBMPs("bomb_%02d.bmp", bmpLetters, 28);
189
190 drawEpigraphLetters(surface, bmpLetters, _epigraphPassword);
191
192 for (uint i = 0; i < 28; i++) {
193 bmpLetters[i].free();
194 }
195
196 if (_messages.size() <= 148) {
197 return;
198 }
199
200 Common::String &translation = _messages[148];
201
202 if (translation.size() == 0) {
203 return;
204 }
205
206 _fontManager.setCurrentFont(1);
207 _fontManager.setTransparentBackground(true);
208 _fontManager.setForeColor(0);
209 _fontManager.setSurface(&surface);
210 _fontManager.displayStr(9, 424, translation);
211 }
212
obj_129()213 void CryOmni3DEngine_Versailles::obj_129() {
214 displayObject(kImagesObjects[18], &CryOmni3DEngine_Versailles::obj_129hk);
215 }
216
obj_129hk(Graphics::ManagedSurface & surface)217 void CryOmni3DEngine_Versailles::obj_129hk(Graphics::ManagedSurface &surface) {
218 if (_messages.size() <= 149) {
219 return;
220 }
221
222 Common::String &translation = _messages[149];
223
224 if (translation.size() == 0) {
225 return;
226 }
227
228 surface.fillRect(Common::Rect(0, 455, 640, 480), 247);
229
230 _fontManager.setCurrentFont(8);
231 _fontManager.setTransparentBackground(true);
232 _fontManager.setForeColor(242);
233 _fontManager.setSurface(&surface);
234 _fontManager.displayStr(10, 460, translation);
235 }
236
obj_142()237 void CryOmni3DEngine_Versailles::obj_142() {
238 // Display a marker only when in maze
239 if (_currentLevel == 6 && _currentPlaceId >= 14 && _currentPlaceId <= 44) {
240 displayObject(kImagesObjects[26], &CryOmni3DEngine_Versailles::obj_142hk);
241 } else {
242 displayObject(kImagesObjects[26]);
243 }
244 }
245
obj_142hk(Graphics::ManagedSurface & surface)246 void CryOmni3DEngine_Versailles::obj_142hk(Graphics::ManagedSurface &surface) {
247 const Common::Point markers[] = {
248 Common::Point(135, 403), // 14
249 Common::Point(136, 321), // 15
250 Common::Point(225, 109),
251 Common::Point(441, 88),
252 Common::Point(505, 78),
253 Common::Point(550, 82),
254 Common::Point(479, 242), // 20
255 Common::Point(529, 333),
256 Common::Point(466, 407),
257 Common::Point(359, 411),
258 Common::Point(305, 415),
259 Common::Point(217, 405), // 25
260 Common::Point(216, 325),
261 Common::Point(280, 378),
262 Common::Point(340, 313),
263 Common::Point(282, 313),
264 Common::Point(253, 285), // 30
265 Common::Point(225, 258),
266 Common::Point(154, 255),
267 Common::Point(219, 188),
268 Common::Point(294, 251),
269 Common::Point(341, 242), // 35
270 Common::Point(308, 206),
271 Common::Point(270, 172),
272 Common::Point(363, 161),
273 Common::Point(416, 201),
274 Common::Point(513, 195), // 40
275 Common::Point(412, 311),
276 Common::Point(446, 280),
277 Common::Point(377, 347),
278 Common::Point(448, 356),
279 };
280
281 uint id = _currentPlaceId - 14;
282 assert(id < ARRAYSIZE(markers));
283
284 /*
285 _fontManager.setSurface(&surface);
286 _fontManager.setCurrentFont(4);
287 _fontManager.setTransparentBackground(true);
288 _fontManager.setForeColor(241);
289 for(id = 0; id < ARRAYSIZE(markers); id++) {
290 */
291 // Why - 20? Ask to game creators, it's like that in the code
292 uint spriteX = markers[id].x - _sprites.getCursor(4).getWidth() / 2 - 20;
293 uint spriteY = markers[id].y - _sprites.getCursor(4).getHeight() / 2;
294 surface.transBlitFrom(_sprites.getSurface(4), Common::Point(spriteX, spriteY),
295 _sprites.getKeyColor(4));
296 /*
297 _fontManager.displayInt(markers[id].x - 10, markers[id].y, id + 14);
298 }
299 */
300 }
301
302 // This array contains images for all paintings it must be kept in sync with _paintingsTitles
303 static const char *kImagesPaintings[] = {
304 "10E_1.GIF", // 0: 41201
305 nullptr, // 1: 41202
306 "10E_3.GIF", // 2: 41203
307 "10E_4.GIF", // 3: 41204
308 "10E_5.GIF", // 4: 41205
309 "10D_1.GIF", // 5: 41301
310 "10D_2.GIF", // 6: 41302
311 "20C_1.GIF", // 7: 42401
312 "20G_11.GIF", // 8: 42901
313 "20G_12.GIF", // 9: 42902
314 "20G_13.GIF", // 10: 42903
315 "20G_14.GIF", // 11: 42904
316 "20G_15.GIF", // 12: 42905
317 "20G_16.GIF", // 13: 42906
318 "20G_21.GIF", // 14: 42907
319 "20G_22.GIF", // 15: 42908
320 "20G_23.GIF", // 16: 42909
321 "20G_31.GIF", // 17: 42910
322 "20G_32.GIF", // 18: 42911
323 "20G_33.GIF", // 19: 42912
324 "20G_34.GIF", // 20: 42913
325 "20G_35.GIF", // 21: 42914
326 "20G_36.GIF", // 22: 42915
327 "30N_1.GIF", // 23: 43090
328 "30N_2.GIF", // 24: 43091
329 "30N_3.GIF", // 25: 43092
330 "30O_1.GIF", // 26: 43100
331 "30O_2.GIF", // 27: 43101
332 "30O_31.GIF", // 28: 43102
333 "30O_32.GIF", // 29: 43103
334 "30O_33.GIF", // 30: 43104
335 "30M_1.GIF", // 31: 43130
336 "30M_2.GIF", // 32: 43131
337 "30M_3.GIF", // 33: 43132
338 "30L_11.GIF", // 34: 43140
339 "30L_12.GIF", // 35: 43141
340 "30L_21.GIF", // 36: 43142
341 nullptr, // 37: 43143
342 "30L_32.GIF", // 38: 43144
343 "30J_11.GIF", // 39: 43150
344 "30J_12.GIF", // 40: 43151
345 "30J_13.GIF", // 41: 43152
346 "30J_21.GIF", // 42: 43153
347 "30J_22.GIF", // 43: 43154
348 "30J_31.GIF", // 44: 43155
349 "30J_32.GIF", // 45: 43156
350 "30J_33.GIF", // 46: 43157
351 "51A_1.GIF", // 47: 45260
352 // Now let's put dumb images, those without description and any special action, they are not synced with _paintingsTitles
353 "30Q_1.GIF", // 48: 43060
354 "30Q_2.GIF", // 49: 43061
355 "DUC.GIF", // 50: 46001
356 "COQ.GIF", // 51: 46002
357 "CHAT.GIF", // 52: 46003
358 "DRAGON.GIF", // 53: 46004
359 "GRUE.GIF", // 54: 46005
360 "RENARD.GIF", // 55: 46006
361 "POULE.GIF", // 56: 46007
362 "LOUP.GIF", // 57: 46008
363 "MILAN.GIF", // 58: 46009
364 "GRENOU.GIF", // 59: 46010
365 "AIGLE.GIF", // 60: 46011
366 "SOURIS.GIF", // 61: 46012
367 "CYGNE.GIF", // 62: 46013 and 46440
368 "LOUPTETE.GIF", // 63: 46014
369 "CANNES.GIF", // 64: 46015
370 };
371
372 // Setup array for all see actions
setupImgScripts()373 void CryOmni3DEngine_Versailles::setupImgScripts() {
374 // First all paintings to keep it simple for counting
375 #define SET_SCRIPT_BY_ID(id) _imgScripts[id] = &CryOmni3DEngine_Versailles::img_ ## id
376 #define SET_SCRIPT_BY_PAINTING(id, image) _imgScripts[id] = &CryOmni3DEngine_Versailles::genericPainting<image>
377 SET_SCRIPT_BY_PAINTING(41201, 0);
378 SET_SCRIPT_BY_ID(41202);
379 SET_SCRIPT_BY_PAINTING(41203, 2);
380 SET_SCRIPT_BY_PAINTING(41204, 3);
381 SET_SCRIPT_BY_PAINTING(41205, 4);
382 SET_SCRIPT_BY_PAINTING(41301, 5);
383 SET_SCRIPT_BY_PAINTING(41302, 6);
384 SET_SCRIPT_BY_PAINTING(42401, 7);
385 SET_SCRIPT_BY_PAINTING(42901, 8);
386 SET_SCRIPT_BY_PAINTING(42902, 9);
387 SET_SCRIPT_BY_PAINTING(42903, 10);
388 SET_SCRIPT_BY_PAINTING(42904, 11);
389 SET_SCRIPT_BY_PAINTING(42905, 12);
390 SET_SCRIPT_BY_PAINTING(42906, 13);
391 SET_SCRIPT_BY_PAINTING(42907, 14);
392 SET_SCRIPT_BY_PAINTING(42908, 15);
393 SET_SCRIPT_BY_PAINTING(42909, 16);
394 SET_SCRIPT_BY_PAINTING(42910, 17);
395 SET_SCRIPT_BY_PAINTING(42911, 18);
396 SET_SCRIPT_BY_PAINTING(42912, 19);
397 SET_SCRIPT_BY_PAINTING(42913, 20);
398 SET_SCRIPT_BY_PAINTING(42914, 21);
399 SET_SCRIPT_BY_PAINTING(42915, 22);
400 SET_SCRIPT_BY_PAINTING(43090, 23);
401 SET_SCRIPT_BY_PAINTING(43091, 24);
402 SET_SCRIPT_BY_PAINTING(43092, 25);
403 SET_SCRIPT_BY_PAINTING(43100, 26);
404 SET_SCRIPT_BY_PAINTING(43101, 27);
405 SET_SCRIPT_BY_PAINTING(43102, 28);
406 SET_SCRIPT_BY_PAINTING(43103, 29);
407 SET_SCRIPT_BY_PAINTING(43104, 30);
408 SET_SCRIPT_BY_PAINTING(43130, 31);
409 SET_SCRIPT_BY_PAINTING(43131, 32);
410 SET_SCRIPT_BY_PAINTING(43132, 33);
411 SET_SCRIPT_BY_PAINTING(43140, 34);
412 SET_SCRIPT_BY_PAINTING(43141, 35);
413 SET_SCRIPT_BY_PAINTING(43142, 36);
414 SET_SCRIPT_BY_ID(43143);
415 SET_SCRIPT_BY_PAINTING(43144, 38);
416 SET_SCRIPT_BY_PAINTING(43150, 39);
417 SET_SCRIPT_BY_PAINTING(43151, 40);
418 SET_SCRIPT_BY_PAINTING(43152, 41);
419 SET_SCRIPT_BY_PAINTING(43153, 42);
420 SET_SCRIPT_BY_PAINTING(43154, 43);
421 SET_SCRIPT_BY_PAINTING(43155, 44);
422 SET_SCRIPT_BY_PAINTING(43156, 45);
423 SET_SCRIPT_BY_PAINTING(43157, 46);
424 SET_SCRIPT_BY_PAINTING(45260, 47);
425 #undef SET_SCRIPT_BY_PAINTING
426 // From now dumb images (like paintings but without interrogation mark handling)
427 #define SET_SCRIPT_BY_DUMB(id, image) _imgScripts[id] = &CryOmni3DEngine_Versailles::genericDumbImage<image>
428 SET_SCRIPT_BY_DUMB(43060, 48);
429 SET_SCRIPT_BY_DUMB(43061, 49);
430 SET_SCRIPT_BY_DUMB(46001, 50);
431 SET_SCRIPT_BY_DUMB(46002, 51);
432 SET_SCRIPT_BY_DUMB(46003, 52);
433 SET_SCRIPT_BY_DUMB(46004, 53);
434 SET_SCRIPT_BY_DUMB(46005, 54);
435 SET_SCRIPT_BY_DUMB(46006, 55);
436 SET_SCRIPT_BY_DUMB(46007, 56);
437 SET_SCRIPT_BY_DUMB(46008, 57);
438 SET_SCRIPT_BY_DUMB(46009, 58);
439 SET_SCRIPT_BY_DUMB(46010, 59);
440 SET_SCRIPT_BY_DUMB(46011, 60);
441 SET_SCRIPT_BY_DUMB(46012, 61);
442 SET_SCRIPT_BY_DUMB(46013, 62);
443 SET_SCRIPT_BY_DUMB(46014, 63);
444 SET_SCRIPT_BY_DUMB(46015, 64);
445 SET_SCRIPT_BY_DUMB(46440, 62); // Same as 46013
446 #undef SET_SCRIPT_BY_DUMB
447 // From now specific handlers for anything that is not a painting
448 SET_SCRIPT_BY_ID(41801);
449 SET_SCRIPT_BY_ID(41802);
450 SET_SCRIPT_BY_ID(43145);
451 SET_SCRIPT_BY_ID(43146);
452 SET_SCRIPT_BY_ID(43160);
453 SET_SCRIPT_BY_ID(43190);
454 SET_SCRIPT_BY_ID(44071);
455 SET_SCRIPT_BY_ID(44161);
456 SET_SCRIPT_BY_ID(45130);
457 SET_SCRIPT_BY_ID(45270);
458 SET_SCRIPT_BY_ID(45280);
459 SET_SCRIPT_BY_ID(88001);
460 SET_SCRIPT_BY_ID(88002);
461 SET_SCRIPT_BY_ID(88003);
462 SET_SCRIPT_BY_ID(88004);
463 #undef SET_SCRIPT_BY_ID
464 }
465
466 // Generic handler for dumb fixed images
467 template<uint ID>
genericDumbImage(ZonFixedImage * fimg)468 void CryOmni3DEngine_Versailles::genericDumbImage(ZonFixedImage *fimg) {
469 fimg->load(kImagesPaintings[ID]);
470 while (1) {
471 fimg->manage();
472 if (fimg->_exit || fimg->_zoneLow) {
473 fimg->_exit = true;
474 break;
475 }
476 }
477 }
478
479 // Generic handler for interrogation mark action: display the painting title
480 #define HANDLE_QUESTION(ID) \
481 do { \
482 if (fimg->_zoneQuestion) { \
483 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), _paintingsTitles[ID], Common::Point(600, 400), \
484 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage)); \
485 } \
486 } while (false)
487
488 // Generic handler for paintings fixed images
489 template<uint ID>
genericPainting(ZonFixedImage * fimg)490 void CryOmni3DEngine_Versailles::genericPainting(ZonFixedImage *fimg) {
491 fimg->load(kImagesPaintings[ID]);
492 while (1) {
493 fimg->manage();
494 if (fimg->_exit || fimg->_zoneLow) {
495 fimg->_exit = true;
496 break;
497 }
498 HANDLE_QUESTION(ID);
499 }
500 }
501
502 // Specific fixed images callbacks
503 #define IMG_CB(name) void CryOmni3DEngine_Versailles::img_ ## name(ZonFixedImage *fimg)
504
505 IMG_CB(31101) {
506 fimg->load("21F_11.GIF");
507 while (1) {
508 fimg->manage();
509 if (fimg->_exit || fimg->_zoneLow) {
510 fimg->_exit = true;
511 break;
512 }
513 if (fimg->_zoneUse) {
514 if (fimg->_currentZone == 0) {
515 // Collect key and change image
516 collectObject(104, fimg);
517 _gameVariables[GameVariables::kCollectKey] = 1;
518 ZonFixedImage::CallbackFunctor *functor =
519 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
520 &CryOmni3DEngine_Versailles::img_31101b);
521 fimg->changeCallback(functor);
522 break;
523 } else if (fimg->_currentZone == 1 && !_inventory.inInventoryByNameID(103)) {
524 collectObject(103, fimg);
525 }
526 }
527 }
528 }
529
530 IMG_CB(31101b) {
531 fimg->load("21F_10.GIF");
532 if (_inventory.inInventoryByNameID(103)) {
533 fimg->disableZone(1);
534 }
535 while (1) {
536 fimg->manage();
537 if (fimg->_exit || fimg->_zoneLow) {
538 fimg->_exit = true;
539 break;
540 }
541 if (fimg->_zoneUse && !_inventory.inInventoryByNameID(103)) {
542 collectObject(103, fimg);
543 // Original game resets callback with this one, this is useless
544 break;
545 }
546 }
547 }
548
549 IMG_CB(31142) {
550 fimg->load("10D2_4.GIF");
551 while (1) {
552 fimg->manage();
553 if (fimg->_exit || fimg->_zoneLow) {
554 fimg->_exit = true;
555 break;
556 }
557 if (fimg->_zoneUse) {
558 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 7,
559 fimg->getZoneCenter(fimg->_currentZone),
560 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
561 }
562 }
563 }
564
565 IMG_CB(31142b) {
566 fimg->load("11D2_2.GIF");
567 while (1) {
568 fimg->manage();
569 if (fimg->_exit || fimg->_zoneLow) {
570 fimg->_exit = true;
571 break;
572 }
573 if (fimg->_zoneUse) {
574 if (_gameVariables[GameVariables::kCollectScissors] || _inventory.inInventoryByNameID(94)) {
575 // Empty drawer
576 ZonFixedImage::CallbackFunctor *functor =
577 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
578 &CryOmni3DEngine_Versailles::img_31142d);
579 fimg->changeCallback(functor);
580 break;
581 } else {
582 // Drawer with scissors in it
583 ZonFixedImage::CallbackFunctor *functor =
584 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
585 &CryOmni3DEngine_Versailles::img_31142c);
586 fimg->changeCallback(functor);
587 break;
588 }
589 }
590 }
591 }
592
593 IMG_CB(31142c) {
594 fimg->load("11D2_21.GIF");
595 while (1) {
596 fimg->manage();
597 if (fimg->_exit || fimg->_zoneLow) {
598 fimg->_exit = true;
599 break;
600 }
601 if (fimg->_zoneUse) {
602 if (!_inventory.inInventoryByNameID(94) && !_gameVariables[GameVariables::kCollectScissors]) {
603 collectObject(94, fimg);
604 }
605 _gameVariables[GameVariables::kCollectScissors] = 1;
606 // Display empty drawer
607 ZonFixedImage::CallbackFunctor *functor =
608 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
609 &CryOmni3DEngine_Versailles::img_31142d);
610 fimg->changeCallback(functor);
611 break;
612 }
613 }
614 }
615
616 IMG_CB(31142d) {
617 fimg->load("11D2_22.GIF");
618 while (1) {
619 fimg->manage();
620 if (fimg->_exit || fimg->_zoneLow) {
621 fimg->_exit = true;
622 break;
623 }
624 if (fimg->_zoneUse) {
625 // Close drawer
626 ZonFixedImage::CallbackFunctor *functor =
627 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
628 &CryOmni3DEngine_Versailles::img_31142b);
629 fimg->changeCallback(functor);
630 break;
631 }
632 }
633 }
634
635 IMG_CB(31143) {
636 fimg->load("10D2_3.GIF");
637 while (1) {
638 fimg->manage();
639 if (fimg->_exit || fimg->_zoneLow) {
640 fimg->_exit = true;
641 break;
642 }
643 if (fimg->_zoneUse) {
644 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 7,
645 fimg->getZoneCenter(fimg->_currentZone),
646 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
647 }
648 }
649 }
650
651 IMG_CB(31143b) {
652 fimg->load("11D2_1.GIF");
653 while (1) {
654 fimg->manage();
655 if (fimg->_exit || fimg->_zoneLow) {
656 fimg->_exit = true;
657 break;
658 }
659 if (fimg->_zoneUse) {
660 if (_inventory.inInventoryByNameID(96)) {
661 // Empty drawer
662 ZonFixedImage::CallbackFunctor *functor =
663 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
664 &CryOmni3DEngine_Versailles::img_31143d);
665 fimg->changeCallback(functor);
666 break;
667 } else {
668 // Drawer with pamphlet about arts in it
669 ZonFixedImage::CallbackFunctor *functor =
670 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
671 &CryOmni3DEngine_Versailles::img_31143c);
672 fimg->changeCallback(functor);
673 break;
674 }
675 }
676 }
677 }
678
679 IMG_CB(31143c) {
680 fimg->load("11D2_11.GIF");
681 while (1) {
682 fimg->manage();
683 if (fimg->_exit || fimg->_zoneLow) {
684 fimg->_exit = true;
685 break;
686 }
687 if (fimg->_zoneUse) {
688 if (!_inventory.inInventoryByNameID(96)) {
689 collectObject(96, fimg);
690 }
691 // Display empty drawer
692 ZonFixedImage::CallbackFunctor *functor =
693 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
694 &CryOmni3DEngine_Versailles::img_31143d);
695 fimg->changeCallback(functor);
696 break;
697 }
698 }
699 }
700
701 IMG_CB(31143d) {
702 fimg->load("11D2_12.GIF");
703 while (1) {
704 fimg->manage();
705 if (fimg->_exit || fimg->_zoneLow) {
706 fimg->_exit = true;
707 break;
708 }
709 if (fimg->_zoneUse) {
710 // Close drawer
711 ZonFixedImage::CallbackFunctor *functor =
712 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
713 &CryOmni3DEngine_Versailles::img_31143b);
714 fimg->changeCallback(functor);
715 break;
716 }
717 }
718 }
719
720 IMG_CB(32120) {
721 if (currentGameTime() != 3) {
722 fimg->_exit = true;
723 return;
724 }
725
726 // Already painted
727 if (_gameVariables[GameVariables::kSketchState] == 3 ||
728 _gameVariables[GameVariables::kSketchState] == 4) {
729 fimg->_exit = true;
730 return;
731 }
732
733 fimg->load("23I_10.GIF");
734 while (1) {
735 fimg->manage();
736 if (fimg->_exit || fimg->_zoneLow) {
737 fimg->_exit = true;
738 _sprites.replaceSpriteColor(59, 254, 244);
739 _sprites.replaceSpriteColor(63, 254, 247);
740 break;
741 }
742 if (fimg->_zoneUse) {
743 if (fimg->_currentZone == 0 && !_inventory.inInventoryByIconID(38)) {
744 // Pick the brush
745 Object *obj = _objects.findObjectByIconID(38);
746 collectObject(obj, fimg);
747 // collectObject animates the cursor
748 // Make it selected
749 _inventory.setSelectedObject(obj);
750 setCursor(obj->idSA()); // 59 in original game
751 fimg->_zonesMode = ZonFixedImage::kZonesMode_Object;
752 }
753 } else if (fimg->_usedObject && fimg->_usedObject->idCA() == 38) {
754 // Brush used
755 if (fimg->_currentZone == 1) { // on gold paint
756 _inventory.removeByIconID(38);
757 Object *obj = _objects.findObjectByIconID(38);
758 obj->rename(111); // Brush has gold on it
759 setMainPaletteColor(254, 128, 128, 0);
760 _sprites.replaceSpriteColor(59, 244, 254);
761 _sprites.replaceSpriteColor(63, 247, 254);
762 // Collect only there once we set the color on the cursors
763 collectObject(obj, fimg);
764 _inventory.setSelectedObject(obj);
765 setCursor(obj->idSA()); // 59 in original game
766 fimg->_zonesMode = ZonFixedImage::kZonesMode_Object;
767 _gameVariables[GameVariables::kBrushColor] = 1;
768 } else if (fimg->_currentZone == 2) { // on red paint
769 _inventory.removeByIconID(38);
770 Object *obj = _objects.findObjectByIconID(38);
771 obj->rename(112); // Brush has red on it
772 setMainPaletteColor(254, 128, 0, 0);
773 _sprites.replaceSpriteColor(59, 244, 254);
774 _sprites.replaceSpriteColor(63, 247, 254);
775 // Collect only there once we set the color on the cursors
776 collectObject(obj, fimg);
777 _inventory.setSelectedObject(obj);
778 setCursor(obj->idSA()); // 59 in original game
779 fimg->_zonesMode = ZonFixedImage::kZonesMode_Object;
780 _gameVariables[GameVariables::kBrushColor] = 2;
781 } else if (fimg->_currentZone == 3) { // on sketch
782 if (fimg->_usedObject->idOBJ() == 111 &&
783 _gameVariables[GameVariables::kBrushColor] == 1) {
784 // Gold brush used on sketch
785 _gameVariables[GameVariables::kSketchState] = 3;
786 playInGameVideo("23I_11");
787 // Force reload of the place
788 if (_nextPlaceId == uint(-1)) {
789 _nextPlaceId = _currentPlaceId;
790 }
791 _inventory.removeByIconID(38);
792 ZonFixedImage::CallbackFunctor *functor =
793 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
794 &CryOmni3DEngine_Versailles::img_32120b);
795 fimg->changeCallback(functor);
796 break;
797 } else if (fimg->_usedObject->idOBJ() == 112 &&
798 _gameVariables[GameVariables::kBrushColor] == 2) {
799 // Red brush used on sketch
800 _gameVariables[GameVariables::kSketchState] = 4;
801 playInGameVideo("23I_12");
802 // Force reload of the place
803 if (_nextPlaceId == uint(-1)) {
804 _nextPlaceId = _currentPlaceId;
805 }
806 _inventory.removeByIconID(38);
807 ZonFixedImage::CallbackFunctor *functor =
808 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
809 &CryOmni3DEngine_Versailles::img_32120c);
810 fimg->changeCallback(functor);
811 break;
812 }
813 }
814 }
815 }
816 }
817
818 IMG_CB(32120b) {
819 fimg->load("23I_11.GIF");
820 while (1) {
821 fimg->manage();
822 if (fimg->_exit || fimg->_zoneUse) {
823 fimg->_exit = true;
824 break;
825 }
826 }
827 _inventory.removeByNameID(107);
828 collectObject(107, fimg);
829
830 _sprites.replaceSpriteColor(59, 254, 244);
831 _sprites.replaceSpriteColor(63, 254, 247);
832
833 setGameTime(4, 2);
834 }
835
836 IMG_CB(32120c) {
837 fimg->load("23I_12.GIF");
838 while (1) {
839 fimg->manage();
840 if (fimg->_exit || fimg->_zoneUse) {
841 fimg->_exit = true;
842 break;
843 }
844 }
845 _inventory.removeByNameID(107);
846 collectObject(109, fimg);
847
848 _sprites.replaceSpriteColor(59, 254, 244);
849 _sprites.replaceSpriteColor(63, 254, 247);
850
851 setGameTime(4, 2);
852 }
853
854 IMG_CB(32201) {
855 fimg->load("21E_41.GIF");
856 while (1) {
857 fimg->manage();
858 if (fimg->_exit || fimg->_zoneLow) {
859 fimg->_exit = true;
860 break;
861 }
862 // There is a check of use but only to change sound path
863 // That must be a leftover
864 /*
865 if (fimg->_zoneUse) {
866 }
867 */
868 }
869 }
870
871 IMG_CB(32202) {
872 fimg->load("21E_42.GIF");
873 while (1) {
874 fimg->manage();
875 if (fimg->_exit || fimg->_zoneLow) {
876 fimg->_exit = true;
877 break;
878 }
879 }
880 }
881
882 IMG_CB(32203) {
883 fimg->load("21E_43.GIF");
884 while (1) {
885 fimg->manage();
886 if (fimg->_exit || fimg->_zoneLow) {
887 fimg->_exit = true;
888 break;
889 }
890 // There is a check of use but only to change sound path
891 // That must be a leftover
892 /*
893 if (fimg->_zoneUse) {
894 }
895 */
896 }
897 }
898
899 IMG_CB(32204) {
900 fimg->load("21E_44.GIF");
901 while (1) {
902 fimg->manage();
903 if (fimg->_exit || fimg->_zoneLow) {
904 fimg->_exit = true;
905 break;
906 }
907 if (fimg->_zoneUse && !_inventory.inInventoryByNameID(105)) {
908 // Collect portfolio
909 collectObject(105, fimg);
910 _gameVariables[GameVariables::kSketchState] = 1;
911 _gameVariables[GameVariables::kCollectPortfolio] = 1;
912
913 ZonFixedImage::CallbackFunctor *functor =
914 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
915 &CryOmni3DEngine_Versailles::img_32204b);
916 fimg->changeCallback(functor);
917 break;
918 }
919 }
920 }
921
922 IMG_CB(32204b) {
923 fimg->load("21E_45.GIF");
924 while (1) {
925 fimg->manage();
926 if (fimg->_exit || fimg->_zoneLow) {
927 fimg->_exit = true;
928 break;
929 }
930 }
931 }
932
933 IMG_CB(34131) {
934 fimg->load("43ZA_1.GIF");
935 while (1) {
936 fimg->manage();
937 if (fimg->_exit || fimg->_zoneLow) {
938 fimg->_exit = true;
939 break;
940 }
941 }
942 }
943
944 IMG_CB(34132) {
945 fimg->load("43ZB_2.GIF");
946 while (1) {
947 fimg->manage();
948 if (fimg->_exit || fimg->_zoneLow) {
949 fimg->_exit = true;
950 break;
951 }
952 }
953 }
954
955 IMG_CB(34172) {
956 playInGameVideo("43X3_10");
957 // Force reload of the place
958 if (_nextPlaceId == uint(-1)) {
959 _nextPlaceId = _currentPlaceId;
960 }
961 fimg->_exit = true;
962 }
963
964 IMG_CB(34173) {
965 fimg->load("43X3_2.GIF");
966 while (1) {
967 fimg->manage();
968 if (fimg->_exit || fimg->_zoneLow) {
969 fimg->_exit = true;
970 break;
971 }
972 if (fimg->_zoneUse) {
973 // WORKAROUND: The video doesn't exist there is only a fixed image unused in original game. We will use it.
974 /*
975 playInGameVideo("43X3_21");
976 // Force reload of the place
977 if (_nextPlaceId == uint(-1)) {
978 _nextPlaceId = _currentPlaceId;
979 }
980 */
981
982 ZonFixedImage::CallbackFunctor *functor =
983 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
984 &CryOmni3DEngine_Versailles::img_34173b);
985 fimg->changeCallback(functor);
986 break;
987 }
988 }
989 }
990
991 // WORKAROUND: In original game an empty clickable drawer is displayed
992 // Happily for them, when you click on an area and change zones, the next zone
993 // under the cursor get activated too (fixed in fixed_image.cpp). So you don't
994 // see what happens. You just get the reminder and see the empty drawer.
995 IMG_CB(34173b) {
996 // 43X3_21 doesn't have a ZON file, use the one of 43X3_22
997 fimg->load("43X3_21.GIF", "43X3_22.ZON");
998 while (1) {
999 fimg->manage();
1000 if (fimg->_exit || fimg->_zoneLow) {
1001 fimg->_exit = true;
1002 break;
1003 }
1004 if (fimg->_zoneUse && !_inventory.inInventoryByNameID(129)) {
1005 // Collect reminder
1006 collectObject(129, fimg);
1007 setGameTime(3, 4);
1008
1009 ZonFixedImage::CallbackFunctor *functor =
1010 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1011 &CryOmni3DEngine_Versailles::img_34173c);
1012 fimg->changeCallback(functor);
1013 break;
1014 }
1015 }
1016 }
1017
1018 IMG_CB(34173c) {
1019 fimg->load("43X3_22.GIF");
1020 // WORKAROUND: Drawer is empty, just disable the use zone
1021 fimg->disableZone(0);
1022 while (1) {
1023 fimg->manage();
1024 if (fimg->_exit || fimg->_zoneLow) {
1025 fimg->_exit = true;
1026 break;
1027 }
1028 }
1029 }
1030
1031 IMG_CB(34174) {
1032 fimg->load("43X3_42.GIF");
1033 while (1) {
1034 fimg->manage();
1035 if (fimg->_exit || fimg->_zoneLow) {
1036 fimg->_exit = true;
1037 break;
1038 }
1039 if (fimg->_zoneUse) {
1040 // Open the door
1041 ZonFixedImage::CallbackFunctor *functor =
1042 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1043 &CryOmni3DEngine_Versailles::img_34174b);
1044 fimg->changeCallback(functor);
1045 break;
1046 }
1047 }
1048 }
1049
1050 IMG_CB(34174b) {
1051 // Door is open but safe is closed
1052 fimg->load("43X3_40.GIF");
1053 while (1) {
1054 fimg->manage();
1055 if (fimg->_exit || fimg->_zoneLow) {
1056 fimg->_exit = true;
1057 break;
1058 }
1059 if (fimg->_zoneUse) {
1060 if (_gameVariables[GameVariables::kSafeUnlocked]) {
1061 // Open the safe
1062 ZonFixedImage::CallbackFunctor *functor =
1063 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1064 &CryOmni3DEngine_Versailles::img_34174c);
1065 fimg->changeCallback(functor);
1066 break;
1067 }
1068 _dialogsMan["{JOUEUR-ALLER-BUREAU-LOUVOIS}"] = 'Y';
1069 if (handleSafe(fimg)) {
1070 // Unlocked the safe
1071 _gameVariables[GameVariables::kSafeUnlocked] = 1;
1072 _dialogsMan["{JOUEUR-ALLER-BUREAU-LOUVOIS}"] = 'N';
1073 // Open it
1074 ZonFixedImage::CallbackFunctor *functor =
1075 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1076 &CryOmni3DEngine_Versailles::img_34174c);
1077 fimg->changeCallback(functor);
1078 break;
1079 }
1080 // If failed to solve: just display this image again
1081 break;
1082 }
1083 }
1084 }
1085
1086 IMG_CB(34174c) {
1087 // Dispatch to the correct state
1088 if (_gameVariables[GameVariables::kCollectVaubanBlueprint1] &&
1089 _gameVariables[GameVariables::kCollectVaubanBlueprint2]) {
1090 // Safe is empty
1091 ZonFixedImage::CallbackFunctor *functor =
1092 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1093 &CryOmni3DEngine_Versailles::img_34174f);
1094 fimg->changeCallback(functor);
1095 return;
1096 }
1097 if (!_gameVariables[GameVariables::kCollectVaubanBlueprint1] &&
1098 _gameVariables[GameVariables::kCollectVaubanBlueprint2] == 1) {
1099 // Blueprint 1 is there not the 2nd one
1100 ZonFixedImage::CallbackFunctor *functor =
1101 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1102 &CryOmni3DEngine_Versailles::img_34174e);
1103 fimg->changeCallback(functor);
1104 return;
1105 }
1106 if (_gameVariables[GameVariables::kCollectVaubanBlueprint1] &&
1107 !_gameVariables[GameVariables::kCollectVaubanBlueprint2]) {
1108 // Blueprint 2 is there not the 1st one
1109 ZonFixedImage::CallbackFunctor *functor =
1110 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1111 &CryOmni3DEngine_Versailles::img_34174d);
1112 fimg->changeCallback(functor);
1113 return;
1114 }
1115
1116 playInGameVideo("cofouv");
1117 // Force reload of the place
1118 if (_nextPlaceId == uint(-1)) {
1119 _nextPlaceId = _currentPlaceId;
1120 }
1121
1122 // Safe has both blueprints
1123 fimg->load("43X3_30.GIF");
1124 while (1) {
1125 fimg->manage();
1126 if (fimg->_exit || fimg->_zoneLow) {
1127 fimg->_exit = true;
1128 break;
1129 }
1130 if (fimg->_zoneUse) {
1131 if (fimg->_currentZone == 0) {
1132 // Collect 1st blueprint
1133 collectObject(131, fimg);
1134 _dialogsMan["{JOUEUR-TROUVE-PLANS-VAUBAN}"] = 'Y';
1135 _gameVariables[GameVariables::kCollectVaubanBlueprint1] = 1;
1136
1137 ZonFixedImage::CallbackFunctor *functor =
1138 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1139 &CryOmni3DEngine_Versailles::img_34174d);
1140 fimg->changeCallback(functor);
1141 break;
1142 } else if (fimg->_currentZone == 1) {
1143 // Collect 2nd blueprint
1144 collectObject(132, fimg);
1145 _gameVariables[GameVariables::kCollectVaubanBlueprint2] = 1;
1146
1147 ZonFixedImage::CallbackFunctor *functor =
1148 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1149 &CryOmni3DEngine_Versailles::img_34174e);
1150 fimg->changeCallback(functor);
1151 break;
1152 }
1153 }
1154 }
1155 }
1156
1157 IMG_CB(34174d) {
1158 // Safe has only blueprint 2
1159 fimg->load("43X3_43.GIF");
1160 while (1) {
1161 fimg->manage();
1162 if (fimg->_exit || fimg->_zoneLow) {
1163 fimg->_exit = true;
1164 break;
1165 }
1166 if (fimg->_zoneUse) {
1167 // Collect 2nd blueprint
1168 collectObject(132, fimg);
1169 _gameVariables[GameVariables::kCollectVaubanBlueprint2] = 1;
1170
1171 ZonFixedImage::CallbackFunctor *functor =
1172 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1173 &CryOmni3DEngine_Versailles::img_34174f);
1174 fimg->changeCallback(functor);
1175 break;
1176 }
1177 }
1178 }
1179
1180 IMG_CB(34174e) {
1181 // Safe has only blueprint 1
1182 fimg->load("43X3_41.GIF");
1183 while (1) {
1184 fimg->manage();
1185 if (fimg->_exit || fimg->_zoneLow) {
1186 fimg->_exit = true;
1187 break;
1188 }
1189 if (fimg->_zoneUse) {
1190 // Collect 1st blueprint
1191 collectObject(131, fimg);
1192 _dialogsMan["{JOUEUR-TROUVE-PLANS-VAUBAN}"] = 'Y';
1193 _gameVariables[GameVariables::kCollectVaubanBlueprint1] = 1;
1194
1195 ZonFixedImage::CallbackFunctor *functor =
1196 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1197 &CryOmni3DEngine_Versailles::img_34174f);
1198 fimg->changeCallback(functor);
1199 break;
1200 }
1201 }
1202 }
1203
1204 IMG_CB(34174f) {
1205 // Safe is empty
1206 fimg->load("43X3_45.GIF");
1207 while (1) {
1208 fimg->manage();
1209 if (fimg->_exit || fimg->_zoneLow) {
1210 fimg->_exit = true;
1211 break;
1212 }
1213 if (fimg->_zoneUse) {
1214 // Close safe
1215 ZonFixedImage::CallbackFunctor *functor =
1216 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1217 &CryOmni3DEngine_Versailles::img_34174b);
1218 fimg->changeCallback(functor);
1219 break;
1220 }
1221 }
1222 }
1223
handleSafe(ZonFixedImage * fimg)1224 bool CryOmni3DEngine_Versailles::handleSafe(ZonFixedImage *fimg) {
1225 bool success = false;
1226 Common::RandomSource rnd("VersaillesSafe");
1227 Graphics::Surface bmpDigits[10];
1228 unsigned char safeDigits[kSafeDigitsCount];
1229 Graphics::ManagedSurface tempSurf;
1230
1231 loadBMPs("coff_%02d.bmp", bmpDigits, 10);
1232 for (uint i = 0; i < kSafeDigitsCount; i++) {
1233 safeDigits[i] = rnd.getRandomNumber(9);
1234 }
1235
1236 fimg->load("43x3_cof.GIF");
1237 const Graphics::Surface *fimgSurface = fimg->surface();
1238 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
1239 tempSurf.blitFrom(*fimgSurface);
1240 drawSafeDigits(tempSurf, bmpDigits, safeDigits);
1241 fimg->updateSurface(&tempSurf.rawSurface());
1242
1243 while (1) {
1244 fimg->manage();
1245 if (fimg->_exit || fimg->_zoneLow) {
1246 break;
1247 }
1248 if (fimg->_zoneUse) {
1249 if (fimg->_currentZone == 15) {
1250 // Safe handle
1251
1252 // Animate handle
1253 playInGameVideo("43x3_poi");
1254 // Force reload of the place
1255 if (_nextPlaceId == uint(-1)) {
1256 _nextPlaceId = _currentPlaceId;
1257 }
1258
1259 // Redraw our safe image
1260 fimg->display();
1261
1262 if (checkSafeDigits(safeDigits)) {
1263 success = true;
1264 break;
1265 }
1266 } else if (fimg->_currentZone < kSafeDigitsCount) {
1267 // Safe digit
1268 safeDigits[fimg->_currentZone] = (safeDigits[fimg->_currentZone] + 1) % 10;
1269 // Reset the surface and redraw digits on it
1270 tempSurf.blitFrom(*fimgSurface);
1271 drawSafeDigits(tempSurf, bmpDigits, safeDigits);
1272 fimg->updateSurface(&tempSurf.rawSurface());
1273
1274 waitMouseRelease();
1275 }
1276 }
1277 }
1278
1279 for (uint i = 0; i < 10; i++) {
1280 bmpDigits[i].free();
1281 }
1282 return success;
1283 }
1284
1285 const uint16 CryOmni3DEngine_Versailles::kSafeDigitsX[] = { 267, 318, 370, 421 };
1286 const uint16 CryOmni3DEngine_Versailles::kSafeDigitsY[] = { 148, 230, 311 };
1287
drawSafeDigits(Graphics::ManagedSurface & surface,const Graphics::Surface (& bmpDigits)[10],const unsigned char (& safeDigits)[kSafeDigitsCount])1288 void CryOmni3DEngine_Versailles::drawSafeDigits(Graphics::ManagedSurface &surface,
1289 const Graphics::Surface(&bmpDigits)[10], const unsigned char (&safeDigits)[kSafeDigitsCount]) {
1290 for (uint i = 0; i < ARRAYSIZE(safeDigits); i++) {
1291 const Graphics::Surface &digit = bmpDigits[safeDigits[i]];
1292 Common::Point dst(kSafeDigitsX[i % 4], kSafeDigitsY[i / 4]);
1293 surface.transBlitFrom(digit, dst);
1294 }
1295 }
1296
1297 const char *CryOmni3DEngine_Versailles::kSafeDates[] = { "1643", "1668", "1674" };
checkSafeDigits(unsigned char (& safeDigits)[kSafeDigitsCount])1298 bool CryOmni3DEngine_Versailles::checkSafeDigits(unsigned char (&safeDigits)[kSafeDigitsCount]) {
1299 uint dateChecked;
1300 for (dateChecked = 0; dateChecked < ARRAYSIZE(kSafeDates); dateChecked++) {
1301 const char *checkDate = kSafeDates[dateChecked];
1302 // Find the date in one of safe digits lines
1303 uint line;
1304 for (line = 0; line < kSafeDigitsCount; line += 4) {
1305 uint digit;
1306 for (digit = 0; digit < 4; digit++) {
1307 if (safeDigits[line + digit] != checkDate[digit] - '0') {
1308 break;
1309 }
1310 }
1311 if (digit == 4) {
1312 // Check was a success: go to next date
1313 break;
1314 }
1315 // Failure: try next line
1316 }
1317 if (line >= kSafeDigitsCount) {
1318 // All lines were tested and none had the date: failure
1319 return false;
1320 }
1321 }
1322 // All dates were found
1323 return true;
1324 }
1325
1326 IMG_CB(41202) {
1327 fimg->load("10E_20.GIF");
1328 while (1) {
1329 fimg->manage();
1330 if (fimg->_exit || fimg->_zoneLow) {
1331 fimg->_exit = true;
1332 break;
1333 }
1334 HANDLE_QUESTION(1);
1335 if (fimg->_zoneUse) {
1336 if (fimg->_currentZone == 2 && !_inventory.inInventoryByNameID(97)) {
1337 // Open the jar
1338 ZonFixedImage::CallbackFunctor *functor =
1339 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1340 &CryOmni3DEngine_Versailles::img_41202b);
1341 fimg->changeCallback(functor);
1342 break;
1343 } else {
1344 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 11,
1345 fimg->getZoneCenter(fimg->_currentZone),
1346 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1347 }
1348 }
1349 }
1350 }
1351
1352 IMG_CB(41202b) {
1353 fimg->load("10E_21.GIF");
1354 while (1) {
1355 fimg->manage();
1356 if (fimg->_exit) {
1357 break;
1358 }
1359 HANDLE_QUESTION(1);
1360 if (fimg->_zoneLow) {
1361 // Go back to jars closed
1362 ZonFixedImage::CallbackFunctor *functor =
1363 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1364 &CryOmni3DEngine_Versailles::img_41202);
1365 fimg->changeCallback(functor);
1366 break;
1367 }
1368 if (fimg->_zoneUse) {
1369 if (!_inventory.inInventoryByNameID(97)) {
1370 collectObject(97, fimg);
1371 }
1372 // Go back to jars closed
1373 ZonFixedImage::CallbackFunctor *functor =
1374 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1375 &CryOmni3DEngine_Versailles::img_41202);
1376 fimg->changeCallback(functor);
1377 break;
1378 }
1379 }
1380 }
1381
1382 IMG_CB(41801) {
1383 fimg->load("12E2_10.GIF");
1384 while (1) {
1385 fimg->manage();
1386 if (fimg->_exit || fimg->_zoneLow) {
1387 fimg->_exit = true;
1388 break;
1389 }
1390 if (fimg->_currentZone == 0) {
1391 bool open = false;
1392 if (fimg->_zoneUse) {
1393 // Using without object
1394 if (_gameVariables[GameVariables::kUsedScissors]) {
1395 open = true;
1396 } else {
1397 // Closed
1398 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 8,
1399 fimg->getZoneCenter(fimg->_currentZone),
1400 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1401 }
1402 } else if (fimg->_usedObject && fimg->_usedObject->idOBJ() == 94) {
1403 _gameVariables[GameVariables::kUsedScissors] = 1;
1404 _inventory.removeByNameID(94);
1405 open = true;
1406 }
1407 if (open) {
1408 if (_gameVariables[GameVariables::kCollectedPaperInTrunk]) {
1409 // Display empty trunk
1410 ZonFixedImage::CallbackFunctor *functor =
1411 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1412 &CryOmni3DEngine_Versailles::img_41801c);
1413 fimg->changeCallback(functor);
1414 break;
1415 } else {
1416 // Display trunk with paper in it
1417 // Animate opening
1418 playInGameVideo("12E2_11");
1419 // Force reload of the place
1420 if (_nextPlaceId == uint(-1)) {
1421 _nextPlaceId = _currentPlaceId;
1422 }
1423
1424 ZonFixedImage::CallbackFunctor *functor =
1425 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1426 &CryOmni3DEngine_Versailles::img_41801b);
1427 fimg->changeCallback(functor);
1428 break;
1429 }
1430 }
1431 }
1432 }
1433 }
1434
1435 IMG_CB(41801b) {
1436 fimg->load("12E2_11.GIF");
1437 while (1) {
1438 fimg->manage();
1439 if (fimg->_exit) {
1440 break;
1441 }
1442 if (fimg->_zoneLow) {
1443 // Animate closing
1444 playInGameVideo("12E2_13");
1445 // Force reload of the place
1446 if (_nextPlaceId == uint(-1)) {
1447 _nextPlaceId = _currentPlaceId;
1448 }
1449 fimg->_exit = true;
1450 break;
1451 }
1452 if (fimg->_zoneUse) {
1453 if (!_inventory.inInventoryByNameID(100)) {
1454 collectObject(100, fimg);
1455 }
1456 _gameVariables[GameVariables::kCollectedPaperInTrunk] = 1;
1457
1458 // Go to empty trunk
1459 ZonFixedImage::CallbackFunctor *functor =
1460 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1461 &CryOmni3DEngine_Versailles::img_41801c);
1462 fimg->changeCallback(functor);
1463 break;
1464 }
1465 }
1466 }
1467
1468 IMG_CB(41801c) {
1469 fimg->load("12E2_12.GIF");
1470 while (1) {
1471 fimg->manage();
1472 if (fimg->_exit) {
1473 break;
1474 }
1475 if (fimg->_zoneLow) {
1476 // Animate closing
1477 playInGameVideo("12E2_13");
1478 // Force reload of the place
1479 if (_nextPlaceId == uint(-1)) {
1480 _nextPlaceId = _currentPlaceId;
1481 }
1482 fimg->_exit = true;
1483 break;
1484 }
1485 }
1486 }
1487
1488 IMG_CB(41802) {
1489 // Dispatch to the correct state
1490 if (_gameVariables[GameVariables::kInkSpilled] &&
1491 !_gameVariables[GameVariables::kCollectedPaperOnTable]) {
1492 // Draw paper with ink on it
1493 ZonFixedImage::CallbackFunctor *functor =
1494 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1495 &CryOmni3DEngine_Versailles::img_41802b);
1496 fimg->changeCallback(functor);
1497 return;
1498 }
1499 if (!_gameVariables[GameVariables::kInkSpilled] &&
1500 _gameVariables[GameVariables::kCollectedPaperOnTable]) {
1501 // Draw table with ink in inkpot and without paper
1502 ZonFixedImage::CallbackFunctor *functor =
1503 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1504 &CryOmni3DEngine_Versailles::img_41802c);
1505 fimg->changeCallback(functor);
1506 return;
1507 }
1508 if (_gameVariables[GameVariables::kInkSpilled] &&
1509 _gameVariables[GameVariables::kCollectedPaperOnTable]) {
1510 // Draw table with ink directly on table
1511 ZonFixedImage::CallbackFunctor *functor =
1512 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1513 &CryOmni3DEngine_Versailles::img_41802d);
1514 fimg->changeCallback(functor);
1515 return;
1516 }
1517
1518 // There we have paper on table and ink is in its inkpot
1519 fimg->load("12E2_20.GIF");
1520 while (1) {
1521 fimg->manage();
1522 if (fimg->_exit || fimg->_zoneLow) {
1523 fimg->_exit = true;
1524 break;
1525 }
1526 if (fimg->_zoneUse && fimg->_currentZone == 1) {
1527 // Collected paper
1528 collectObject(95, fimg);
1529 _gameVariables[GameVariables::kCollectedPaperOnTable] = 1;
1530 setPlaceState(8, 1);
1531 // Draw table with ink in inkpot and without paper
1532 ZonFixedImage::CallbackFunctor *functor =
1533 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1534 &CryOmni3DEngine_Versailles::img_41802c);
1535 fimg->changeCallback(functor);
1536 break;
1537 }
1538 if (fimg->_zoneUse && fimg->_currentZone == 2) {
1539 _gameVariables[GameVariables::kInkSpilled] = 1;
1540 setPlaceState(8, 3);
1541 // Draw paper with ink on it
1542 ZonFixedImage::CallbackFunctor *functor =
1543 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1544 &CryOmni3DEngine_Versailles::img_41802b);
1545 fimg->changeCallback(functor);
1546 break;
1547 }
1548 if (fimg->_usedObject && fimg->_currentZone == 0) {
1549 uint objID = fimg->_usedObject->idOBJ();
1550 if (objID == 100) {
1551 playInGameVideo("12E2_24");
1552 // Force reload of the place
1553 if (_nextPlaceId == uint(-1)) {
1554 _nextPlaceId = _currentPlaceId;
1555 }
1556 _inventory.removeByNameID(100);
1557 // Revealed paper
1558 collectObject(98, fimg);
1559 _gameVariables[GameVariables::kGotRevealedPaper] = 1;
1560 setGameTime(3, 1);
1561 } else if (objID == 96) {
1562 // Lampoon about arts
1563 playInGameVideo("PAP-BRUL");
1564 // Force reload of the place
1565 if (_nextPlaceId == uint(-1)) {
1566 _nextPlaceId = _currentPlaceId;
1567 }
1568 doGameOver();
1569 }
1570 }
1571 }
1572 }
1573
1574 IMG_CB(41802b) {
1575 // There we have paper on table with ink on it
1576 fimg->load("12E2_21.GIF");
1577 while (1) {
1578 fimg->manage();
1579 if (fimg->_exit || fimg->_zoneLow) {
1580 fimg->_exit = true;
1581 break;
1582 }
1583 if (fimg->_zoneUse && fimg->_currentZone == 1) {
1584 // Collected paper with ink on it
1585 collectObject(99, fimg);
1586 _gameVariables[GameVariables::kCollectedPaperOnTable] = 1;
1587 setPlaceState(8, 2);
1588 // Draw table with ink spilled and without paper
1589 ZonFixedImage::CallbackFunctor *functor =
1590 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1591 &CryOmni3DEngine_Versailles::img_41802d);
1592 fimg->changeCallback(functor);
1593 break;
1594 }
1595 if (fimg->_usedObject && fimg->_currentZone == 0) {
1596 uint objID = fimg->_usedObject->idOBJ();
1597 if (objID == 100) {
1598 playInGameVideo("12E2_24");
1599 // Force reload of the place
1600 if (_nextPlaceId == uint(-1)) {
1601 _nextPlaceId = _currentPlaceId;
1602 }
1603 _inventory.removeByNameID(100);
1604 // Revealed paper
1605 collectObject(98, fimg);
1606 _gameVariables[GameVariables::kGotRevealedPaper] = 1;
1607 setGameTime(3, 1);
1608 } else if (objID == 96) {
1609 // Lampoon about arts
1610 playInGameVideo("PAP-BRUL");
1611 // Force reload of the place
1612 if (_nextPlaceId == uint(-1)) {
1613 _nextPlaceId = _currentPlaceId;
1614 }
1615 doGameOver();
1616 }
1617 }
1618 }
1619 }
1620
1621 IMG_CB(41802c) {
1622 // There we have ink in inkpot and without paper
1623 fimg->load("12E2_22.GIF");
1624 while (1) {
1625 fimg->manage();
1626 if (fimg->_exit || fimg->_zoneLow) {
1627 fimg->_exit = true;
1628 break;
1629 }
1630 if (fimg->_zoneUse && fimg->_currentZone == 1) {
1631 _gameVariables[GameVariables::kInkSpilled] = 1;
1632 setPlaceState(8, 2);
1633 // Draw table with ink on it
1634 ZonFixedImage::CallbackFunctor *functor =
1635 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1636 &CryOmni3DEngine_Versailles::img_41802d);
1637 fimg->changeCallback(functor);
1638 break;
1639 }
1640 if (fimg->_usedObject && fimg->_currentZone == 0) {
1641 uint objID = fimg->_usedObject->idOBJ();
1642 if (objID == 100) {
1643 playInGameVideo("12E2_24");
1644 // Force reload of the place
1645 if (_nextPlaceId == uint(-1)) {
1646 _nextPlaceId = _currentPlaceId;
1647 }
1648 _inventory.removeByNameID(100);
1649 // Revealed paper
1650 collectObject(98, fimg);
1651 _gameVariables[GameVariables::kGotRevealedPaper] = 1;
1652 setGameTime(3, 1);
1653 } else if (objID == 96) {
1654 // Lampoon about arts
1655 playInGameVideo("PAP-BRUL");
1656 // Force reload of the place
1657 if (_nextPlaceId == uint(-1)) {
1658 _nextPlaceId = _currentPlaceId;
1659 }
1660 doGameOver();
1661 }
1662 }
1663 }
1664 }
1665
1666 IMG_CB(41802d) {
1667 // There we have ink directly on table
1668 fimg->load("12E2_23.GIF");
1669 while (1) {
1670 fimg->manage();
1671 if (fimg->_exit || fimg->_zoneLow) {
1672 fimg->_exit = true;
1673 break;
1674 }
1675 if (fimg->_usedObject && fimg->_currentZone == 0) {
1676 uint objID = fimg->_usedObject->idOBJ();
1677 if (objID == 100) {
1678 playInGameVideo("12E2_24");
1679 // Force reload of the place
1680 if (_nextPlaceId == uint(-1)) {
1681 _nextPlaceId = _currentPlaceId;
1682 }
1683 _inventory.removeByNameID(100);
1684 // Revealed paper
1685 collectObject(98, fimg);
1686 _gameVariables[GameVariables::kGotRevealedPaper] = 1;
1687 setGameTime(3, 1);
1688 } else if (objID == 96) {
1689 // Lampoon about arts
1690 playInGameVideo("PAP-BRUL");
1691 // Force reload of the place
1692 if (_nextPlaceId == uint(-1)) {
1693 _nextPlaceId = _currentPlaceId;
1694 }
1695 doGameOver();
1696 }
1697 }
1698 }
1699 }
1700
1701 IMG_CB(43143) {
1702 // Lampoon is there: display it
1703 if (!_gameVariables[GameVariables::kCollectLampoonArchitecture] &&
1704 (_currentLevel == 5 || currentGameTime() >= 3)) {
1705 ZonFixedImage::CallbackFunctor *functor =
1706 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1707 &CryOmni3DEngine_Versailles::img_43143b);
1708 fimg->changeCallback(functor);
1709 return;
1710 }
1711
1712 fimg->load("30L_31.GIF");
1713 while (1) {
1714 fimg->manage();
1715 if (fimg->_exit || fimg->_zoneLow) {
1716 fimg->_exit = true;
1717 break;
1718 }
1719 HANDLE_QUESTION(37);
1720 }
1721 }
1722
1723 IMG_CB(43143b) {
1724 fimg->load("30L_3101.GIF");
1725 while (1) {
1726 fimg->manage();
1727 if (fimg->_exit || fimg->_zoneLow) {
1728 fimg->_exit = true;
1729 break;
1730 }
1731 HANDLE_QUESTION(37);
1732 if (fimg->_zoneUse) {
1733 // Paper is out of reach
1734 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 16,
1735 fimg->getZoneCenter(fimg->_currentZone),
1736 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1737 } else if (fimg->_usedObject && fimg->_usedObject->idOBJ() == 119 && fimg->_currentZone == 0) {
1738 _inventory.removeByNameID(119);
1739 collectLampoonArchitecture(fimg);
1740 // Display without the lampoon
1741 ZonFixedImage::CallbackFunctor *functor =
1742 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1743 &CryOmni3DEngine_Versailles::img_43143);
1744 fimg->changeCallback(functor);
1745 break;
1746 }
1747 }
1748 }
1749
1750 IMG_CB(43145) {
1751 fimg->load("30L_50.GIF");
1752 while (1) {
1753 fimg->manage();
1754 if (fimg->_exit || fimg->_zoneLow) {
1755 fimg->_exit = true;
1756 break;
1757 }
1758 if (fimg->_zoneUse) {
1759 if (fimg->_currentZone == 0) {
1760 playInGameVideo("30L_51");
1761 // Force reload of the place
1762 if (_nextPlaceId == uint(-1)) {
1763 _nextPlaceId = _currentPlaceId;
1764 }
1765
1766 ZonFixedImage::CallbackFunctor *functor =
1767 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1768 &CryOmni3DEngine_Versailles::img_43145b);
1769 fimg->changeCallback(functor);
1770 break;
1771 } else if (fimg->_currentZone == 1) {
1772 playInGameVideo("30L_52");
1773 // Force reload of the place
1774 if (_nextPlaceId == uint(-1)) {
1775 _nextPlaceId = _currentPlaceId;
1776 }
1777
1778 ZonFixedImage::CallbackFunctor *functor =
1779 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1780 &CryOmni3DEngine_Versailles::img_43145c);
1781 fimg->changeCallback(functor);
1782 break;
1783 }
1784 }
1785 }
1786 }
1787
1788 IMG_CB(43145b) {
1789 fimg->load("30L_51.GIF");
1790 while (1) {
1791 fimg->manage();
1792 if (fimg->_exit) {
1793 break;
1794 }
1795 if (fimg->_zoneLow) {
1796 // Go back to drawer closed
1797 ZonFixedImage::CallbackFunctor *functor =
1798 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1799 &CryOmni3DEngine_Versailles::img_43145);
1800 fimg->changeCallback(functor);
1801 break;
1802 }
1803 if (fimg->_zoneUse) {
1804 if (_gameVariables[GameVariables::kCabinetDrawerStatus] == 1) {
1805 // Small key 2 has been put in it and not yet picked by us
1806 collectObject(116, fimg);
1807 _gameVariables[GameVariables::kCabinetDrawerStatus] = 2;
1808 } else {
1809 // Drawer is empty
1810 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 3,
1811 fimg->getZoneCenter(fimg->_currentZone),
1812 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1813 }
1814 }
1815 }
1816 }
1817
1818 IMG_CB(43145c) {
1819 fimg->load("30L_52.GIF");
1820 while (1) {
1821 fimg->manage();
1822 if (fimg->_exit) {
1823 break;
1824 }
1825 if (fimg->_zoneLow) {
1826 // Go back to drawer closed
1827 ZonFixedImage::CallbackFunctor *functor =
1828 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1829 &CryOmni3DEngine_Versailles::img_43145);
1830 fimg->changeCallback(functor);
1831 break;
1832 }
1833 if (fimg->_zoneUse) {
1834 // Drawer is empty
1835 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 3,
1836 fimg->getZoneCenter(fimg->_currentZone),
1837 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1838 }
1839 }
1840 }
1841
1842 IMG_CB(43146) {
1843 fimg->load("30L_40.GIF");
1844 while (1) {
1845 fimg->manage();
1846 if (fimg->_exit || fimg->_zoneLow) {
1847 fimg->_exit = true;
1848 break;
1849 }
1850 if (fimg->_zoneUse) {
1851 if (fimg->_currentZone == 0) {
1852 playInGameVideo("30L_41");
1853 // Force reload of the place
1854 if (_nextPlaceId == uint(-1)) {
1855 _nextPlaceId = _currentPlaceId;
1856 }
1857
1858 ZonFixedImage::CallbackFunctor *functor =
1859 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1860 &CryOmni3DEngine_Versailles::img_43146b);
1861 fimg->changeCallback(functor);
1862 break;
1863 } else if (fimg->_currentZone == 1) {
1864 playInGameVideo("30L_42");
1865 // Force reload of the place
1866 if (_nextPlaceId == uint(-1)) {
1867 _nextPlaceId = _currentPlaceId;
1868 }
1869
1870 ZonFixedImage::CallbackFunctor *functor =
1871 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1872 &CryOmni3DEngine_Versailles::img_43146c);
1873 fimg->changeCallback(functor);
1874 break;
1875 }
1876 }
1877 }
1878 }
1879
1880 IMG_CB(43146b) {
1881 fimg->load("30L_41.GIF");
1882 while (1) {
1883 fimg->manage();
1884 if (fimg->_exit) {
1885 break;
1886 }
1887 if (fimg->_zoneLow) {
1888 // Go back to drawer closed
1889 ZonFixedImage::CallbackFunctor *functor =
1890 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1891 &CryOmni3DEngine_Versailles::img_43146);
1892 fimg->changeCallback(functor);
1893 break;
1894 }
1895 if (fimg->_zoneUse) {
1896 // Drawer is empty
1897 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 3,
1898 fimg->getZoneCenter(fimg->_currentZone),
1899 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1900 }
1901 }
1902 }
1903
1904 IMG_CB(43146c) {
1905 fimg->load("30L_42.GIF");
1906 while (1) {
1907 fimg->manage();
1908 if (fimg->_exit) {
1909 break;
1910 }
1911 if (fimg->_zoneLow) {
1912 // Go back to drawer closed
1913 ZonFixedImage::CallbackFunctor *functor =
1914 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1915 &CryOmni3DEngine_Versailles::img_43146);
1916 fimg->changeCallback(functor);
1917 break;
1918 }
1919 if (fimg->_zoneUse) {
1920 // Drawer is empty
1921 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 3,
1922 fimg->getZoneCenter(fimg->_currentZone),
1923 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
1924 }
1925 }
1926 }
1927
1928 IMG_CB(43160) {
1929 // Dispatch to the correct state
1930 bool inInvCharcoal = _inventory.inInventoryByNameID(113);
1931 bool inInvPaper = _inventory.inInventoryByNameID(114);
1932 if (inInvCharcoal && inInvPaper) {
1933 // When everything is collected, state of place change and we shouldn't be able to look at the table
1934 error("BUG: Shouldn't be here");
1935 } else if (inInvCharcoal && !inInvPaper) {
1936 // Draw table with paper but without charcoal
1937 ZonFixedImage::CallbackFunctor *functor =
1938 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1939 &CryOmni3DEngine_Versailles::img_43160b);
1940 fimg->changeCallback(functor);
1941 return;
1942 } else if (!inInvCharcoal && inInvPaper) {
1943 // Draw table with charcoal but without paper
1944 ZonFixedImage::CallbackFunctor *functor =
1945 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1946 &CryOmni3DEngine_Versailles::img_43160c);
1947 fimg->changeCallback(functor);
1948 return;
1949 }
1950
1951 // There we have charcoal and paper on table
1952 fimg->load("31I01.GIF");
1953 while (1) {
1954 fimg->manage();
1955 if (fimg->_exit || fimg->_zoneLow) {
1956 fimg->_exit = true;
1957 break;
1958 }
1959 if (fimg->_zoneUse) {
1960 if (fimg->_currentZone == 0) {
1961 // Collected charcoal
1962 collectObject(113, fimg);
1963 // Draw table with paper but without charcoal
1964 ZonFixedImage::CallbackFunctor *functor =
1965 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1966 &CryOmni3DEngine_Versailles::img_43160b);
1967 fimg->changeCallback(functor);
1968 break;
1969 } else if (fimg->_currentZone == 1) {
1970 // Collected paper
1971 collectObject(114, fimg);
1972 // Draw table with charcoal but without paper
1973 ZonFixedImage::CallbackFunctor *functor =
1974 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1975 &CryOmni3DEngine_Versailles::img_43160c);
1976 fimg->changeCallback(functor);
1977 break;
1978 }
1979 }
1980 }
1981 }
1982
1983 IMG_CB(43160b) {
1984 // There we have paper on table but without charcoal
1985 fimg->load("31I02.GIF");
1986 while (1) {
1987 fimg->manage();
1988 if (fimg->_exit) {
1989 break;
1990 }
1991 if (fimg->_zoneUse) {
1992 // Collected paper
1993 collectObject(114, fimg);
1994 // Draw table empty
1995 ZonFixedImage::CallbackFunctor *functor =
1996 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
1997 &CryOmni3DEngine_Versailles::img_43160d);
1998 fimg->changeCallback(functor);
1999 break;
2000 }
2001 }
2002 }
2003
2004 IMG_CB(43160c) {
2005 // There we have charcoal on table but without paper
2006 fimg->load("31I03.GIF");
2007 while (1) {
2008 fimg->manage();
2009 if (fimg->_exit) {
2010 break;
2011 }
2012 if (fimg->_zoneUse) {
2013 // Collected charcoal
2014 collectObject(113, fimg);
2015 // Draw table empty
2016 ZonFixedImage::CallbackFunctor *functor =
2017 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2018 &CryOmni3DEngine_Versailles::img_43160d);
2019 fimg->changeCallback(functor);
2020 break;
2021 }
2022 }
2023 }
2024
2025 IMG_CB(43160d) {
2026 // There we have neither charcoal nor paper on table
2027 fimg->load("31I04.GIF");
2028 setPlaceState(16, 1);
2029 while (1) {
2030 fimg->manage();
2031 if (fimg->_exit || fimg->_zoneLow) {
2032 fimg->_exit = true;
2033 break;
2034 }
2035 }
2036 }
2037
2038 IMG_CB(43190) {
2039 fimg->load("31L1_20.GIF");
2040 if (_gameVariables[GameVariables::kCollectScore]) {
2041 fimg->disableZone(0);
2042 }
2043 while (1) {
2044 fimg->manage();
2045 if (fimg->_exit || fimg->_zoneLow) {
2046 fimg->_exit = true;
2047 break;
2048 }
2049 if (fimg->_zoneUse) {
2050 playInGameVideo("31L1_2A");
2051 // Force reload of the place
2052 if (_nextPlaceId == uint(-1)) {
2053 _nextPlaceId = _currentPlaceId;
2054 }
2055 ZonFixedImage::CallbackFunctor *functor =
2056 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2057 &CryOmni3DEngine_Versailles::img_43190b);
2058 fimg->changeCallback(functor);
2059 break;
2060 }
2061 }
2062 }
2063
2064 IMG_CB(43190b) {
2065 fimg->load("31L1_20B.GIF");
2066 while (1) {
2067 fimg->manage();
2068 if (fimg->_exit || fimg->_zoneLow) {
2069 fimg->_exit = true;
2070 break;
2071 }
2072 if (fimg->_zoneUse) {
2073 playInGameVideo("31L1_2B");
2074 // Force reload of the place
2075 if (_nextPlaceId == uint(-1)) {
2076 _nextPlaceId = _currentPlaceId;
2077 }
2078 ZonFixedImage::CallbackFunctor *functor =
2079 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2080 &CryOmni3DEngine_Versailles::img_43190c);
2081 fimg->changeCallback(functor);
2082 break;
2083 }
2084 }
2085 }
2086
2087 IMG_CB(43190c) {
2088 fimg->load("31L1_20C.GIF");
2089 while (1) {
2090 fimg->manage();
2091 if (fimg->_exit || fimg->_zoneLow) {
2092 fimg->_exit = true;
2093 break;
2094 }
2095 if (fimg->_zoneUse) {
2096 playInGameVideo("31L1_2C");
2097 // Force reload of the place
2098 if (_nextPlaceId == uint(-1)) {
2099 _nextPlaceId = _currentPlaceId;
2100 }
2101 ZonFixedImage::CallbackFunctor *functor =
2102 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2103 &CryOmni3DEngine_Versailles::img_43190d);
2104 fimg->changeCallback(functor);
2105 break;
2106 }
2107 }
2108 }
2109
2110 IMG_CB(43190d) {
2111 fimg->load("31L1_20D.GIF");
2112 while (1) {
2113 fimg->manage();
2114 if (fimg->_exit || fimg->_zoneLow) {
2115 fimg->_exit = true;
2116 break;
2117 }
2118 if (fimg->_zoneUse) {
2119 playInGameVideo("31L1_2D");
2120 // Force reload of the place
2121 if (_nextPlaceId == uint(-1)) {
2122 _nextPlaceId = _currentPlaceId;
2123 }
2124 ZonFixedImage::CallbackFunctor *functor =
2125 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2126 &CryOmni3DEngine_Versailles::img_43190e);
2127 fimg->changeCallback(functor);
2128 break;
2129 }
2130 }
2131 }
2132
2133 IMG_CB(43190e) {
2134 fimg->load("31L1_20E.GIF");
2135 while (1) {
2136 fimg->manage();
2137 if (fimg->_exit || fimg->_zoneLow) {
2138 fimg->_exit = true;
2139 break;
2140 }
2141 if (fimg->_zoneUse) {
2142 ZonFixedImage::CallbackFunctor *functor =
2143 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2144 &CryOmni3DEngine_Versailles::img_43190f);
2145 fimg->changeCallback(functor);
2146 break;
2147 }
2148 }
2149 }
2150
2151 IMG_CB(43190f) {
2152 fimg->load("31L1_22.GIF");
2153 while (1) {
2154 fimg->manage();
2155 if (fimg->_exit) {
2156 break;
2157 }
2158 if (fimg->_zoneUse) {
2159 _gameVariables[GameVariables::kCollectScore] = 1;
2160 collectObject(118, fimg);
2161 fimg->_exit = true;
2162 break;
2163 }
2164 }
2165 }
2166
2167 IMG_CB(44071) {
2168 // Dispatch to the correct state
2169 if (_gameVariables[GameVariables::kCollectFood]) {
2170 // Draw plate with less food
2171 ZonFixedImage::CallbackFunctor *functor =
2172 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2173 &CryOmni3DEngine_Versailles::img_44071b);
2174 fimg->changeCallback(functor);
2175 return;
2176 }
2177
2178 // There we have a full plate
2179 fimg->load("41B_bboy.GIF");
2180 while (1) {
2181 fimg->manage();
2182 if (fimg->_exit || fimg->_zoneLow) {
2183 fimg->_exit = true;
2184 break;
2185 }
2186 if (fimg->_zoneUse) {
2187 // Collected food
2188 collectObject(124, fimg);
2189 _gameVariables[GameVariables::kCollectFood] = 1;
2190 // Draw plate with less food
2191 ZonFixedImage::CallbackFunctor *functor =
2192 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2193 &CryOmni3DEngine_Versailles::img_44071b);
2194 fimg->changeCallback(functor);
2195 break;
2196 }
2197 }
2198 }
2199
2200 IMG_CB(44071b) {
2201 // There we have less food on plate
2202 fimg->load("41B_bbo2.GIF");
2203 while (1) {
2204 fimg->manage();
2205 if (fimg->_exit || fimg->_zoneLow) {
2206 fimg->_exit = true;
2207 break;
2208 }
2209 }
2210 }
2211
2212 IMG_CB(44161) {
2213 // Dispatch to the correct state
2214 if (_gameVariables[GameVariables::kCollectQuill] == 1 && !_inventory.inInventoryByNameID(126)) {
2215 // We have collected quill but not solved epigraph yet
2216 ZonFixedImage::CallbackFunctor *functor =
2217 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2218 &CryOmni3DEngine_Versailles::img_44161b);
2219 fimg->changeCallback(functor);
2220 return;
2221 } else if (_gameVariables[GameVariables::kUsedVaubanBlueprint1] == 1 &&
2222 _gameVariables[GameVariables::kUsedVaubanBlueprint2] == 1) {
2223 // We have used vauban blueprints: display the solution
2224 ZonFixedImage::CallbackFunctor *functor =
2225 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2226 &CryOmni3DEngine_Versailles::img_44161f);
2227 fimg->changeCallback(functor);
2228 return;
2229 } else if (_gameVariables[GameVariables::kCollectQuill] == 1 &&
2230 _inventory.inInventoryByNameID(126)) {
2231 // We have collected quill and epigraph
2232 ZonFixedImage::CallbackFunctor *functor =
2233 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2234 &CryOmni3DEngine_Versailles::img_44161c);
2235 fimg->changeCallback(functor);
2236 return;
2237 }
2238
2239 // There we have blueprints, quill and epigraph on desk
2240 fimg->load("42X2_20.GIF");
2241 while (1) {
2242 fimg->manage();
2243 if (fimg->_exit || fimg->_zoneLow) {
2244 fimg->_exit = true;
2245 break;
2246 }
2247 if (fimg->_zoneUse && fimg->_currentZone == 0 && currentGameTime() >= 2) {
2248 // Collected quill
2249 collectObject(128, fimg);
2250 _gameVariables[GameVariables::kCollectQuill] = 1;
2251 // Try to solve epigraph
2252 ZonFixedImage::CallbackFunctor *functor =
2253 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2254 &CryOmni3DEngine_Versailles::img_44161b);
2255 fimg->changeCallback(functor);
2256 break;
2257 } else if (fimg->_zoneSee) {
2258 // Look at blueprints
2259 ZonFixedImage::CallbackFunctor *functor =
2260 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2261 &CryOmni3DEngine_Versailles::img_44161d);
2262 fimg->changeCallback(functor);
2263 break;
2264 }
2265 }
2266 }
2267
2268 IMG_CB(44161b) {
2269 // There we have blueprints and epigraph on desk.
2270 fimg->load("42X2_10.GIF");
2271 while (1) {
2272 fimg->manage();
2273 if (fimg->_exit || fimg->_zoneLow) {
2274 fimg->_exit = true;
2275 break;
2276 }
2277 if (fimg->_usedObject && fimg->_usedObject->idOBJ() == 128 && fimg->_currentZone == 1) {
2278 if (handleEpigraph(fimg)) {
2279 // Epigraph is solved
2280 _inventory.removeByNameID(128);
2281 collectObject(126, fimg, false);
2282 _dialogsMan["{JOUEUR_POSSEDE_EPIGRAPHE}"] = 'Y';
2283 setPlaceState(16, 2);
2284 // No more epigraphe nor quill
2285 ZonFixedImage::CallbackFunctor *functor =
2286 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2287 &CryOmni3DEngine_Versailles::img_44161c);
2288 fimg->changeCallback(functor);
2289 }
2290 // If failed to solve: just display this image again
2291 break;
2292 } else if (fimg->_zoneSee) {
2293 // Look at blueprints
2294 ZonFixedImage::CallbackFunctor *functor =
2295 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2296 &CryOmni3DEngine_Versailles::img_44161d);
2297 fimg->changeCallback(functor);
2298 break;
2299 }
2300 }
2301 }
2302
2303 IMG_CB(44161c) {
2304 // There we have no quill nor epigraph anymore
2305 fimg->load("42X2_11.GIF");
2306 while (1) {
2307 fimg->manage();
2308 if (fimg->_exit || fimg->_zoneLow) {
2309 fimg->_exit = true;
2310 break;
2311 }
2312 if (fimg->_zoneSee) {
2313 // Look at blueprints
2314 ZonFixedImage::CallbackFunctor *functor =
2315 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2316 &CryOmni3DEngine_Versailles::img_44161d);
2317 fimg->changeCallback(functor);
2318 break;
2319 }
2320 }
2321 }
2322
2323 IMG_CB(44161d) {
2324 // Look at blueprints
2325 fimg->load("VAU1.GIF");
2326 while (1) {
2327 fimg->manage();
2328 if (fimg->_exit || fimg->_zoneLow) {
2329 fimg->_exit = true;
2330 break;
2331 }
2332 if (fimg->_usedObject && fimg->_usedObject->idOBJ() == 131) {
2333 // Overlay blueprints
2334 ZonFixedImage::CallbackFunctor *functor =
2335 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2336 &CryOmni3DEngine_Versailles::img_44161e);
2337 fimg->changeCallback(functor);
2338 break;
2339 }
2340 }
2341 }
2342
2343 IMG_CB(44161e) {
2344 // Look at blueprints
2345 fimg->load("VAUB22.GIF");
2346 while (1) {
2347 fimg->manage();
2348 if (fimg->_exit || fimg->_zoneLow) {
2349 fimg->_exit = true;
2350 break;
2351 }
2352 if (fimg->_usedObject && fimg->_usedObject->idOBJ() == 132) {
2353 // Overlay blueprints
2354 _gameVariables[GameVariables::kUsedVaubanBlueprint1] = 1;
2355 _gameVariables[GameVariables::kUsedVaubanBlueprint2] = 1;
2356 _inventory.removeByNameID(131);
2357 _inventory.removeByNameID(132);
2358 setGameTime(4, 4);
2359 // Look at the final result
2360 ZonFixedImage::CallbackFunctor *functor =
2361 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2362 &CryOmni3DEngine_Versailles::img_44161f);
2363 fimg->changeCallback(functor);
2364 break;
2365 }
2366 }
2367 }
2368
2369 IMG_CB(44161f) {
2370 // Look at blueprints result
2371 fimg->load("VAU.GIF");
2372 while (1) {
2373 fimg->manage();
2374 if (fimg->_exit || fimg->_zoneLow) {
2375 fimg->_exit = true;
2376 break;
2377 }
2378 }
2379 }
2380
handleEpigraph(ZonFixedImage * fimg)2381 bool CryOmni3DEngine_Versailles::handleEpigraph(ZonFixedImage *fimg) {
2382 bool success = false;
2383 Graphics::Surface bmpLetters[28];
2384 Common::String password;
2385 Graphics::ManagedSurface tempSurf;
2386
2387 loadBMPs("bomb_%02d.bmp", bmpLetters, 28);
2388
2389 fimg->load("EPIL.GIF");
2390 const Graphics::Surface *fimgSurface = fimg->surface();
2391 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2392 // No need to customize image yet
2393
2394 while (1) {
2395 fimg->manage();
2396 if (fimg->_exit || fimg->_zoneLow) {
2397 break;
2398 }
2399 if (fimg->_zoneUse) {
2400 if (password.size() >= kEpigraphMaxLetters) {
2401 continue;
2402 }
2403 // Find which letter got clicked
2404 char letter = _epigraphContent[fimg->_currentZone];
2405 password += letter;
2406 // Reset the surface and redraw digits on it
2407 tempSurf.blitFrom(*fimgSurface);
2408 drawEpigraphLetters(tempSurf, bmpLetters, password);
2409 fimg->updateSurface(&tempSurf.rawSurface());
2410
2411 waitMouseRelease();
2412 } else if (fimg->_key.keycode) {
2413 Common::KeyCode keyCode = fimg->_key.keycode;
2414 if (keyCode == Common::KEYCODE_BACKSPACE) {
2415 password.deleteLastChar();
2416 } else {
2417 if (password.size() >= kEpigraphMaxLetters) {
2418 continue;
2419 }
2420 if (keyCode >= Common::KEYCODE_a &&
2421 keyCode <= Common::KEYCODE_z &&
2422 _epigraphContent.contains((char)(keyCode - Common::KEYCODE_a + 'A'))) {
2423 password += keyCode - Common::KEYCODE_a + 'A';
2424 } else {
2425 continue;
2426 }
2427 }
2428 // Reset the surface and redraw digits on it
2429 tempSurf.blitFrom(*fimgSurface);
2430 drawEpigraphLetters(tempSurf, bmpLetters, password);
2431 fimg->updateSurface(&tempSurf.rawSurface());
2432 }
2433
2434 if (password == _epigraphPassword) {
2435 success = true;
2436 break;
2437 }
2438 }
2439
2440 for (uint i = 0; i < 28; i++) {
2441 bmpLetters[i].free();
2442 }
2443 return success;
2444 }
2445
drawEpigraphLetters(Graphics::ManagedSurface & surface,const Graphics::Surface (& bmpLetters)[28],const Common::String & letters)2446 void CryOmni3DEngine_Versailles::drawEpigraphLetters(Graphics::ManagedSurface &surface,
2447 const Graphics::Surface(&bmpLetters)[28], const Common::String &letters) {
2448 for (uint i = 0; i < letters.size() && i < kEpigraphMaxLetters; i++) {
2449 uint letterId = 0;
2450 if (letters[i] >= 'A' && letters[i] <= 'Z') {
2451 letterId = letters[i] - 'A';
2452 } else if (letters[i] == ' ') {
2453 letterId = 26;
2454 } else if (letters[i] == '\'') {
2455 letterId = 27;
2456 }
2457 const Graphics::Surface &letter = bmpLetters[letterId];
2458 Common::Point dst(34 * i + 4, 380);
2459 surface.transBlitFrom(letter, dst);
2460 }
2461 }
2462
2463 IMG_CB(45130) {
2464 fimg->load("52M2.GIF");
2465 _dialogsMan["{JOUEUR-VU-PLANS-SALON-DIANE}"] = 'Y';
2466 while (1) {
2467 fimg->manage();
2468 if (fimg->_exit || fimg->_zoneLow) {
2469 fimg->_exit = true;
2470 break;
2471 }
2472 }
2473 }
2474
2475 IMG_CB(45270) {
2476 fimg->load("51A4_11.GIF");
2477 while (1) {
2478 fimg->manage();
2479 if (fimg->_exit || fimg->_zoneLow) {
2480 fimg->_exit = true;
2481 break;
2482 }
2483 if (fimg->_zoneUse) {
2484 if (fimg->_currentZone == 0) {
2485 // Open left drawer
2486 ZonFixedImage::CallbackFunctor *functor =
2487 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2488 &CryOmni3DEngine_Versailles::img_45270b);
2489 fimg->changeCallback(functor);
2490 break;
2491 } else if (fimg->_currentZone == 1) {
2492 // Open middle drawer
2493 ZonFixedImage::CallbackFunctor *functor =
2494 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2495 &CryOmni3DEngine_Versailles::img_45270c);
2496 fimg->changeCallback(functor);
2497 break;
2498 } else if (fimg->_currentZone == 2) {
2499 // Open right drawer
2500 ZonFixedImage::CallbackFunctor *functor =
2501 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2502 &CryOmni3DEngine_Versailles::img_45270d);
2503 fimg->changeCallback(functor);
2504 break;
2505 }
2506 }
2507 }
2508 }
2509
2510 IMG_CB(45270b) {
2511 fimg->load("51A4_22.GIF");
2512 if (!_gameVariables[GameVariables::kCollectSmallKey3]) {
2513 // Collected small key 3
2514 collectObject(135, fimg);
2515 _gameVariables[GameVariables::kCollectSmallKey3] = 1;
2516 }
2517 while (1) {
2518 fimg->manage();
2519 if (fimg->_exit || fimg->_zoneLow) {
2520 fimg->_exit = true;
2521 break;
2522 }
2523 if (fimg->_zoneUse) {
2524 // Close drawer
2525 ZonFixedImage::CallbackFunctor *functor =
2526 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2527 &CryOmni3DEngine_Versailles::img_45270);
2528 fimg->changeCallback(functor);
2529 break;
2530 }
2531 }
2532 }
2533
2534 IMG_CB(45270c) {
2535 fimg->load("51A4_32.GIF");
2536 if (!_gameVariables[GameVariables::kCollectEngraving]) {
2537 // Collected engraving
2538 collectObject(134, fimg);
2539 _gameVariables[GameVariables::kCollectEngraving] = 1;
2540 }
2541 while (1) {
2542 fimg->manage();
2543 if (fimg->_exit || fimg->_zoneLow) {
2544 fimg->_exit = true;
2545 break;
2546 }
2547 if (fimg->_zoneUse) {
2548 // Close drawer
2549 ZonFixedImage::CallbackFunctor *functor =
2550 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2551 &CryOmni3DEngine_Versailles::img_45270);
2552 fimg->changeCallback(functor);
2553 break;
2554 }
2555 }
2556 }
2557
2558 IMG_CB(45270d) {
2559 fimg->load("51A4_12.GIF");
2560 while (1) {
2561 fimg->manage();
2562 if (fimg->_exit || fimg->_zoneLow) {
2563 fimg->_exit = true;
2564 break;
2565 }
2566 if (fimg->_zoneUse) {
2567 // Close drawer
2568 ZonFixedImage::CallbackFunctor *functor =
2569 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2570 &CryOmni3DEngine_Versailles::img_45270);
2571 fimg->changeCallback(functor);
2572 break;
2573 }
2574 }
2575 }
2576
2577 IMG_CB(45280) {
2578 if (_gameVariables[GameVariables::kOpenedCurtain]) {
2579 fimg->load("53I_LUST.GIF");
2580 _gameVariables[GameVariables::kSeenMemorandum] = 1;
2581 while (1) {
2582 fimg->manage();
2583 if (fimg->_exit || fimg->_zoneLow) {
2584 fimg->_exit = true;
2585 break;
2586 }
2587 }
2588 } else {
2589 fimg->_exit = true;
2590 }
2591 }
2592
2593 IMG_CB(88001) {
2594 if (!_inventory.inInventoryByNameID(121) &&
2595 _gameVariables[GameVariables::kMedalsDrawerStatus] == 3) {
2596 ZonFixedImage::CallbackFunctor *functor =
2597 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2598 &CryOmni3DEngine_Versailles::img_88001c);
2599 fimg->changeCallback(functor);
2600 return;
2601 }
2602
2603 fimg->load("33P_10.GIF");
2604 if (_inventory.inInventoryByNameID(121)) {
2605 fimg->disableZone(0);
2606 }
2607 while (1) {
2608 fimg->manage();
2609 if (fimg->_exit || fimg->_zoneLow) {
2610 fimg->_exit = true;
2611 break;
2612 }
2613 if (fimg->_zoneUse &&
2614 !_inventory.inInventoryByNameID(121)) {
2615 // Open the drawer
2616
2617 playInGameVideo("33P_10");
2618 // Force reload of the place
2619 if (_nextPlaceId == uint(-1)) {
2620 _nextPlaceId = _currentPlaceId;
2621 }
2622
2623 ZonFixedImage::CallbackFunctor *functor =
2624 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2625 &CryOmni3DEngine_Versailles::img_88001b);
2626 fimg->changeCallback(functor);
2627 break;
2628 }
2629 }
2630 }
2631
2632 IMG_CB(88001b) {
2633 _gameVariables[GameVariables::kMedalsDrawerStatus] = 2;
2634
2635 fimg->load("33P_12.GIF");
2636 while (1) {
2637 fimg->manage();
2638 if (fimg->_exit) {
2639 break;
2640 }
2641 if (fimg->_zoneLow) {
2642 _gameVariables[GameVariables::kMedalsDrawerStatus] = 0;
2643 // Go back to drawer closed
2644 ZonFixedImage::CallbackFunctor *functor =
2645 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2646 &CryOmni3DEngine_Versailles::img_88001);
2647 fimg->changeCallback(functor);
2648 break;
2649 }
2650 if (fimg->_usedObject &&
2651 fimg->_usedObject->idOBJ() == 114 &&
2652 fimg->_currentZone == 0) {
2653 // Lay the paper on the medals
2654 _inventory.removeByNameID(114);
2655
2656 ZonFixedImage::CallbackFunctor *functor =
2657 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2658 &CryOmni3DEngine_Versailles::img_88001c);
2659 fimg->changeCallback(functor);
2660 break;
2661 }
2662 }
2663 }
2664
2665 IMG_CB(88001c) {
2666 // Paper is laid on the medals
2667 _gameVariables[GameVariables::kMedalsDrawerStatus] = 3;
2668
2669 fimg->load("33P_13.GIF");
2670 while (1) {
2671 fimg->manage();
2672 if (fimg->_exit || fimg->_zoneLow) {
2673 fimg->_exit = true;
2674 break;
2675 }
2676 if (fimg->_usedObject &&
2677 fimg->_usedObject->idOBJ() == 113 &&
2678 fimg->_currentZone == 0) {
2679 // Use charcoal on paper and medals
2680 _inventory.removeByNameID(113);
2681
2682 playInGameVideo("33P_14");
2683 // Force reload of the place
2684 if (_nextPlaceId == uint(-1)) {
2685 _nextPlaceId = _currentPlaceId;
2686 }
2687
2688 collectObject(121, fimg);
2689 _dialogsMan["{JOUEUR-POSSEDE-FUSAIN-MEDAILLES}"] = 'Y';
2690
2691 ZonFixedImage::CallbackFunctor *functor =
2692 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2693 &CryOmni3DEngine_Versailles::img_88001);
2694 fimg->changeCallback(functor);
2695 break;
2696 }
2697 }
2698 }
2699
2700 IMG_CB(88002) {
2701 fimg->load("53Z1c_10.GIF");
2702 while (1) {
2703 fimg->manage();
2704 if (fimg->_exit || fimg->_zoneLow) {
2705 fimg->_exit = true;
2706 break;
2707 }
2708 if (fimg->_zoneUse) {
2709 if (_currentLevel == 7) {
2710 // You will need something to reach the bomb
2711 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 10,
2712 fimg->getZoneCenter(fimg->_currentZone),
2713 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
2714 }
2715 }
2716 }
2717 }
2718
2719 IMG_CB(88003) {
2720 // Dispatch to the correct state
2721 if (_gameVariables[GameVariables::kBombState] >= 1 &&
2722 _gameVariables[GameVariables::kBombState] <= 5) {
2723 FixedImgCallback callback = nullptr;
2724 switch (_gameVariables[GameVariables::kBombState]) {
2725 case 1:
2726 callback = &CryOmni3DEngine_Versailles::img_88003b;
2727 break;
2728 case 2:
2729 callback = &CryOmni3DEngine_Versailles::img_88003c;
2730 break;
2731 case 3:
2732 callback = &CryOmni3DEngine_Versailles::img_88003d;
2733 break;
2734 case 4:
2735 callback = &CryOmni3DEngine_Versailles::img_88003e;
2736 break;
2737 case 5:
2738 callback = &CryOmni3DEngine_Versailles::img_88003f;
2739 break;
2740 default:
2741 error("BUG: Invalid bomb state");
2742 break;
2743 }
2744 ZonFixedImage::CallbackFunctor *functor =
2745 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this, callback);
2746 fimg->changeCallback(functor);
2747 return;
2748 }
2749
2750 fimg->load("70Z_10.GIF");
2751
2752 // Draw countdown there and not in fixed image class directly
2753 Graphics::ManagedSurface tempSurf;
2754 const Graphics::Surface *fimgSurface = fimg->surface();
2755 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2756 tempSurf.blitFrom(*fimgSurface);
2757 drawCountdown(&tempSurf);
2758 fimg->updateSurface(&tempSurf.rawSurface());
2759
2760 while (1) {
2761 fimg->manage();
2762 if (fimg->_exit || fimg->_zoneLow) {
2763 fimg->_exit = true;
2764 break;
2765 }
2766 if (fimg->_currentZone == 0 && fimg->_usedObject &&
2767 fimg->_usedObject->idOBJ() == 145) {
2768 // Now we know how to reach the bomb
2769 _gameVariables[GameVariables::kBombState] = 1;
2770 ZonFixedImage::CallbackFunctor *functor =
2771 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2772 &CryOmni3DEngine_Versailles::img_88003b);
2773 fimg->changeCallback(functor);
2774 break;
2775 }
2776 if (fimg->_zoneUse) {
2777 if (_currentLevel == 7) {
2778 // You will need something to reach the bomb
2779 displayMessageBox(kFixedimageMsgBoxParameters, fimg->surface(), 10,
2780 fimg->getZoneCenter(fimg->_currentZone),
2781 Common::Functor0Mem<void, ZonFixedImage>(fimg, &ZonFixedImage::manage));
2782 }
2783 }
2784 if (countDown()) {
2785 // Countdown has changed: refresh surface
2786 drawCountdown(&tempSurf);
2787 fimg->updateSurface(&tempSurf.rawSurface());
2788 }
2789 }
2790 }
2791
2792 IMG_CB(88003b) {
2793 fimg->load("70Z_11.GIF");
2794
2795 // Draw countdown there and not in fixed image class directly
2796 Graphics::ManagedSurface tempSurf;
2797 const Graphics::Surface *fimgSurface = fimg->surface();
2798 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2799 tempSurf.blitFrom(*fimgSurface);
2800 drawCountdown(&tempSurf);
2801 fimg->updateSurface(&tempSurf.rawSurface());
2802
2803 while (1) {
2804 fimg->manage();
2805 if (fimg->_exit || fimg->_zoneLow) {
2806 fimg->_exit = true;
2807 break;
2808 }
2809 if (fimg->_currentZone == 0 && fimg->_usedObject &&
2810 fimg->_usedObject->idOBJ() == 97) {
2811 // Unlock first line with key 1
2812 _gameVariables[GameVariables::kBombState] = 2;
2813 ZonFixedImage::CallbackFunctor *functor =
2814 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2815 &CryOmni3DEngine_Versailles::img_88003c);
2816 fimg->changeCallback(functor);
2817 break;
2818 }
2819 if (countDown()) {
2820 // Countdown has changed: refresh surface
2821 drawCountdown(&tempSurf);
2822 fimg->updateSurface(&tempSurf.rawSurface());
2823 }
2824 }
2825 }
2826
2827 IMG_CB(88003c) {
2828 fimg->load("70Z_12.GIF");
2829
2830 // Draw countdown there and not in fixed image class directly
2831 Graphics::ManagedSurface tempSurf;
2832 const Graphics::Surface *fimgSurface = fimg->surface();
2833 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2834 tempSurf.blitFrom(*fimgSurface);
2835 drawCountdown(&tempSurf);
2836 fimg->updateSurface(&tempSurf.rawSurface());
2837
2838 while (1) {
2839 fimg->manage();
2840 if (fimg->_exit || fimg->_zoneLow) {
2841 fimg->_exit = true;
2842 break;
2843 }
2844 if (fimg->_currentZone == 1 && fimg->_usedObject &&
2845 fimg->_usedObject->idOBJ() == 116) {
2846 // Unlock second line with key 2
2847 _gameVariables[GameVariables::kBombState] = 3;
2848 ZonFixedImage::CallbackFunctor *functor =
2849 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2850 &CryOmni3DEngine_Versailles::img_88003d);
2851 fimg->changeCallback(functor);
2852 break;
2853 }
2854 if (countDown()) {
2855 // Countdown has changed: refresh surface
2856 drawCountdown(&tempSurf);
2857 fimg->updateSurface(&tempSurf.rawSurface());
2858 }
2859 }
2860 }
2861
2862 IMG_CB(88003d) {
2863 fimg->load("70Z_13.GIF");
2864
2865 // Draw countdown there and not in fixed image class directly
2866 Graphics::ManagedSurface tempSurf;
2867 const Graphics::Surface *fimgSurface = fimg->surface();
2868 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2869 tempSurf.blitFrom(*fimgSurface);
2870 drawCountdown(&tempSurf);
2871 fimg->updateSurface(&tempSurf.rawSurface());
2872
2873 while (1) {
2874 fimg->manage();
2875 if (fimg->_exit || fimg->_zoneLow) {
2876 fimg->_exit = true;
2877 break;
2878 }
2879 if (fimg->_currentZone == 2 && fimg->_usedObject &&
2880 fimg->_usedObject->idOBJ() == 135) {
2881 // Unlock third line with key 3
2882 _gameVariables[GameVariables::kBombState] = 4;
2883 ZonFixedImage::CallbackFunctor *functor =
2884 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2885 &CryOmni3DEngine_Versailles::img_88003e);
2886 fimg->changeCallback(functor);
2887 break;
2888 }
2889 if (countDown()) {
2890 // Countdown has changed: refresh surface
2891 drawCountdown(&tempSurf);
2892 fimg->updateSurface(&tempSurf.rawSurface());
2893 }
2894 }
2895 }
2896
2897 IMG_CB(88003e) {
2898 fimg->load("70Z_14.GIF");
2899
2900 // Draw countdown there and not in fixed image class directly
2901 Graphics::ManagedSurface tempSurf;
2902 const Graphics::Surface *fimgSurface = fimg->surface();
2903 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2904 tempSurf.blitFrom(*fimgSurface);
2905 drawCountdown(&tempSurf);
2906 fimg->updateSurface(&tempSurf.rawSurface());
2907
2908 while (1) {
2909 fimg->manage();
2910 if (fimg->_exit || fimg->_zoneLow) {
2911 fimg->_exit = true;
2912 break;
2913 }
2914 if (fimg->_currentZone == 3 && fimg->_usedObject &&
2915 fimg->_usedObject->idOBJ() == 136) {
2916 // Unlock fourth line with key 4
2917 _gameVariables[GameVariables::kBombState] = 5;
2918 ZonFixedImage::CallbackFunctor *functor =
2919 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
2920 &CryOmni3DEngine_Versailles::img_88003f);
2921 fimg->changeCallback(functor);
2922 break;
2923 }
2924 if (countDown()) {
2925 // Countdown has changed: refresh surface
2926 drawCountdown(&tempSurf);
2927 fimg->updateSurface(&tempSurf.rawSurface());
2928 }
2929 }
2930 }
2931
2932 IMG_CB(88003f) {
2933 fimg->load("70Z_15.GIF");
2934
2935 // Draw countdown there and not in fixed image class directly
2936 Graphics::ManagedSurface tempSurf;
2937 const Graphics::Surface *fimgSurface = fimg->surface();
2938 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
2939 tempSurf.blitFrom(*fimgSurface);
2940 drawCountdown(&tempSurf);
2941 fimg->updateSurface(&tempSurf.rawSurface());
2942
2943 while (1) {
2944 fimg->manage();
2945 if (fimg->_exit || fimg->_zoneLow) {
2946 fimg->_exit = true;
2947 break;
2948 }
2949 if (fimg->_zoneUse) {
2950 if (handleBomb(fimg)) {
2951 playInGameVideo("COFFRE");
2952 _forcePaletteUpdate = true;
2953 // Force reload of the place
2954 if (_nextPlaceId == uint(-1)) {
2955 _nextPlaceId = _currentPlaceId;
2956 }
2957 playTransitionEndLevel(7);
2958 break;
2959 }
2960 }
2961 if (countDown()) {
2962 // Countdown has changed: refresh surface
2963 drawCountdown(&tempSurf);
2964 fimg->updateSurface(&tempSurf.rawSurface());
2965 }
2966 }
2967 }
2968
handleBomb(ZonFixedImage * fimg)2969 bool CryOmni3DEngine_Versailles::handleBomb(ZonFixedImage *fimg) {
2970 bool success = false;
2971 Common::RandomSource rnd("VersaillesBomb");
2972 Graphics::Surface bmpLetters[28];
2973 uint32 bombPossibilites[60][5];
2974 byte bombCurrentLetters[60];
2975 Graphics::ManagedSurface tempSurf;
2976
2977 const uint bombPasswordLength = _bombPassword.size();
2978 if (bombPasswordLength >= kBombPasswordMaxLength) {
2979 error("Bomb password is too long");
2980 }
2981
2982 uint max = _bombAlphabet.size() - 1;
2983 if (getLanguage() != Common::JA_JPN) {
2984 // In bitmap mode we only have 28 images
2985 assert(max < 28);
2986 // BUG: in game the rand is modulo 27
2987 max = 26;
2988 loadBMPs("bomb_%02d.bmp", bmpLetters, 28);
2989 }
2990 for (uint i = 0; i < bombPasswordLength; i++) {
2991 bombPossibilites[i][0] = _bombPassword[i];
2992 for (uint j = 1; j < 5; j++) {
2993 bool foundSameLetter;
2994 do {
2995 foundSameLetter = false;
2996 bombPossibilites[i][j] = _bombAlphabet[rnd.getRandomNumber(max)];
2997 for (uint k = 0; k < j; k++) {
2998 if (bombPossibilites[i][k] == bombPossibilites[i][j]) {
2999 foundSameLetter = true;
3000 }
3001 }
3002 } while (foundSameLetter);
3003 }
3004 bombCurrentLetters[i] = rnd.getRandomNumber(4);
3005 }
3006
3007 if (bombPasswordLength <= kBombPasswordSmallLength) {
3008 fimg->load("70z_16.GIF");
3009 } else {
3010 fimg->load("70z_17.GIF");
3011 }
3012 const Graphics::Surface *fimgSurface = fimg->surface();
3013 tempSurf.create(fimgSurface->w, fimgSurface->h, fimgSurface->format);
3014 tempSurf.blitFrom(*fimgSurface);
3015 drawBombLetters(tempSurf, bmpLetters, bombPasswordLength, bombPossibilites, bombCurrentLetters);
3016 drawCountdown(&tempSurf);
3017 fimg->updateSurface(&tempSurf.rawSurface());
3018
3019 while (1) {
3020 fimg->manage();
3021 if (fimg->_exit || fimg->_zoneLow) {
3022 break;
3023 }
3024 if (fimg->_zoneUse) {
3025 if (fimg->_currentZone < bombPasswordLength) {
3026 // Safe digit
3027 bombCurrentLetters[fimg->_currentZone] = (bombCurrentLetters[fimg->_currentZone] + 1) % 5;
3028 // Reset the surface and redraw letters on it
3029 tempSurf.blitFrom(*fimgSurface);
3030 drawBombLetters(tempSurf, bmpLetters, bombPasswordLength, bombPossibilites, bombCurrentLetters);
3031 drawCountdown(&tempSurf);
3032 fimg->updateSurface(&tempSurf.rawSurface());
3033
3034 waitMouseRelease();
3035
3036 // Check if password is OK
3037 success = true;
3038 for (uint i = 0; i < bombPasswordLength; i++) {
3039 uint16 letterId = bombPossibilites[i][bombCurrentLetters[i]];
3040 if (letterId != _bombPassword[i]) {
3041 success = false;
3042 break;
3043 }
3044 }
3045 if (success) {
3046 handleBombTranslation(tempSurf);
3047 break;
3048 }
3049 }
3050 }
3051 if (countDown()) {
3052 // Countdown has changed: refresh surface
3053 drawCountdown(&tempSurf);
3054 fimg->updateSurface(&tempSurf.rawSurface());
3055 }
3056 }
3057
3058 for (uint i = 0; i < 28; i++) {
3059 bmpLetters[i].free();
3060 }
3061 return success;
3062 }
3063
handleBombTranslation(Graphics::ManagedSurface & surface)3064 void CryOmni3DEngine_Versailles::handleBombTranslation(Graphics::ManagedSurface &surface) {
3065 if (_messages.size() <= 150) {
3066 return;
3067 }
3068
3069 Common::String &translation = _messages[150];
3070
3071 if (translation.size() == 0) {
3072 return;
3073 }
3074
3075 surface.fillRect(Common::Rect(0, 430, 640, 480), 247);
3076
3077 _fontManager.setCurrentFont(1);
3078 _fontManager.setTransparentBackground(true);
3079 _fontManager.setForeColor(242);
3080 _fontManager.setSurface(&surface);
3081 uint w = _fontManager.getStrWidth(translation);
3082 _fontManager.displayStr((640 - w) / 2, 440, translation);
3083
3084 g_system->copyRectToScreen(surface.getPixels(), surface.pitch, 0, 0,
3085 surface.w, surface.h);
3086 g_system->updateScreen();
3087
3088 uint32 end = g_system->getMillis() + 5000;
3089 bool exitImg = false;
3090 while (!shouldAbort() && !exitImg && g_system->getMillis() < end) {
3091 if (pollEvents()) {
3092 if (checkKeysPressed() || getCurrentMouseButton() == 1) {
3093 exitImg = true;
3094 }
3095 }
3096 g_system->updateScreen();
3097 g_system->delayMillis(10);
3098 }
3099 }
3100
3101 const uint16 CryOmni3DEngine_Versailles::kBombLettersPos[2][kBombPasswordMaxLength][2] = {
3102 {
3103 {26, 91},
3104 {84, 89},
3105 {141, 89},
3106 {202, 88},
3107 {261, 87},
3108 {322, 86},
3109 {384, 85},
3110 {448, 84},
3111 {512, 83},
3112 {576, 83},
3113 {26, 175},
3114 {84, 175},
3115 {142, 174},
3116 {202, 174},
3117 {260, 174},
3118 {322, 174},
3119 {384, 173},
3120 {448, 173},
3121 {512, 173},
3122 {576, 172},
3123 {26, 261},
3124 {84, 261},
3125 {141, 261},
3126 {202, 261},
3127 {261, 262},
3128 {322, 262},
3129 {383, 262},
3130 {447, 263},
3131 {512, 263},
3132 {576, 263},
3133 {26, 344},
3134 {84, 345},
3135 {142, 346},
3136 {202, 347},
3137 {260, 348},
3138 {322, 349},
3139 {384, 350},
3140 {448, 351},
3141 {512, 352},
3142 {576, 352}
3143 },
3144 {
3145 {42, 26},
3146 {100, 24},
3147 {155, 22},
3148 {214, 19},
3149 {271, 18},
3150 {330, 15},
3151 {389, 14},
3152 {451, 11},
3153 {515, 8},
3154 {576, 6},
3155 {45, 102},
3156 {100, 102},
3157 {156, 101},
3158 {215, 100},
3159 {272, 99},
3160 {331, 98},
3161 {391, 97},
3162 {453, 96},
3163 {515, 94},
3164 {578, 94},
3165 {44, 184},
3166 {101, 184},
3167 {157, 184},
3168 {215, 183},
3169 {272, 183},
3170 {331, 183},
3171 {391, 182},
3172 {453, 182},
3173 {515, 182},
3174 {577, 181},
3175 {44, 267},
3176 {101, 267},
3177 {157, 267},
3178 {215, 268},
3179 {272, 268},
3180 {331, 268},
3181 {390, 269},
3182 {453, 269},
3183 {515, 269},
3184 {578, 269},
3185 {45, 348},
3186 {101, 349},
3187 {156, 349},
3188 {215, 351},
3189 {271, 351},
3190 {331, 351},
3191 {391, 353},
3192 {453, 354},
3193 {515, 355},
3194 {577, 356},
3195 {44, 434},
3196 {101, 435},
3197 {156, 436},
3198 {215, 437},
3199 {272, 437},
3200 {331, 437},
3201 {391, 439},
3202 {453, 440},
3203 {515, 441},
3204 {578, 442}
3205 },
3206 };
3207
drawBombLetters(Graphics::ManagedSurface & surface,const Graphics::Surface (& bmpLetters)[28],const uint bombPasswordLength,const uint32 (& bombPossibilites)[kBombPasswordMaxLength][5],const byte (& bombCurrentLetters)[kBombPasswordMaxLength])3208 void CryOmni3DEngine_Versailles::drawBombLetters(Graphics::ManagedSurface &surface,
3209 const Graphics::Surface(&bmpLetters)[28], const uint bombPasswordLength,
3210 const uint32(&bombPossibilites)[kBombPasswordMaxLength][5],
3211 const byte(&bombCurrentLetters)[kBombPasswordMaxLength]) {
3212 uint table = bombPasswordLength <= kBombPasswordSmallLength ? 0 : 1;
3213 if (getLanguage() == Common::JA_JPN) {
3214 _fontManager.setCurrentFont(1);
3215 _fontManager.setTransparentBackground(true);
3216 _fontManager.setForeColor(0);
3217 _fontManager.setSurface(&surface);
3218
3219 for (uint i = 0; i < bombPasswordLength; i++) {
3220 Common::Rect rct(34, 34);
3221 rct.moveTo(kBombLettersPos[table][i][0], kBombLettersPos[table][i][1]);
3222 surface.fillRect(rct, 239);
3223
3224 uint32 letter = bombPossibilites[i][bombCurrentLetters[i]];
3225 Common::U32String str(&letter, 1);
3226
3227 _fontManager.displayStr(rct.left + (34 - _fontManager.getStrWidth(str)) / 2,
3228 rct.top + 5, str);
3229 }
3230 } else {
3231 for (uint i = 0; i < bombPasswordLength; i++) {
3232 uint letterId = _bombAlphabet.find(bombPossibilites[i][bombCurrentLetters[i]]);
3233 const Graphics::Surface &letter = bmpLetters[letterId];
3234 Common::Point dst(kBombLettersPos[table][i][0], kBombLettersPos[table][i][1]);
3235 surface.transBlitFrom(letter, dst);
3236 }
3237 }
3238 }
3239
3240 IMG_CB(88004) {
3241 fimg->load("31j31.gif");
3242 while (1) {
3243 fimg->manage();
3244 if (fimg->_exit || fimg->_zoneLow) {
3245 fimg->_exit = true;
3246 break;
3247 }
3248 if (fimg->_zoneUse) {
3249 ZonFixedImage::CallbackFunctor *functor =
3250 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
3251 &CryOmni3DEngine_Versailles::img_88004b);
3252 fimg->changeCallback(functor);
3253 break;
3254 }
3255 }
3256 }
3257
3258 IMG_CB(88004b) {
3259 // Open the toilets
3260 playInGameVideo("31j32");
3261 // Force reload of the place
3262 if (_nextPlaceId == uint(-1)) {
3263 _nextPlaceId = _currentPlaceId;
3264 }
3265 fimg->load("31j32.gif");
3266 while (1) {
3267 fimg->manage();
3268 if (fimg->_exit || fimg->_zoneLow) {
3269 fimg->_exit = true;
3270 break;
3271 }
3272 if (fimg->_zoneUse) {
3273 ZonFixedImage::CallbackFunctor *functor =
3274 new Common::Functor1Mem<ZonFixedImage *, void, CryOmni3DEngine_Versailles>(this,
3275 &CryOmni3DEngine_Versailles::img_88004);
3276 fimg->changeCallback(functor);
3277 break;
3278 }
3279 }
3280 if (!shouldAbort()) {
3281 // Close the toilets
3282 playInGameVideo("31j32b");
3283 // Force reload of the place
3284 if (_nextPlaceId == uint(-1)) {
3285 _nextPlaceId = _currentPlaceId;
3286 }
3287 }
3288 }
3289
3290 #undef IMG_CB
3291
3292 // Init place and filter event
3293 #define FILTER_EVENT(level, place) bool CryOmni3DEngine_Versailles::filterEventLevel ## level ## Place ## place(uint *event)
3294 #define INIT_PLACE(level, place) void CryOmni3DEngine_Versailles::initPlaceLevel ## level ## Place ## place()
3295
3296 FILTER_EVENT(1, 1) {
3297 if (*event > 0 && *event < 9999) {
3298 _gameVariables[GameVariables::kWarnedIncomplete] = 0;
3299 }
3300 if (*event == 11015 && currentGameTime() < 3) {
3301 return false;
3302 } else {
3303 return true;
3304 }
3305 }
3306
3307 FILTER_EVENT(1, 2) {
3308 if (*event == 7 && currentGameTime() < 2) {
3309 // Closed
3310 displayMessageBoxWarp(2);
3311 return false;
3312 }
3313
3314 if (*event == 1 && currentGameTime() < 3) {
3315 _dialogsMan.play("11E_HUI");
3316 _forcePaletteUpdate = true;
3317 // Force reload of the place
3318 if (_nextPlaceId == uint(-1)) {
3319 _nextPlaceId = _currentPlaceId;
3320 }
3321 return false;
3322 }
3323
3324 return true;
3325 }
3326
3327 INIT_PLACE(1, 3) {
3328 if (!_gameVariables[GameVariables::kHasPlayedLebrun]) {
3329 Common::File *audioFile = new Common::File();
3330 if (!audioFile->open(_localizedFilenames[LocalizedFilenames::kLeb001])) {
3331 warning("Failed to open sound file %s", _localizedFilenames[LocalizedFilenames::kLeb001].c_str());
3332 delete audioFile;
3333 return;
3334 }
3335
3336 Audio::SeekableAudioStream *audioDecoder = Audio::makeWAVStream(audioFile, DisposeAfterUse::YES);
3337 // We lost ownership of the audioFile just set it to nullptr and don't use it
3338 audioFile = nullptr;
3339 if (!audioDecoder) {
3340 return;
3341 }
3342
3343 _mixer->playStream(Audio::Mixer::kSpeechSoundType, nullptr, audioDecoder, SoundIds::kLeb001);
3344 // We lost ownership of the audioDecoder just set it to nullptr and don't use it
3345 audioDecoder = nullptr;
3346
3347 _gameVariables[GameVariables::kHasPlayedLebrun] = 1;
3348 }
3349 }
3350
3351 FILTER_EVENT(1, 3) {
3352 if (*event == 11301) {
3353 while (!shouldAbort() && _mixer->isSoundIDActive(SoundIds::kLeb001)) {
3354 g_system->updateScreen();
3355 g_system->delayMillis(10);
3356 pollEvents();
3357 }
3358 clearKeys();
3359 return true;
3360 }
3361
3362 if (*event > 0 && *event < 10000) {
3363 _mixer->stopID(SoundIds::kLeb001);
3364 return true;
3365 }
3366 return true;
3367 }
3368
3369 // Event 19 is not in this room: must be a leftover
3370 /*
3371 FILTER_EVENT(1, 7) {
3372 if (*event == 19) {
3373 // Too dark
3374 displayMessageBoxWarp(7);
3375 return false;
3376 }
3377
3378 return true;
3379 }
3380 */
3381
3382 FILTER_EVENT(1, 14) {
3383 if (*event == 31141 && _placeStates[14].state == 0) {
3384 // Open the curtain
3385 uint fakePlaceId = getFakeTransition(*event);
3386 fakeTransition(fakePlaceId);
3387 playInGameVideo("10D2_1");
3388 setPlaceState(14, 1);
3389 // setPlaceState will force reload
3390 // Don't pass the event as we try to avoid implementing use
3391 return false;
3392 }
3393
3394 if (*event != 31142 && *event != 31143) {
3395 // Not for us
3396 return true;
3397 }
3398
3399 const char *video;
3400 FixedImgCallback callback;
3401
3402 if (_currentLevel == 1 && _placeStates[14].state == 0) {
3403 if (*event == 31142) {
3404 video = "10D2_4";
3405 callback = &CryOmni3DEngine_Versailles::img_31142;
3406 } else if (*event == 31143) {
3407 video = "10D2_3";
3408 callback = &CryOmni3DEngine_Versailles::img_31143;
3409 } else {
3410 error("BUG: Shouldn't be here");
3411 }
3412 } else if (_currentLevel == 2 || _placeStates[14].state == 1) {
3413 if (*event == 31142) {
3414 video = "11D2_2";
3415 callback = &CryOmni3DEngine_Versailles::img_31142b;
3416 } else if (*event == 31143) {
3417 video = "11D2_1";
3418 callback = &CryOmni3DEngine_Versailles::img_31143b;
3419 } else {
3420 error("BUG: Shouldn't be here");
3421 }
3422 } else {
3423 error("Invalid state in filter event 1/14: level: %d/ placeState: %d", _currentLevel,
3424 _placeStates[14].state);
3425 }
3426
3427 uint fakePlaceId = getFakeTransition(*event);
3428 fakeTransition(fakePlaceId);
3429
3430 playInGameVideo(video);
3431
3432 // Force reload of the place
3433 if (_nextPlaceId == uint(-1)) {
3434 _nextPlaceId = _currentPlaceId;
3435 }
3436
3437 handleFixedImg(callback);
3438
3439 // Don't pass the event as we try to avoid implementing use
3440 return false;
3441 }
3442
3443 FILTER_EVENT(2, 1) {
3444 if (*event == 22101 && _inventory.selectedObject()) {
3445 _dialogsMan["{JOUEUR-MONTRE-UN-PAMPHLET}"] = 'N';
3446 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
3447 _dialogsMan["{JOUEUR-MONTRE-PAPIER-ECRIT-ENCRE-SYMPATHIQUE}"] = 'N';
3448 uint idOBJ = _inventory.selectedObject()->idOBJ();
3449 if (idOBJ == 96 || idOBJ == 101 || idOBJ == 115 ||
3450 idOBJ == 125 || idOBJ == 127) {
3451 _dialogsMan["{JOUEUR-MONTRE-UN-PAMPHLET}"] = 'Y';
3452 } else if (idOBJ == 98) {
3453 _dialogsMan["{JOUEUR-MONTRE-PAPIER-ECRIT-ENCRE-SYMPATHIQUE}"] = 'Y';
3454 } else {
3455 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
3456 }
3457 _dialogsMan.play("21F_BON");
3458
3459 _forcePaletteUpdate = true;
3460 // Force reload of the place
3461 if (_nextPlaceId == uint(-1)) {
3462 _nextPlaceId = _currentPlaceId;
3463 }
3464
3465 _dialogsMan["{JOUEUR-MONTRE-UN-PAMPHLET}"] = 'N';
3466 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
3467 _dialogsMan["{JOUEUR-MONTRE-PAPIER-ECRIT-ENCRE-SYMPATHIQUE}"] = 'N';
3468
3469 if (idOBJ == 98 && _dialogsMan["JOUEUR-CONFIE-MESSAGE-HUISSIER"] == 'Y') {
3470 _inventory.removeByNameID(98);
3471 setGameTime(2, 2);
3472 }
3473 _inventory.deselectObject();
3474 } else if (*event == 31101) {
3475 if (!_inventory.selectedObject() && currentGameTime() > 1) {
3476 const char *video;
3477 FixedImgCallback callback;
3478
3479 if (!_gameVariables[GameVariables::kCollectKey]) {
3480 video = "21F_11";
3481 callback = &CryOmni3DEngine_Versailles::img_31101;
3482 } else {
3483 video = "21F_10";
3484 callback = &CryOmni3DEngine_Versailles::img_31101b;
3485 }
3486
3487 playInGameVideo(video);
3488
3489 // Force reload of the place
3490 if (_nextPlaceId == uint(-1)) {
3491 _nextPlaceId = _currentPlaceId;
3492 }
3493
3494 handleFixedImg(callback);
3495 }
3496 // Don't pass the event as we try to avoid implementing use
3497 return false;
3498 } else if (*event >= 1 && *event <= 9999 && currentGameTime() == 2) {
3499 setPlaceState(1, 1);
3500 }
3501 return true;
3502 }
3503
3504 FILTER_EVENT(2, 2) {
3505 if (*event < 32201 || *event > 32204) {
3506 // Not handled here
3507 return true;
3508 }
3509
3510 const char *video = nullptr;
3511 FixedImgCallback callback = nullptr;
3512
3513 const Object *obj = _inventory.selectedObject();
3514 bool deselectObj = false;
3515
3516 if (*event == 32201) {
3517 if (!obj) {
3518 // Opening left drawer
3519 video = "21E_41";
3520 callback = &CryOmni3DEngine_Versailles::img_32201;
3521 } else {
3522 return false;
3523 }
3524 } else if (*event == 32202) {
3525 if (obj && obj->idOBJ() == 104) {
3526 // Using key on left door
3527 video = "21E_42";
3528 callback = &CryOmni3DEngine_Versailles::img_32202;
3529 } else {
3530 // This door is locked
3531 displayMessageBoxWarp(1);
3532 return false;
3533 }
3534 } else if (*event == 32203) {
3535 if (!obj) {
3536 // Opening right drawer
3537 video = "21E_43";
3538 callback = &CryOmni3DEngine_Versailles::img_32203;
3539 } else {
3540 return false;
3541 }
3542 } else if (*event == 32204) {
3543 if (obj && obj->idOBJ() == 104) {
3544 // Using key on right door
3545 if (_gameVariables[GameVariables::kCollectPortfolio]) {
3546 video = "21E_45";
3547 callback = &CryOmni3DEngine_Versailles::img_32204b;
3548 } else {
3549 video = "21E_44";
3550 callback = &CryOmni3DEngine_Versailles::img_32204;
3551 }
3552 deselectObj = true;
3553 } else {
3554 // This door is locked
3555 displayMessageBoxWarp(1);
3556 return false;
3557 }
3558 }
3559
3560 assert(video != nullptr);
3561 assert(callback != nullptr);
3562
3563 // Adjust viewpoint for video
3564 uint fakePlaceId = getFakeTransition(*event);
3565 fakeTransition(fakePlaceId);
3566
3567 playInGameVideo(video);
3568
3569 // Force reload of the place
3570 if (_nextPlaceId == uint(-1)) {
3571 _nextPlaceId = _currentPlaceId;
3572 }
3573
3574 handleFixedImg(callback);
3575
3576 if (deselectObj) {
3577 _inventory.deselectObject();
3578 }
3579
3580 // Don't pass the event: it has been handled
3581 return false;
3582 }
3583
3584 FILTER_EVENT(2, 5) {
3585 if (*event == 22501 && _inventory.selectedObject()) {
3586 uint idOBJ = _inventory.selectedObject()->idOBJ();
3587 if (idOBJ == 96) {
3588 if (!_inventory.inInventoryByNameID(101)) {
3589 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARTS}"] = 'Y';
3590 }
3591 } else {
3592 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-CHOSE}"] = 'Y';
3593 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
3594 }
3595
3596 _dialogsMan.play("21B1_HUI");
3597
3598 _forcePaletteUpdate = true;
3599 // Force reload of the place
3600 if (_nextPlaceId == uint(-1)) {
3601 _nextPlaceId = _currentPlaceId;
3602 }
3603
3604 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARTS}"] = 'N';
3605 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-CHOSE}"] = 'N';
3606 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
3607
3608 _inventory.deselectObject();
3609 } else if (*event >= 1 && *event <= 9999 &&
3610 _inventory.inInventoryByNameID(96) && !_inventory.inInventoryByNameID(101)) {
3611 // Give your clues at the bailiff
3612 displayMessageBoxWarp(15);
3613 return false;
3614 }
3615 return true;
3616 }
3617
3618 INIT_PLACE(2, 9) {
3619 // BUG: This dialog gets played twice when Monseigneur is waiting for the sketches and we speak to him
3620 // The bug is in original version too
3621 if (_gameVariables[GameVariables::kSketchState] == 1 && currentGameTime() == 2) {
3622 // Sketches are not yet sorted
3623 _dialogsMan["{JOUEUR-SE-DIRIGE-VERS-MONSEIGNEUR-AVEC-ESQUISSES}"] = 'Y';
3624
3625 _dialogsMan.play("22G_DAU");
3626
3627 _forcePaletteUpdate = true;
3628 // Force reload of the place
3629 if (_nextPlaceId == uint(-1)) {
3630 _nextPlaceId = _currentPlaceId;
3631 }
3632
3633 // Change warp viewpoint
3634 _omni3dMan.setAlpha(4.17);
3635 _omni3dMan.setBeta(0.097);
3636
3637 _inventory.deselectObject();
3638
3639 _dialogsMan["{JOUEUR-SE-DIRIGE-VERS-MONSEIGNEUR-AVEC-ESQUISSES}"] = 'N';
3640 }
3641 }
3642
3643 FILTER_EVENT(2, 9) {
3644 if (*event == 22902 && _inventory.selectedObject() &&
3645 _inventory.selectedObject()->idOBJ() == 105) {
3646 _dialogsMan["{JOUEUR-DONNE-ESQUISSES}"] = 'Y';
3647
3648 _dialogsMan.setIgnoreNoEndOfConversation(true);
3649 _dialogsMan.play("22G_DAU");
3650 _dialogsMan.setIgnoreNoEndOfConversation(false);
3651
3652 _forcePaletteUpdate = true;
3653 // Force reload of the place
3654 if (_nextPlaceId == uint(-1)) {
3655 _nextPlaceId = _currentPlaceId;
3656 }
3657
3658 _dialogsMan["{JOUEUR-DONNE-ESQUISSES}"] = 'N';
3659
3660 _inventory.deselectObject();
3661 } else if (*event >= 1 && *event <= 9999 && currentGameTime() == 3 &&
3662 _placeStates[9].state != 2) {
3663 setPlaceState(9, 2);
3664 }
3665 return true;
3666 }
3667
3668 FILTER_EVENT(2, 11) {
3669 if (*event == 22111 && _inventory.selectedObject()) {
3670 bool gameOver = false;
3671 uint idOBJ = _inventory.selectedObject()->idOBJ();
3672 if (idOBJ == 107) {
3673 _dialogsMan["{JOUEUR-MONTRE-TITRE-FABLE-APPARU-SUR-ESQUISSE}"] = 'Y';
3674 } else if (idOBJ == 109) {
3675 _dialogsMan["{JOUEUR-MONTRE-ESQUISSE-DETRUITE}"] = 'Y';
3676 gameOver = true;
3677 }
3678
3679 _dialogsMan.play("24Z_BON");
3680
3681 _forcePaletteUpdate = true;
3682 // Force reload of the place
3683 if (_nextPlaceId == uint(-1)) {
3684 _nextPlaceId = _currentPlaceId;
3685 }
3686
3687 _dialogsMan["{JOUEUR-MONTRE-TITRE-FABLE-APPARU-SUR-ESQUISSE}"] = 'N';
3688 _dialogsMan["{JOUEUR-MONTRE-ESQUISSE-DETRUITE}"] = 'N';
3689
3690 _inventory.deselectObject();
3691
3692 if (gameOver) {
3693 doGameOver();
3694 }
3695 }
3696 return true;
3697 }
3698
3699 FILTER_EVENT(2, 12) {
3700 if (*event == 22121 && _inventory.selectedObject()) {
3701 uint idOBJ = _inventory.selectedObject()->idOBJ();
3702 if (idOBJ == 105) {
3703 _dialogsMan["{LE JOUEUR-PRESENTE-AUTRES-ESQUISSES-OU-ESQUISSE-NON-TRIEES}"] = 'Y';
3704 _dialogsMan["{JOUEUR-A-MONTRE-ESQUISSES-NON-TRIEES-LEBRUN}"] = 'Y';
3705 } else if (idOBJ == 106) {
3706 _dialogsMan["{LE JOUEUR-PRESENTE-ESQUISSES-TRIEES}"] = 'Y';
3707 _inventory.removeByNameID(106);
3708 } else if (idOBJ == 107 && _gameVariables[GameVariables::kSketchState] == 2) {
3709 if (_gameVariables[GameVariables::kFakeSketchChatState] == 0) {
3710 _dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS}"] = 'Y';
3711 _gameVariables[GameVariables::kFakeSketchChatState] = 1;
3712 } else if (_gameVariables[GameVariables::kFakeSketchChatState] == 1) {
3713 _dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS2}"] = 'Y';
3714 _gameVariables[GameVariables::kFakeSketchChatState] = 2;
3715 } else if (_gameVariables[GameVariables::kFakeSketchChatState] == 2) {
3716 _dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS3}"] = 'Y';
3717 }
3718 } else if (idOBJ == 96) {
3719 _dialogsMan["{JOUEUR-PRESENTE-PAMPHLET-SUR-LEBRUN}"] = 'Y';
3720 } else {
3721 _dialogsMan["{JOUEUR-PRESENTE-TOUT-AUTRE-PAMPHLET-OU-LETTRE}"] = 'Y';
3722 }
3723
3724 _dialogsMan.play("23I_LEB");
3725
3726 _forcePaletteUpdate = true;
3727 // Force reload of the place
3728 if (_nextPlaceId == uint(-1)) {
3729 _nextPlaceId = _currentPlaceId;
3730 }
3731
3732 _dialogsMan["{JOUEUR-PRESENTE-PAMPHLET-SUR-LEBRUN}"] = 'N';
3733 _dialogsMan["{LE JOUEUR-PRESENTE-AUTRES-ESQUISSES-OU-ESQUISSE-NON-TRIEES}"] = 'N';
3734 _dialogsMan["{LE JOUEUR-PRESENTE-ESQUISSES-TRIEES}"] = 'N';
3735 _dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS}"] = 'N';
3736 _dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS2}"] = 'N';
3737 _dialogsMan["{JOUEUR-PRESENTE-FAUX-CROQUIS3}"] = 'N';
3738 _dialogsMan["{JOUEUR-PRESENTE-TOUT-AUTRE-PAMPHLET-OU-LETTRE}"] = 'N';
3739
3740 _inventory.deselectObject();
3741 } else if (*event == 32120) {
3742 if (_inventory.selectedObject() &&
3743 _inventory.selectedObject()->idOBJ() == 107 &&
3744 _gameVariables[GameVariables::kSketchState] == 2) {
3745 handleFixedImg(&CryOmni3DEngine_Versailles::img_32120);
3746 }
3747 // We handle use here
3748 return false;
3749 }
3750 return true;
3751 }
3752
3753 FILTER_EVENT(2, 14) {
3754 return filterEventLevel1Place14(event);
3755 }
3756
3757 FILTER_EVENT(3, 3) {
3758 if (*event == 23030 && _inventory.selectedObject() &&
3759 _inventory.selectedObject()->idOBJ() == 118 &&
3760 _gameVariables[GameVariables::kDecipherScore]) {
3761 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-DECHIFFRE-PAR-LULLY}"] = 'Y';
3762 _dialogsMan.play("31X_BON");
3763
3764 _forcePaletteUpdate = true;
3765 // Force reload of the place
3766 if (_nextPlaceId == uint(-1)) {
3767 _nextPlaceId = _currentPlaceId;
3768 }
3769
3770 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-DECHIFFRE-PAR-LULLY}"] = 'N';
3771 _inventory.deselectObject();
3772 }
3773 return true;
3774 }
3775
3776 FILTER_EVENT(3, 10) {
3777 if (*event == 23101 && _inventory.selectedObject() &&
3778 _inventory.selectedObject()->idOBJ() == 120) {
3779 _inventory.removeByNameID(120);
3780
3781 _dialogsMan["{JOUEUR-MONTRE-AUTORISATION-DE-BONTEMPS}"] = 'Y';
3782 _dialogsMan.play("31O_SUIP");
3783
3784 _forcePaletteUpdate = true;
3785 // Force reload of the place
3786 if (_nextPlaceId == uint(-1)) {
3787 _nextPlaceId = _currentPlaceId;
3788 }
3789
3790 _dialogsMan["{JOUEUR-MONTRE-AUTORISATION-DE-BONTEMPS}"] = 'N';
3791 _inventory.deselectObject();
3792 return true;
3793 } else if (*event == 21) {
3794 if (_dialogsMan["SUISSE-VU-AUTORISATION"] == 'Y') {
3795 fakeTransition(*event);
3796 playInGameVideo("33O_SUIP");
3797 playInGameVideo("33O_P");
3798 executeSeeAction(88001);
3799 if (!shouldAbort()) {
3800 playInGameVideo("33P_O");
3801 }
3802 _forcePaletteUpdate = true;
3803 // Force reload of the place
3804 if (_nextPlaceId == uint(-1)) {
3805 _nextPlaceId = _currentPlaceId;
3806 }
3807 }
3808 // This place is a fake one: so never go in there
3809 return false;
3810 }
3811 return true;
3812 }
3813
3814 FILTER_EVENT(3, 13) {
3815 _dialogsMan["{JOUEUR-MONTRE-FUSAIN-MEDAILLES}"] = 'N';
3816 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
3817 if (*event == 33130 && !_inventory.inInventoryByNameID(119)) {
3818 collectObject(119);
3819 if (_placeStates[13].state) {
3820 setPlaceState(13, 3);
3821 } else {
3822 setPlaceState(13, 1);
3823 }
3824 // We handle use here
3825 return false;
3826 } else if (*event == 23131 && _inventory.selectedObject()) {
3827 if (_inventory.selectedObject()->idOBJ() == 121) {
3828 _dialogsMan["{JOUEUR-MONTRE-FUSAIN-MEDAILLES}"] = 'Y';
3829 } else {
3830 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
3831 }
3832 _dialogsMan.play("32M_MR");
3833
3834 _forcePaletteUpdate = true;
3835 // Force reload of the place
3836 if (_nextPlaceId == uint(-1)) {
3837 _nextPlaceId = _currentPlaceId;
3838 }
3839
3840 _dialogsMan["{JOUEUR-MONTRE-FUSAIN-MEDAILLES}"] = 'N';
3841 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
3842 _inventory.deselectObject();
3843 return true;
3844 } else {
3845 return true;
3846 }
3847 }
3848
3849 FILTER_EVENT(3, 15) {
3850 if (*event == 23151 && _inventory.selectedObject()) {
3851 return filterEventLevel3Obj23151();
3852 }
3853 return true;
3854 }
3855
3856 FILTER_EVENT(3, 17) {
3857 if (*event == 18) {
3858 if (_inventory.selectedObject() &&
3859 _inventory.selectedObject()->idOBJ() == 123) {
3860 _gameVariables[GameVariables::kUnlockHiddenDoor] = 1;
3861 _inventory.removeByNameID(123);
3862 return true;
3863 } else if (_gameVariables[GameVariables::kUnlockHiddenDoor] != 1) {
3864 // Locked
3865 displayMessageBoxWarp(1);
3866 _dialogsMan["{LE JOUEUR-A-TENTE-OUVRIR-PETITE-PORTE}"] = 'Y';
3867 return false;
3868 } else {
3869 return true;
3870 }
3871 } else if (*event == 23151) {
3872 return filterEventLevel3Obj23151();
3873 } else {
3874 return true;
3875 }
3876 }
3877
3878 FILTER_EVENT(3, 18) {
3879 if (*event != 19) {
3880 return true;
3881 }
3882
3883 // Only take care of event 19
3884
3885 // Adjust camera
3886 fakeTransition(*event);
3887 // As we have just adjusted camera, don't do it later
3888 _transitionAnimateWarp = false;
3889
3890 if (_placeStates[22].state) {
3891 playInGameVideo("31J1_L2");
3892 } else if (_gameVariables[GameVariables::kAlreadyWent3_19]) {
3893 playInGameVideo("31J1_L1");
3894 } else {
3895 playInGameVideo("31J1_L0");
3896 playInGameVideo("31L1_AL2");
3897 playInGameVideo("31L1_AL3");
3898 _gameVariables[GameVariables::kAlreadyWent3_19] = 1;
3899 _gameVariables[GameVariables::kCabinetDrawerStatus] = 1;
3900 }
3901
3902 _forcePaletteUpdate = true;
3903 // Force reload of the place
3904 if (_nextPlaceId == uint(-1)) {
3905 _nextPlaceId = _currentPlaceId;
3906 }
3907 return true;
3908 }
3909
3910 FILTER_EVENT(3, 19) {
3911 if (*event != 18) {
3912 return true;
3913 }
3914 if (currentGameTime() != 3 || _placeStates[22].state) {
3915 return true;
3916 }
3917
3918 if (_gameVariables[GameVariables::kCollectLampoonArchitecture]) {
3919 setPlaceState(22, 2);
3920 } else {
3921 setPlaceState(22, 1);
3922 }
3923 setPlaceState(19, 1);
3924
3925 return true;
3926 }
3927
3928 FILTER_EVENT(3_5, 20) {
3929 if (*event != 25) {
3930 return true;
3931 }
3932
3933 fakeTransition(*event);
3934 playInGameVideo("31j31");
3935
3936 // Force reload of the place
3937 if (_nextPlaceId == uint(-1)) {
3938 _nextPlaceId = _currentPlaceId;
3939 }
3940
3941 // Toilets
3942 executeSeeAction(88004);
3943
3944 _forcePaletteUpdate = true;
3945
3946 return false;
3947 }
3948
3949 FILTER_EVENT(3, 22) {
3950 if (*event == 33220) {
3951 if (!_gameVariables[GameVariables::kCollectLampoonArchitecture]) {
3952 if (_inventory.selectedObject() &&
3953 _inventory.selectedObject()->idOBJ() == 119) {
3954 // Using pool cue
3955 _inventory.removeByNameID(119);
3956 collectLampoonArchitecture();
3957 _forcePaletteUpdate = true;
3958 } else {
3959 // Paper is out of reach
3960 displayMessageBoxWarp(16);
3961 }
3962 }
3963 // We handle use here
3964 return false;
3965 }
3966
3967 if (*event >= 20000 && *event < 30000 &&
3968 _inventory.selectedObject() &&
3969 _inventory.selectedObject()->idOBJ() == 118) {
3970 _dialogsMan["{JOUEUR-PRESENTE-PAMPHLET-PARTITION}"] = 'Y';
3971 _dialogsMan.play("31L1_LUL");
3972
3973 _forcePaletteUpdate = true;
3974 // Force reload of the place
3975 if (_nextPlaceId == uint(-1)) {
3976 _nextPlaceId = _currentPlaceId;
3977 }
3978
3979 _dialogsMan["{JOUEUR-PRESENTE-PAMPHLET-PARTITION}"] = 'N';
3980 if (_dialogsMan["LULLY-DONNE-MISSION1-JOUEUR"] != 'Y' ||
3981 _gameVariables[GameVariables::kDecipherScore]) {
3982 _inventory.deselectObject();
3983 } else {
3984 _inventory.removeByNameID(118);
3985 }
3986 }
3987 return true;
3988 }
3989
3990 FILTER_EVENT(3, 23) {
3991 if (*event != 32) {
3992 return true;
3993 }
3994
3995 if (_inventory.selectedObject() &&
3996 _inventory.selectedObject()->idOBJ() == 140) {
3997 _gameVariables[GameVariables::kUnlockedAttic] = 1;
3998 _inventory.removeByNameID(140);
3999 return true;
4000 } else if (_gameVariables[GameVariables::kUnlockedAttic] != 1) {
4001 // Locked
4002 displayMessageBoxWarp(1);
4003 return false;
4004 } else {
4005 return true;
4006 }
4007 }
4008
filterEventLevel3Obj23151()4009 bool CryOmni3DEngine_Versailles::filterEventLevel3Obj23151() {
4010 if (_inventory.selectedObject() &&
4011 _inventory.selectedObject()->idOBJ() == 115) {
4012 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'Y';
4013 } else if (_inventory.selectedObject() &&
4014 _inventory.selectedObject()->idOBJ() == 121 &&
4015 _gameVariables[GameVariables::kGotMedalsSolution]) {
4016 _inventory.removeByNameID(121);
4017 _dialogsMan["{JOUEUR-MONTRE-EPIGRAPHE-MEDAILLES}"] = 'Y';
4018 } else {
4019 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-CHOSE}"] = 'Y';
4020 }
4021
4022 _dialogsMan.play("32J_CRO");
4023
4024 _forcePaletteUpdate = true;
4025 // Force reload of the place
4026 if (_nextPlaceId == uint(-1)) {
4027 _nextPlaceId = _currentPlaceId;
4028 }
4029
4030 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'N';
4031 _dialogsMan["{JOUEUR-MONTRE-EPIGRAPHE-MEDAILLES}"] = 'N';
4032 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-CHOSE}"] = 'N';
4033
4034 _inventory.deselectObject();
4035
4036 return true;
4037 }
4038
collectLampoonArchitecture(const ZonFixedImage * fimg)4039 void CryOmni3DEngine_Versailles::collectLampoonArchitecture(const ZonFixedImage *fimg) {
4040 _gameVariables[GameVariables::kCollectLampoonArchitecture] = 1;
4041 collectObject(115, fimg);
4042 if (_currentLevel == 3) {
4043 setPlaceState(22, 2);
4044 }
4045 _dialogsMan["{JOUEUR_POSSEDE_PAMPHLET_ARCHI}"] = 'Y';
4046 }
4047
4048 INIT_PLACE(4, 9) {
4049 if (currentGameTime() == 4 && !_inventory.inInventoryByNameID(125)) {
4050 _dialogsMan.play("4_MAI");
4051 _forcePaletteUpdate = true;
4052 // Force reload of the place
4053 if (_nextPlaceId == uint(-1)) {
4054 _nextPlaceId = _currentPlaceId;
4055 }
4056 }
4057 }
4058
4059 FILTER_EVENT(4, 10) {
4060 if (*event == 24104 && _inventory.selectedObject()) {
4061 _dialogsMan["{JOUEUR-PRESENTE-OBJET-HUISSIER}"] = 'Y';
4062 _dialogsMan.play("41C_HUI");
4063
4064 _forcePaletteUpdate = true;
4065 // Force reload of the place
4066 if (_nextPlaceId == uint(-1)) {
4067 _nextPlaceId = _currentPlaceId;
4068 }
4069
4070 _dialogsMan["{JOUEUR-PRESENTE-OBJET-HUISSIER}"] = 'N';
4071 _inventory.deselectObject();
4072 return true;
4073 } else if (*event == 24105 && _inventory.selectedObject()) {
4074 if (_inventory.selectedObject()->idOBJ() == 127) {
4075 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-GOUVERNEMENT}"] = 'Y';
4076 } else if (_inventory.selectedObject()->idOBJ() == 125) {
4077 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'Y';
4078 } else if (_inventory.selectedObject()->idOBJ() == 126) {
4079 _dialogsMan["{JOUEUR-MONTRE-PAPIER-CROISSY}"] = 'Y';
4080 } else {
4081 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
4082 }
4083 _dialogsMan.play("42C_BON");
4084
4085 _forcePaletteUpdate = true;
4086 // Force reload of the place
4087 if (_nextPlaceId == uint(-1)) {
4088 _nextPlaceId = _currentPlaceId;
4089 }
4090
4091 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-GOUVERNEMENT}"] = 'N';
4092 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'N';
4093 _dialogsMan["{JOUEUR-MONTRE-PAPIER-CROISSY}"] = 'N';
4094 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
4095 _inventory.deselectObject();
4096 return true;
4097 } else if (*event == 11 && currentGameTime() < 3) {
4098 // Closed
4099 displayMessageBoxWarp(2);
4100 return false;
4101 } else {
4102 return true;
4103 }
4104 }
4105
4106 FILTER_EVENT(4, 12_13_14) {
4107 if (*event != 34131 && *event != 34132) {
4108 // Not for us
4109 return true;
4110 }
4111
4112 if (!_inventory.selectedObject() ||
4113 _inventory.selectedObject()->idOBJ() != 130) {
4114 // Not using scope: do nothing
4115 return false;
4116 }
4117
4118 // Using scope
4119 const char *video;
4120 FixedImgCallback callback;
4121
4122 if (*event == 34131) {
4123 video = "43ZA_1";
4124 callback = &CryOmni3DEngine_Versailles::img_34131;
4125 } else if (*event == 34132) {
4126 video = "43ZB_2";
4127 callback = &CryOmni3DEngine_Versailles::img_34132;
4128 } else {
4129 error("BUG: Shouldn't be here");
4130 }
4131
4132 playInGameVideo(video);
4133
4134 // Force reload of the place
4135 if (_nextPlaceId == uint(-1)) {
4136 _nextPlaceId = _currentPlaceId;
4137 }
4138
4139 handleFixedImg(callback);
4140
4141 // Don't pass the event: it has been handled
4142 return false;
4143 }
4144
4145 FILTER_EVENT(4, 15) {
4146 if (*event == 17 && (_dialogsMan["BONTEMPS-VU-PAPIER-CROISSY"] == 'N' ||
4147 _dialogsMan["BONTEMPS-VU-PAMPHLET-GOUVERNEMENT"] == 'N')) {
4148 // Closed
4149 displayMessageBoxWarp(2);
4150 return false;
4151 }
4152
4153 return true;
4154 }
4155
4156 FILTER_EVENT(4, 16) {
4157 if (*event == 24161 && _inventory.selectedObject()) {
4158 uint idOBJ = _inventory.selectedObject()->idOBJ();
4159 if (idOBJ == 124) {
4160 _dialogsMan["{JOUEUR-DONNE-REPAS}"] = 'Y';
4161 } else {
4162 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
4163 }
4164 _dialogsMan.play("41X2_CRO");
4165
4166 _forcePaletteUpdate = true;
4167 // Force reload of the place
4168 if (_nextPlaceId == uint(-1)) {
4169 _nextPlaceId = _currentPlaceId;
4170 }
4171
4172 _dialogsMan["{JOUEUR-DONNE-REPAS}"] = 'N';
4173 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
4174
4175 if (idOBJ == 124) {
4176 _inventory.removeByNameID(124);
4177 playInGameVideo("41X2_CR1");
4178 setGameTime(2, 4);
4179 }
4180 _inventory.deselectObject();
4181 return true;
4182 } else if (*event == 34162) {
4183 if (!_inventory.inInventoryByNameID(127)) {
4184 collectObject(127);
4185 _forcePaletteUpdate = true;
4186 } else {
4187 // Nothing there anymore
4188 displayMessageBoxWarp(21);
4189 }
4190
4191 // Don't pass the event: it has been handled
4192 return false;
4193 }
4194 return true;
4195 }
4196
4197 FILTER_EVENT(4, 17) {
4198 if (*event == 34171) {
4199 collectObject(130);
4200 setPlaceState(17, 1);
4201 return false;
4202 } else if (*event == 34172) {
4203 uint fakePlaceId = getFakeTransition(*event);
4204 fakeTransition(fakePlaceId);
4205 handleFixedImg(&CryOmni3DEngine_Versailles::img_34172);
4206 return false;
4207 } else if (*event == 34173) {
4208 handleFixedImg(&CryOmni3DEngine_Versailles::img_34173);
4209 return false;
4210 } else if (*event == 34174) {
4211 handleFixedImg(&CryOmni3DEngine_Versailles::img_34174);
4212 return false;
4213 }
4214
4215 return true;
4216 }
4217
4218 INIT_PLACE(5, 6) {
4219 if (currentGameTime() == 2) {
4220 setPlaceState(27, 2);
4221 }
4222 }
4223
4224 FILTER_EVENT(5, 9) {
4225 if (*event == 25090 && _inventory.selectedObject()) {
4226 uint idOBJ = _inventory.selectedObject()->idOBJ();
4227 if (currentGameTime() < 4) {
4228 if (idOBJ == 125 && _gameVariables[GameVariables::kStateLampoonReligion] == 3) {
4229 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'Y';
4230 } else if (idOBJ == 115) {
4231 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'Y';
4232 } else {
4233 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
4234 }
4235
4236 _dialogsMan.play("53N_BON");
4237
4238 _forcePaletteUpdate = true;
4239 // Force reload of the place
4240 if (_nextPlaceId == uint(-1)) {
4241 _nextPlaceId = _currentPlaceId;
4242 }
4243
4244 if (_dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] == 'Y' && currentGameTime() != 3) {
4245 setGameTime(3, 5);
4246 _inventory.removeByNameID(125);
4247 }
4248
4249 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'N';
4250 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'N';
4251 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
4252
4253 _inventory.deselectObject();
4254 } else {
4255 if (_inventory.inInventoryByNameID(135) && _inventory.inInventoryByNameID(116)) {
4256 _dialogsMan["{JOUEUR-POSSEDE-CLEF-3-ET-4}"] = 'Y';
4257 }
4258 // Useless?
4259 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
4260
4261 if (idOBJ == 137) {
4262 _dialogsMan["{JOUEUR-MONTRE-MEMORANDUM}"] = 'Y';
4263 } else {
4264 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
4265 }
4266
4267 _dialogsMan.play("54I_BON");
4268
4269 _forcePaletteUpdate = true;
4270 // Force reload of the place
4271 if (_nextPlaceId == uint(-1)) {
4272 _nextPlaceId = _currentPlaceId;
4273 }
4274
4275 _dialogsMan["{JOUEUR-MONTRE-MEMORANDUM}"] = 'N';
4276 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
4277
4278 _inventory.deselectObject();
4279 }
4280 }
4281
4282 return true;
4283 }
4284
4285 FILTER_EVENT(5, 14) {
4286 if (*event == 25142 && _inventory.selectedObject()) {
4287 uint idOBJ = _inventory.selectedObject()->idOBJ();
4288 if (idOBJ == 125) {
4289 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'Y';
4290 } else {
4291 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'Y';
4292 }
4293
4294 _dialogsMan.play("52L_BOU");
4295
4296 _forcePaletteUpdate = true;
4297 // Force reload of the place
4298 if (_nextPlaceId == uint(-1)) {
4299 _nextPlaceId = _currentPlaceId;
4300 }
4301
4302 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'N';
4303 _dialogsMan["{JOUEUR-MONTRE-TOUT-AUTRE-OBJET}"] = 'N';
4304 _inventory.deselectObject();
4305 }
4306
4307 return true;
4308 }
4309
4310 FILTER_EVENT(5, 15) {
4311 if (*event == 16 && _gameVariables[GameVariables::kLoweredChandelier]) {
4312 *event = 29;
4313 }
4314
4315 return true;
4316 }
4317
4318 FILTER_EVENT(5, 16) {
4319 if (*event == 35162) {
4320 // Don't move the ladder when there is a guard
4321 if (_placeStates[16].state != 0) {
4322 // Take back the ladder from the scaffolding
4323 if (_gameVariables[GameVariables::kLadderState] == 2) {
4324 collectObject(108);
4325 _gameVariables[GameVariables::kLadderState] = 1;
4326 filterEventLevel5UpdatePlaceStates();
4327 }
4328 }
4329 // Handled here
4330 return false;
4331 } else if (*event == 35160) {
4332 // Don't move the ladder when there is a guard
4333 if (_placeStates[16].state != 0) {
4334 if (_gameVariables[GameVariables::kLadderState] == 0) {
4335 // Take the ladder from the curtain
4336 collectObject(108);
4337 _gameVariables[GameVariables::kLadderState] = 1;
4338 filterEventLevel5UpdatePlaceStates();
4339 } else if (_gameVariables[GameVariables::kLadderState] == 1 &&
4340 _inventory.selectedObject() &&
4341 _inventory.selectedObject()->idOBJ() == 108) {
4342 // Put back the ladder
4343 _inventory.removeByNameID(108);
4344 _gameVariables[GameVariables::kLadderState] = 0;
4345 filterEventLevel5UpdatePlaceStates();
4346 }
4347 }
4348 // Handled here
4349 return false;
4350 } else if (*event == 35161) {
4351 // Don't move the ladder when there is a guard
4352 if (_placeStates[16].state != 0) {
4353 if (!_gameVariables[GameVariables::kOpenedCurtain] &&
4354 _inventory.selectedObject() &&
4355 _inventory.selectedObject()->idOBJ() == 133) {
4356 // Try to open the curtain
4357 if (_gameVariables[GameVariables::kLadderState]) {
4358 // Ladder is not near the curtain
4359 // Cannot reach the covering
4360 displayMessageBoxWarp(4);
4361 } else {
4362 _inventory.removeByNameID(133);
4363 _gameVariables[GameVariables::kOpenedCurtain] = 1;
4364 filterEventLevel5UpdatePlaceStates();
4365 }
4366 }
4367 }
4368 // Handled here
4369 return false;
4370 } else if (*event == 28) {
4371 // Try to go to scaffolding
4372 if (_gameVariables[GameVariables::kLadderState] == 1 &&
4373 _inventory.selectedObject() &&
4374 _inventory.selectedObject()->idOBJ() == 108) {
4375 // Put the ladder on the scaffolding
4376 _inventory.removeByNameID(108);
4377 _gameVariables[GameVariables::kLadderState] = 2;
4378 filterEventLevel5UpdatePlaceStates();
4379 }
4380 // Don't move if there is no ladder on the scaffolding
4381 // Don't take selected object into account
4382 return _gameVariables[GameVariables::kLadderState] == 2;
4383 } else if (*event == 15 && _inventory.inInventoryByNameID(108)) {
4384 // Cannot move carrying ladder
4385 displayMessageBoxWarp(20);
4386 return false;
4387 } else {
4388 return true;
4389 }
4390 }
4391
filterEventLevel5UpdatePlaceStates()4392 void CryOmni3DEngine_Versailles::filterEventLevel5UpdatePlaceStates() {
4393 // Place 28 (mirror of 16 with chandelier on the floor) only depends on curtain state
4394 setPlaceState(28, _gameVariables[GameVariables::kOpenedCurtain]);
4395 if (!_gameVariables[GameVariables::kOpenedCurtain]) {
4396 // Curtain is closed
4397 switch (_gameVariables[GameVariables::kLadderState]) {
4398 case 0:
4399 // Ladder is near the curtain
4400 setPlaceState(16, 2);
4401 break;
4402 case 1:
4403 // Ladder is with us
4404 setPlaceState(16, 4);
4405 break;
4406 case 2:
4407 // Ladder is on the scaffolding
4408 setPlaceState(16, 5);
4409 break;
4410 default:
4411 error("BUG: Invalid ladder state");
4412 break;
4413 }
4414 } else {
4415 // Curtain is opened
4416 switch (_gameVariables[GameVariables::kLadderState]) {
4417 case 0:
4418 // Ladder is near the curtain
4419 setPlaceState(16, 1);
4420 break;
4421 case 1:
4422 // Ladder is with us
4423 setPlaceState(16, 3);
4424 break;
4425 case 2:
4426 // Ladder is on the scaffolding
4427 setPlaceState(16, 6);
4428 break;
4429 default:
4430 error("BUG: Invalid ladder state");
4431 break;
4432 }
4433 }
4434 }
4435
4436 FILTER_EVENT(5, 23) {
4437 if (*event != 32) {
4438 return true;
4439 }
4440
4441 // Event 32 only
4442 // Try to open attic door
4443 if (_inventory.selectedObject() &&
4444 _inventory.selectedObject()->idOBJ() == 140) {
4445 _gameVariables[GameVariables::kUnlockedAttic] = 1;
4446 _inventory.removeByNameID(140);
4447 return true;
4448 } else if (_gameVariables[GameVariables::kUnlockedAttic] != 1) {
4449 // Locked
4450 displayMessageBoxWarp(1);
4451 return false;
4452 } else {
4453 return true;
4454 }
4455 }
4456
4457 FILTER_EVENT(5, 27) {
4458 if (*event == 25270) {
4459 if (_inventory.selectedObject()) {
4460 uint idOBJ = _inventory.selectedObject()->idOBJ();
4461 if (idOBJ == 115) {
4462 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'Y';
4463 } else if (idOBJ == 125) {
4464 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'Y';
4465 } else if (idOBJ == 134) {
4466 _dialogsMan["{JOUEUR-MONTRE-ECROUELLES}"] = 'Y';
4467 }
4468
4469 _dialogsMan.play("52A4_LAC");
4470
4471 _forcePaletteUpdate = true;
4472 // Force reload of the place
4473 if (_nextPlaceId == uint(-1)) {
4474 _nextPlaceId = _currentPlaceId;
4475 }
4476
4477 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-ARCHITECTURE}"] = 'N';
4478 _dialogsMan["{JOUEUR-MONTRE-PAMPHLET-RELIGION}"] = 'N';
4479 _dialogsMan["{JOUEUR-MONTRE-ECROUELLES}"] = 'N';
4480
4481 if (_dialogsMan["LACHAIZE-TROUVE-ECROUELLES"] == 'Y') {
4482 _inventory.removeByNameID(134);
4483 }
4484 _inventory.deselectObject();
4485 }
4486 } else if (*event == 35270) {
4487 if (!_inventory.inInventoryByNameID(133)) {
4488 collectObject(133);
4489 _gameVariables[GameVariables::kCollectCord] = 1;
4490 setPlaceState(27, 1);
4491 }
4492 // Handled here
4493 return false;
4494 } else if (*event > 0 && *event < 10000 && currentGameTime() == 1 &&
4495 _gameVariables[GameVariables::kCollectCord]) {
4496 setGameTime(2, 5);
4497 }
4498
4499 return true;
4500 }
4501
4502 FILTER_EVENT(5, 28) {
4503 if (*event == 45280 && !_gameVariables[GameVariables::kOpenedCurtain]) {
4504 // Too dark
4505 displayMessageBoxWarp(7);
4506 }
4507
4508 return true;
4509 }
4510
4511 FILTER_EVENT(5, 29) {
4512 if (*event == 35290 && _placeStates[29].state == 0) {
4513 // Collect memorandum
4514 collectObject(137);
4515 setPlaceState(29, 1);
4516 // Handled here
4517 return false;
4518 }
4519
4520 return true;
4521 }
4522
4523 FILTER_EVENT(5, 33) {
4524 if (*event == 35330 && !_gameVariables[GameVariables::kLoweredChandelier]) {
4525 uint fakePlaceId = getFakeTransition(*event);
4526 fakeTransition(fakePlaceId);
4527
4528 playInGameVideo("LUSTRE");
4529 // setPlaceState will force reload
4530
4531 setPlaceState(33, 1);
4532 setGameTime(4, 5);
4533
4534 _gameVariables[GameVariables::kLoweredChandelier] = 1;
4535
4536 // Handled here
4537 return false;
4538 }
4539
4540 return true;
4541 }
4542
4543 FILTER_EVENT(5, 34) {
4544 if (*event == 35) {
4545 fakeTransition(*event);
4546
4547 playInGameVideo("53z1c_10");
4548
4549 executeSeeAction(88002);
4550
4551 _forcePaletteUpdate = true;
4552 // Force reload of the place
4553 if (_nextPlaceId == uint(-1)) {
4554 _nextPlaceId = _currentPlaceId;
4555 }
4556 // Handled here
4557 return false;
4558 }
4559
4560 return true;
4561 }
4562
4563 FILTER_EVENT(6, 1) {
4564 if (*event == 36010 && _placeStates[1].state == 0) {
4565 collectObject(144);
4566 setPlaceState(1, 1);
4567 // Handled here
4568 return false;
4569 }
4570
4571 return true;
4572 }
4573
4574 FILTER_EVENT(6, 3) {
4575 if (!filterEventLevel6PlaceOrangery(event)) {
4576 // Handled
4577 return false;
4578 } else if (*event == 36030 && _placeStates[3].state == 0) {
4579 collectObject(143);
4580 setPlaceState(3, 1);
4581 // Handled here
4582 return false;
4583 } else if (*event == 1) {
4584 // To apothecary
4585 displayMessageBoxWarp(17);
4586 }
4587
4588 return true;
4589 }
4590
4591 FILTER_EVENT(6, Orangery) {
4592 if (*event == 36000) {
4593 if (_inventory.selectedObject() &&
4594 _inventory.selectedObject()->idOBJ() == 143) {
4595 _gameVariables[GameVariables::kCombedOrangeTree]++; // Not used afterwards
4596 displayMessageBoxWarp(5);
4597 }
4598 // Handled here
4599 return false;
4600 } else if (*event == 36001) {
4601 if (_inventory.selectedObject() &&
4602 _inventory.selectedObject()->idOBJ() == 143) {
4603 displayMessageBoxWarp(6);
4604 }
4605 // Handled here
4606 return false;
4607 }
4608
4609 return true;
4610 }
4611
4612 FILTER_EVENT(6, 19) {
4613 if (*event == 26190 && _inventory.selectedObject() &&
4614 _placeStates[19].state == 0) {
4615 if (!_gameVariables[GameVariables::kMaineTalked]) {
4616 if (_inventory.selectedObject()->idOBJ() == 144) {
4617 _dialogsMan["{JOUEUR-DONNE-AUTRE-MEDICAMENT}"] = 'Y';
4618 }
4619
4620 _dialogsMan.play("61_DUC");
4621 } else {
4622 if (_inventory.selectedObject()->idOBJ() == 144) {
4623 _dialogsMan["{JOUEUR-DONNE-SIROP-DE-ROSE}"] = 'Y';
4624 _dialogsMan.setIgnoreNoEndOfConversation(true);
4625 }
4626
4627 _dialogsMan.play("62_DUC");
4628 _dialogsMan.setIgnoreNoEndOfConversation(false);
4629 }
4630
4631 _forcePaletteUpdate = true;
4632 // Force reload of the place
4633 if (_nextPlaceId == uint(-1)) {
4634 _nextPlaceId = _currentPlaceId;
4635 }
4636
4637 _dialogsMan["{JOUEUR-DONNE-AUTRE-MEDICAMENT}"] = 'N';
4638 _dialogsMan["{JOUEUR-DONNE-SIROP-DE-ROSE}"] = 'N';
4639
4640 _inventory.deselectObject();
4641 } else if (*event > 0 && *event < 10000 && _dialogsMan["{DUC_MAIN_A_PARLE}"] == 'Y') {
4642 _gameVariables[GameVariables::kMaineTalked] = 1;
4643 _whoSpeaksWhere[PlaceActionKey(19, 16190)] = "62_DUC";
4644 } else if (*event == 36190 && _placeStates[19].state == 1) {
4645 collectObject(142);
4646 setGameTime(2, 6);
4647 // Handled here
4648 return false;
4649 }
4650
4651 return true;
4652 }
4653
4654 FILTER_EVENT(7, 2) {
4655 if (*event == 37021) {
4656 if (_inventory.selectedObject() &&
4657 _inventory.selectedObject()->idOBJ() == 103) {
4658 // Light the candle
4659 _inventory.removeByNameID(103);
4660 collectObject(102);
4661 }
4662 // Handled here
4663 return false;
4664 } else if (*event == 37022) {
4665 if (!_inventory.inInventoryByNameID(97)) {
4666 collectObject(97);
4667 _inventory.deselectObject();
4668 } else {
4669 // Jar is empty
4670 displayMessageBoxWarp(11);
4671 }
4672 // Handled here
4673 return false;
4674 } else if (*event == 7) {
4675 // Stairs
4676 if (_gameVariables[GameVariables::kUsedLitCandle]) {
4677 return true;
4678 }
4679
4680 if (_inventory.selectedObject() &&
4681 _inventory.selectedObject()->idOBJ() == 102) {
4682 // Now you can go
4683 displayMessageBoxWarp(12);
4684 _inventory.removeByNameID(102);
4685 _inventory.deselectObject();
4686 // Save it for later
4687 _gameVariables[GameVariables::kUsedLitCandle] = 1;
4688
4689 return true;
4690 }
4691
4692 // Didn't used lit candle and not using it now: denied
4693 // Too dark
4694 displayMessageBoxWarp(7);
4695 return false;
4696 }
4697
4698 return true;
4699 }
4700
4701 FILTER_EVENT(7, 9) {
4702 if (*event == 37090) {
4703 if (_placeStates[9].state == 0) {
4704 // Get the candle snuffer
4705 collectObject(145);
4706 _inventory.deselectObject();
4707 setPlaceState(9, 1);
4708 }
4709 // Handled here
4710 return false;
4711 }
4712
4713 return true;
4714 }
4715
4716 FILTER_EVENT(7, 10_11_13) {
4717 if (*event == 37131) {
4718 if (_inventory.selectedObject() &&
4719 _inventory.selectedObject()->idOBJ() == 143 &&
4720 !_inventory.inInventoryByNameID(136)) {
4721 collectObject(136);
4722 // WORKAROUND: Deselect the tool
4723 _inventory.deselectObject();
4724 }
4725 // Handled here
4726 return false;
4727 } else if (*event == 37132) {
4728 if (_inventory.selectedObject() &&
4729 _inventory.selectedObject()->idOBJ() == 143) {
4730 // Nothing in this orange tree
4731 displayMessageBoxWarp(5);
4732 }
4733 // Handled here
4734 return false;
4735 }
4736
4737 return true;
4738 }
4739
4740 FILTER_EVENT(7, 20) {
4741 if (*event == 21) {
4742 fakeTransition(*event);
4743
4744 playInGameVideo("70z_10");
4745
4746 executeSeeAction(88003);
4747
4748 _forcePaletteUpdate = true;
4749 // Force reload of the place
4750 if (_nextPlaceId == uint(-1)) {
4751 _nextPlaceId = _currentPlaceId;
4752 }
4753 // Handled here
4754 return false;
4755 }
4756
4757 return true;
4758 }
4759
4760 #undef FILTER_EVENT
4761 #undef INIT_PLACE
4762
4763 // Countdown
4764
initCountdown()4765 void CryOmni3DEngine_Versailles::initCountdown() {
4766 strcpy(_countdownValue, "05:00");
4767 if (_gameVariables[GameVariables::kSavedCountdown]) {
4768 uint counter = _gameVariables[GameVariables::kSavedCountdown];
4769 _countdownValue[4] = counter;
4770 counter >>= 8;
4771 _countdownValue[3] = counter;
4772 counter >>= 8;
4773 _countdownValue[1] = counter;
4774 counter >>= 8;
4775 _countdownValue[0] = counter;
4776 }
4777 }
4778
syncCountdown()4779 void CryOmni3DEngine_Versailles::syncCountdown() {
4780 uint counter = 0;
4781 counter |= _countdownValue[0];
4782 counter <<= 8;
4783 counter |= _countdownValue[1];
4784 counter <<= 8;
4785 counter |= _countdownValue[3];
4786 counter <<= 8;
4787 counter |= _countdownValue[4];
4788 _gameVariables[GameVariables::kSavedCountdown] = counter;
4789 }
4790
doCountDown()4791 bool CryOmni3DEngine_Versailles::doCountDown() {
4792 if (g_system->getMillis() > _countdownNextEvent) {
4793 _countdownNextEvent = g_system->getMillis() + 1000;
4794 // Decrement countdown
4795 _countdownValue[4]--;
4796 if (_countdownValue[4] < '0') {
4797 _countdownValue[4] = '9';
4798 _countdownValue[3]--;
4799 if (_countdownValue[3] < '0') {
4800 _countdownValue[3] = '5';
4801 _countdownValue[1]--;
4802 if (_countdownValue[1] < '0') {
4803 _countdownValue[1] = '9';
4804 _countdownValue[0]--;
4805 if (_countdownValue[0] < '0') {
4806 // Finished!
4807 _countingDown = false;
4808 playTransitionEndLevel(8);
4809 _abortCommand = kAbortGameOver;
4810 }
4811 }
4812 }
4813 }
4814
4815 // Redraw surface
4816 _countdownSurface.clear(0);
4817 _fontManager.setCurrentFont(3);
4818 _fontManager.setTransparentBackground(true);
4819 _fontManager.setForeColor(241);
4820 _fontManager.setLineHeight(14);
4821 _fontManager.setSpaceWidth(0);
4822 _fontManager.setCharSpacing(1);
4823 _fontManager.setSurface(&_countdownSurface);
4824
4825 _fontManager.displayStr(0, 2, _countdownValue);
4826
4827 // Surface changed: need redraw
4828 return true;
4829 } else {
4830 return false;
4831 }
4832 }
4833
doDrawCountdown(Graphics::ManagedSurface * surface)4834 void CryOmni3DEngine_Versailles::doDrawCountdown(Graphics::ManagedSurface *surface) {
4835 if (surface) {
4836 surface->blitFrom(_countdownSurface, Common::Point(600, 0));
4837 } else {
4838 g_system->copyRectToScreen(_countdownSurface.getPixels(), _countdownSurface.pitch, 600, 0,
4839 _countdownSurface.w, _countdownSurface.h);
4840 }
4841 }
4842
4843 } // End of namespace Versailles
4844 } // End of namespace CryOmni3D
4845