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