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 "neverhood/diskplayerscene.h"
24 #include "neverhood/gamemodule.h"
25 #include "neverhood/menumodule.h"
26 #include "neverhood/smackerplayer.h"
27 #include "neverhood/modules/module1000_sprites.h"
28 #include "neverhood/modules/module1200_sprites.h"
29 #include "neverhood/modules/module1300.h"
30 #include "neverhood/modules/module1300_sprites.h"
31 #include "neverhood/modules/module1400_sprites.h"
32 #include "neverhood/modules/module2200_sprites.h"
33 
34 namespace Neverhood {
35 
36 static const uint32 kModule1300SoundList[] = {
37 	0x16805648,
38 	0x16805C48,
39 	0xB4964448,
40 	0x96A05481,
41 	0xD0E14441,
42 	0x90815450,
43 	0
44 };
45 
Module1300(NeverhoodEngine * vm,Module * parentModule,int which)46 Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
47 	: Module(vm, parentModule) {
48 
49 	_vm->_soundMan->addMusic(0x61C090, 0x00203197);
50 	_vm->_soundMan->addSoundList(0x61C090, kModule1300SoundList);
51 	_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 50, 600, 20, 150);
52 	_vm->_soundMan->playTwoSounds(0x61C090, 0x48498E46, 0x50399F64, 0);
53 	_vm->_soundMan->setSoundVolume(0x48498E46, 70);
54 	_vm->_soundMan->setSoundVolume(0x50399F64, 70);
55 
56 	if (which < 0) {
57 		if (_vm->gameState().sceneNum >= 1 && _vm->gameState().sceneNum <= 17)
58 			createScene(_vm->gameState().sceneNum, -1);
59 		else
60 			createScene(11, 0);
61 	} else {
62 		switch (which) {
63 		case 0:
64 			createScene(11, 0);
65 			break;
66 		case 1:
67 			createScene(13, 0);
68 			break;
69 		case 2:
70 			createScene(14, 0);
71 			break;
72 		case 3:
73 			createScene(15, 0);
74 			break;
75 		case 4:
76 			createScene(7, 0);
77 			break;
78 		case 5:
79 			createScene(5, 1);
80 			break;
81 		case 6:
82 			createScene(5, 5);
83 			break;
84 		case 7:
85 			createScene(3, 0);
86 			break;
87 		case 8:
88 			createScene(1, 0);
89 			break;
90 		case 9:
91 			createScene(2, 0);
92 			break;
93 		case 10:
94 			createScene(6, 0);
95 			break;
96 		case 11:
97 			createScene(4, 0);
98 			break;
99 		default:
100 			createScene(12, 0);
101 			break;
102 		}
103 	}
104 
105 }
106 
~Module1300()107 Module1300::~Module1300() {
108 	_vm->_soundMan->deleteGroup(0x61C090);
109 }
110 
createScene(int sceneNum,int which)111 void Module1300::createScene(int sceneNum, int which) {
112 	debug(1, "Module1300::createScene(%d, %d)", sceneNum, which);
113 	_sceneNum = sceneNum;
114 	switch (_sceneNum) {
115 	case 1:
116 		_vm->gameState().sceneNum = 1;
117 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
118 		_vm->_soundMan->startMusic(0x00203197, 0, 2);
119 		_childObject = new Scene1302(_vm, this, which);
120 		break;
121 	case 2:
122 		_vm->gameState().sceneNum = 2;
123 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
124 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
125 		_childObject = new Scene1303(_vm, this);
126 		break;
127 	case 3:
128 		_vm->gameState().sceneNum = 3;
129 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
130 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
131 		_childObject = new Scene1304(_vm, this, which);
132 		break;
133 	case 4:
134 		_vm->gameState().sceneNum = 4;
135 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
136 		_vm->_soundMan->startMusic(0x00203197, 0, 2);
137 		_childObject = new Scene1305(_vm, this, which);
138 		break;
139 	case 5:
140 		_vm->gameState().sceneNum = 5;
141 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
142 		_vm->_soundMan->startMusic(0x00203197, 0, 2);
143 		_childObject = new Scene1306(_vm, this, which);
144 		break;
145 	case 6:
146 		_vm->gameState().sceneNum = 6;
147 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
148 		_vm->_soundMan->startMusic(0x00203197, 0, 2);
149 		_childObject = new Scene1307(_vm, this);
150 		break;
151 	case 7:
152 		_vm->gameState().sceneNum = 7;
153 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
154 		_vm->_soundMan->startMusic(0x00203197, 0, 2);
155 		_childObject = new Scene1308(_vm, this, which);
156 		break;
157 	case 8:
158 		_vm->gameState().sceneNum = 8;
159 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
160 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
161 		_childObject = new DiskplayerScene(_vm, this, 1);
162 		break;
163 	case 9:
164 		_vm->gameState().sceneNum = 9;
165 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
166 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
167 		createSmackerScene(0x20082818, true, true, false);
168 		break;
169 	case 10:
170 		_vm->gameState().sceneNum = 10;
171 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
172 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
173 		createSmackerScene(0x20082828, true, true, false);
174 		break;
175 	case 11:
176 		_vm->gameState().sceneNum = 11;
177 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0);
178 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
179 		createNavigationScene(0x004B27A8, which);
180 		break;
181 	case 12:
182 		_vm->gameState().sceneNum = 12;
183 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0);
184 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
185 		createNavigationScene(0x004B2718, which);
186 		break;
187 	case 13:
188 		_vm->gameState().sceneNum = 13;
189 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0);
190 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
191 		createNavigationScene(0x004B27D8, which);
192 		break;
193 	case 14:
194 		_vm->gameState().sceneNum = 14;
195 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0);
196 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
197 		createNavigationScene(0x004B2808, which);
198 		break;
199 	case 15:
200 		_vm->gameState().sceneNum = 15;
201 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, true, 0, 0, 0, 0);
202 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
203 		createNavigationScene(0x004B2838, which);
204 		break;
205 	case 16:
206 		_vm->gameState().sceneNum = 16;
207 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
208 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
209 		_childObject = new Scene1317(_vm, this);
210 		break;
211 	case 17:
212 		_vm->gameState().sceneNum = 17;
213 		_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 0, 0, 0, 0);
214 		_vm->_soundMan->stopMusic(0x00203197, 0, 2);
215 		_childObject = new CreditsScene(_vm, this, false);
216 		break;
217 	default:
218 		break;
219 	}
220 	SetUpdateHandler(&Module1300::updateScene);
221 	_childObject->handleUpdate();
222 }
223 
updateScene()224 void Module1300::updateScene() {
225 	if (!updateChild()) {
226 		switch (_sceneNum) {
227 		case 1:
228 			if (_moduleResult == 1)
229 				createScene(4, 0);
230 			else
231 				createScene(7, 1);
232 			break;
233 		case 2:
234 			createScene(5, 3);
235 			break;
236 		case 3:
237 			createScene(15, 0);
238 			break;
239 		case 4:
240 			createScene(16, -1);
241 			break;
242 		case 5:
243 			if (_moduleResult == 2)
244 				createScene(8, 0);
245 			else if (_moduleResult == 3)
246 				createScene(2, 0);
247 			else if (_moduleResult == 0)
248 				leaveModule(0);
249 			else if (_moduleResult == 1)
250 				createScene(10, -1);
251 			break;
252 		case 6:
253 			createScene(7, 2);
254 			break;
255 		case 7:
256 			if (_moduleResult == 0)
257 				createScene(13, 0);
258 			else if (_moduleResult == 1)
259 				createScene(1, 0);
260 			else if (_moduleResult == 2)
261 				createScene(6, 0);
262 			break;
263 		case 8:
264 			createScene(5, 2);
265 			break;
266 		case 9:
267 			createScene(5, 0);
268 			break;
269 		case 10:
270 			createScene(14, 0);
271 			break;
272 		case 11:
273 			if (_moduleResult == 0)
274 				createScene(12, 0);
275 			else if (_moduleResult == 1)
276 				createScene(11, 1);
277 			break;
278 		case 12:
279 			if (_moduleResult == 0)
280 				createScene(14, 1);
281 			else if (_moduleResult == 1)
282 				createScene(15, 1);
283 			else if (_moduleResult == 3)
284 				createScene(11, 1);
285 			else if (_moduleResult == 5)
286 				createScene(13, 1);
287 			break;
288 		case 13:
289 			if (_moduleResult == 0)
290 				createScene(12, 2);
291 			else if (_moduleResult == 1)
292 				createScene(7, 0);
293 			break;
294 		case 14:
295 			if (_moduleResult == 0)
296 				createScene(12, 3);
297 			else if (_moduleResult == 1)
298 				createScene(9, -1);
299 			break;
300 		case 15:
301 			if (_moduleResult == 0)
302 				createScene(12, 4);
303 			else if (_moduleResult == 1)
304 				createScene(3, 0);
305 			break;
306 		case 16:
307 			createScene(17, -1);
308 			break;
309 		case 17:
310 			leaveModule(1);
311 			break;
312 		default:
313 			break;
314 		}
315 	}
316 }
317 
Scene1302(NeverhoodEngine * vm,Module * parentModule,int which)318 Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which)
319 	: Scene(vm, parentModule) {
320 
321 	SetMessageHandler(&Scene1302::handleMessage);
322 
323 	setHitRects(0x004B0858);
324 	setRectList(0x004B0A38);
325 	setBackground(0x420643C4);
326 	setPalette(0x420643C4);
327 	insertScreenMouse(0x643C0428);
328 
329 	_class595 = insertStaticSprite(0xB0420130, 1015);
330 	_sprite1 = insertStaticSprite(0x942FC224, 300);
331 	_sprite2 = insertStaticSprite(0x70430830, 1200);
332 	_sprite2->setVisible(false);
333 	_sprite3 = insertStaticSprite(0x16E01E20, 1100);
334 	_asRing1 = insertSprite<AsScene1002Ring>(this, false, 218, 122, _class595->getDrawRect().y, false);
335 	_asRing2 = insertSprite<AsScene1002Ring>(this, true, 218 + 32, 132, _class595->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_BRIDGE));
336 	_asRing3 = insertSprite<AsScene1002Ring>(this, false, 218 + 32 + 32, 122, _class595->getDrawRect().y, false);
337 	_asRing4 = insertSprite<AsScene1002Ring>(this, true, 218 + 32 + 32 + 32, 132, _class595->getDrawRect().y, getGlobalVar(V_FLYTRAP_RING_FENCE));
338 	_asRing5 = insertSprite<AsScene1002Ring>(this, false, 218 + 32 + 32 + 32 + 32, 115, _class595->getDrawRect().y, false);
339 	_asBridge = insertSprite<AsScene1302Bridge>(this);
340 	_ssFence = insertSprite<SsScene1302Fence>();
341 	_ssFence->setClipRect(0, 0, 640, _sprite1->getDrawRect().y2());
342 
343 	if (which < 0) {
344 		// Restoring game
345 		insertKlaymen<KmScene1002>(380, 364);
346 		setMessageList(0x004B0868);
347 	} else {
348 		// Klaymen entering from back
349 		insertKlaymen<KmScene1002>(293, 330);
350 		setMessageList(0x004B0870);
351 	}
352 
353 	_klaymen->setClipRect(0, 0, _sprite3->getDrawRect().x2(), 480);
354 
355 	_asVenusFlyTrap = insertSprite<AsScene1002VenusFlyTrap>(this, _klaymen, true);
356 	addCollisionSprite(_asVenusFlyTrap);
357 
358 	sendEntityMessage(_klaymen, NM_CAR_MOVE_TO_PREV_POINT, _asVenusFlyTrap);
359 
360 }
361 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)362 uint32 Scene1302::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
363 	uint32 messageResult = 0;
364 	Scene::handleMessage(messageNum, param, sender);
365 	switch (messageNum) {
366 	case NM_ANIMATION_START:
367 		if (param.asInteger() == 0x4A845A00) {
368 			sendEntityMessage(_klaymen, 0x1014, _asRing1);
369 		} else if (param.asInteger() == 0x43807801) {
370 			if (!getGlobalVar(V_FLYTRAP_RING_BRIDGE)) {
371 				sendEntityMessage(_klaymen, 0x1014, _asRing2);
372 				if (_asVenusFlyTrap->getX() - 10 < 218 + 32 && _asVenusFlyTrap->getX() + 10 > 218 + 32)
373 					setMessageList(0x004B0940);
374 				else
375 					setMessageList(0x004B0938);
376 			} else
377 				setMessageList(0x004B0950);
378 			messageResult = 1;
379 		} else if (param.asInteger() == 0x46C26A01) {
380 			sendEntityMessage(_klaymen, 0x1014, _asRing3);
381 		} else if (param.asInteger() == 0x468C7B11) {
382 			if (!getGlobalVar(V_FLYTRAP_RING_FENCE)) {
383 				sendEntityMessage(_klaymen, 0x1014, _asRing4);
384 				if (_asVenusFlyTrap->getX() - 10 < 218 + 32 + 32 + 32 && _asVenusFlyTrap->getX() + 10 > 218 + 32 + 32 + 32)
385 					setMessageList(0x004B0940);
386 				else
387 					setMessageList(0x004B0938);
388 			} else
389 				setMessageList(0x004B0950);
390 			messageResult = 1;
391 		} else if (param.asInteger() == 0x42845B19) {
392 			sendEntityMessage(_klaymen, 0x1014, _asRing5);
393 		} else if (param.asInteger() == 0x430A6060) {
394 			if (getGlobalVar(V_FLYTRAP_RING_BRIDGE))
395 				setMessageList2(0x004B0910);
396 			else
397 				cancelMessageList();
398 		} else if (param.asInteger() == 0x012E2070) {
399 			if (getGlobalVar(V_FLYTRAP_RING_BRIDGE))
400 				setMessageList2(0x004B0968);
401 			else
402 				cancelMessageList();
403 		} else if (param.asInteger() == 0x11C40840) {
404 			if (_asVenusFlyTrap->getX() >= 260 && _asVenusFlyTrap->getX() <= 342)
405 				setMessageList(0x004B0878);
406 			else
407 				setMessageList(0x004B0978);
408 		}
409 		break;
410 	case NM_ANIMATION_UPDATE:
411 		if (_klaymen->getY() > 360) {
412 			sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap);
413 			setMessageList2(0x004B08F0);
414 		} else
415 			setMessageList2(0x004B0920);
416 		break;
417 	case NM_POSITION_CHANGE:
418 		if (_klaymen->getX() > 545)
419 			leaveScene(1);
420 		break;
421 	case 0x2032:
422 		_sprite2->setVisible(true);
423 		break;
424 	case NM_KLAYMEN_USE_OBJECT:
425 		sendMessage(_parentModule, 0x1024, 2);
426 		if (sender == _asRing1)
427 			playSound(0, 0x665198C0);
428 		else if (sender == _asRing2) {
429 			sendMessage(_asBridge, NM_KLAYMEN_OPEN_DOOR, 0);
430 			setGlobalVar(V_FLYTRAP_RING_BRIDGE, 1);
431 		} else if (sender == _asRing3) {
432 			playSound(0, 0xE2D389C0);
433 		} else if (sender == _asRing4) {
434 			sendMessage(_ssFence, NM_KLAYMEN_OPEN_DOOR, 0);
435 			setGlobalVar(V_FLYTRAP_RING_FENCE, 1);
436 		} else if (sender == _asRing5)
437 			playSound(0, 0x40428A09);
438 		break;
439 	case NM_KLAYMEN_RAISE_LEVER:
440 		if (sender == _asRing2) {
441 			sendMessage(_asBridge, NM_KLAYMEN_CLOSE_DOOR, 0);
442 			setGlobalVar(V_FLYTRAP_RING_BRIDGE, 0);
443 			_sprite2->setVisible(false);
444 		} else if (sender == _asRing4) {
445 			sendMessage(_ssFence, NM_KLAYMEN_CLOSE_DOOR, 0);
446 			setGlobalVar(V_FLYTRAP_RING_FENCE, 0);
447 		} else if (sender == _asVenusFlyTrap) {
448 			if (getGlobalVar(V_FLYTRAP_RING_BRIDGE))
449 				sendMessage(_asRing2, NM_KLAYMEN_RAISE_LEVER, 0);
450 			else
451 				sendMessage(_asRing4, NM_KLAYMEN_RAISE_LEVER, 0);
452 		}
453 		break;
454 	case NM_KLAYMEN_LOWER_LEVER:
455 		if (sender == _asRing2) {
456 			playSound(0, 0x60755842);
457 			sendMessage(_asBridge, NM_KLAYMEN_OPEN_DOOR, 0);
458 			setGlobalVar(V_FLYTRAP_RING_BRIDGE, 1);
459 		} else if (sender == _asRing4) {
460 			playSound(0, 0x60755842);
461 			sendMessage(_ssFence, NM_KLAYMEN_OPEN_DOOR, 0);
462 			setGlobalVar(V_FLYTRAP_RING_FENCE, 1);
463 		}
464 		break;
465 	case NM_MOVE_TO_BACK:
466 		sendMessage(_asVenusFlyTrap, NM_MOVE_TO_FRONT, 0);
467 		break;
468 	case NM_MOVE_TO_FRONT:
469 		sendMessage(_asVenusFlyTrap, NM_MOVE_TO_BACK, 0);
470 		break;
471 	case 0x8000:
472 		setSpriteSurfacePriority(_class595, 995);
473 		break;
474 	case 0x8001:
475 		setSpriteSurfacePriority(_class595, 1015);
476 		break;
477 	default:
478 		break;
479 	}
480 	return messageResult;
481 }
482 
Scene1303(NeverhoodEngine * vm,Module * parentModule)483 Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule)
484 	: Scene(vm, parentModule), _asBalloon(NULL) {
485 
486 	SetMessageHandler(&Scene1303::handleMessage);
487 
488 	setRectList(0x004AF9E8);
489 	setBackground(0x01581A9C);
490 	setPalette(0x01581A9C);
491 	insertScreenMouse(0x81A9801D);
492 
493 	if (!getGlobalVar(V_BALLOON_POPPED)) {
494 		_asBalloon = insertSprite<AsScene1303Balloon>(this);
495 		addCollisionSprite(_asBalloon);
496 	}
497 
498 	_sprite1 = insertStaticSprite(0xA014216B, 1100);
499 
500 	insertKlaymen<KmScene1303>(207, 332);
501 	setMessageList(0x004AF9A0);
502 
503 	_klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480);
504 
505 }
506 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)507 uint32 Scene1303::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
508 	Scene::handleMessage(messageNum, param, sender);
509 	switch (messageNum) {
510 	case NM_ANIMATION_UPDATE:
511 		setGlobalVar(V_BALLOON_POPPED, 1);
512 		sendMessage(_asBalloon, 0x2000, 0);
513 		break;
514 	case 0x4826:
515 		if (sender == _asBalloon && getGlobalVar(V_HAS_NEEDLE))
516 			setMessageList(0x004AF9B8);
517 		break;
518 	default:
519 		break;
520 	}
521 	return 0;
522 }
523 
Scene1304(NeverhoodEngine * vm,Module * parentModule,int which)524 Scene1304::Scene1304(NeverhoodEngine *vm, Module *parentModule, int which)
525 	: Scene(vm, parentModule), _asNeedle(NULL) {
526 
527 	SetMessageHandler(&Scene1304::handleMessage);
528 
529 	setRectList(0x004B91A8);
530 	setBackground(0x062C0214);
531 	setPalette(0x062C0214);
532 	insertScreenMouse(0xC021006A);
533 
534 	if (getGlobalVar(V_BALLOON_POPPED)) {
535 		_asKey = insertSprite<AsCommonKey>(this, 0, 1100, 278, 347);
536 		addCollisionSprite(_asKey);
537 	} else {
538 		_asKey = insertSprite<AnimatedSprite>(0x80106018, 100, 279, 48);
539 	}
540 
541 	if (!getGlobalVar(V_HAS_NEEDLE)) {
542 		_asNeedle = insertSprite<AsScene1304Needle>(this, 1100, 278, 347);
543 		addCollisionSprite(_asNeedle);
544 	}
545 
546 	_sprite1 = insertStaticSprite(0x0562E621, 1100);
547 	insertStaticSprite(0x012AE033, 1100);
548 	insertStaticSprite(0x090AF033, 1100);
549 
550 	if (which < 0) {
551 		// Restoring game
552 		insertKlaymen<KmScene1304>(217, 347);
553 		setMessageList(0x004B90E8);
554 	} else {
555 		// Klaymen entering from the left
556 		insertKlaymen<KmScene1304>(100, 347);
557 		setMessageList(0x004B90F0);
558 	}
559 
560 	_klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480);
561 
562 }
563 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)564 uint32 Scene1304::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
565 	Scene::handleMessage(messageNum, param, sender);
566 	switch (messageNum) {
567 	case NM_ANIMATION_START:
568 		if (param.asInteger() == 0x415634A4) {
569 			if (getGlobalVar(V_BALLOON_POPPED))
570 				cancelMessageList();
571 			else
572 				setMessageList(0x004B9158);
573 		}
574 		break;
575 	case 0x4826:
576 		if (sender == _asNeedle) {
577 			sendEntityMessage(_klaymen, 0x1014, _asNeedle);
578 			setMessageList(0x004B9130);
579 		} else if (sender == _asKey) {
580 			sendEntityMessage(_klaymen, 0x1014, _asKey);
581 			setMessageList(0x004B9140);
582 		}
583 		break;
584 	default:
585 		break;
586 	}
587 	return 0;
588 }
589 
Scene1305(NeverhoodEngine * vm,Module * parentModule,int which)590 Scene1305::Scene1305(NeverhoodEngine *vm, Module *parentModule, int which)
591 	: Scene(vm, parentModule) {
592 
593 	SetMessageHandler(&Scene1305::handleMessage);
594 
595 	setRectList(0x004B6E98);
596 	setBackground(0x28801B64);
597 	setPalette(0x28801B64);
598 	insertScreenMouse(0x01B60280);
599 
600 	if (which < 0) {
601 		// Restoring game
602 		insertKlaymen<KmScene1305>(212, 441);
603 		setMessageList(0x004B6E40);
604 	} else {
605 		// Klaymen enters falling
606 		insertKlaymen<KmScene1305>(212, 441);
607 		setMessageList(0x004B6E48);
608 	}
609 
610 }
611 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)612 uint32 Scene1305::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
613 	return Scene::handleMessage(messageNum, param, sender);
614 }
615 
Scene1306(NeverhoodEngine * vm,Module * parentModule,int which)616 Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which)
617 	: Scene(vm, parentModule), _asKey(nullptr) {
618 
619 	if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0)
620 		setGlobalVar(V_KEY3_LOCATION, 4);
621 
622 	SetMessageHandler(&Scene1306::handleMessage);
623 
624 	setBackground(0x05303114);
625 	setPalette(0x05303114);
626 	insertScreenMouse(0x0311005B);
627 
628 	if (getGlobalVar(V_KEY3_LOCATION) == 4) {
629 		_asKey = insertSprite<AsCommonKey>(this, 2, 1100, 435, 445);
630 		addCollisionSprite(_asKey);
631 	}
632 
633 	_ssButton = insertSprite<SsCommonButtonSprite>(this, 0x404A36A0, 100, 0x440C1000);
634 	_asTape = insertSprite<AsScene1201Tape>(this, 19, 1100, 359, 445, 0x9148A011);
635 	_asElevatorDoor = insertSprite<AnimatedSprite>(0x043B0270, 90, 320, 240);
636 	_asElevatorDoor->startAnimation(0x043B0270, 6, -1);
637 	_asElevatorDoor->setNewHashListIndex(6);
638 	_asElevator = insertSprite<AsScene1306Elevator>(this, _asElevatorDoor);
639 	_sprite1 = insertStaticSprite(0x036A1EE0, 80);
640 	insertStaticSprite(0x00042313, 1100);
641 
642 	if (which < 0) {
643 		// Restoring game
644 		insertKlaymen<KmScene1306>(380, 440);
645 		setMessageList(0x004AFAD0);
646 		sendMessage(this, 0x2000, 0);
647 		addCollisionSprite(_asTape);
648 	} else if (which == 1) {
649 		// Klaymen teleporting in
650 		insertKlaymen<KmScene1306>(136, 440);
651 		sendMessage(_klaymen, 0x2000, 1);
652 		setMessageList(0x004AFAF0);
653 		sendMessage(this, 0x2000, 1);
654 		addCollisionSprite(_asTape);
655 	} else if (which == 2) {
656 		// Klaymen returning from diskplayer
657 		if (getGlobalVar(V_KLAYMEN_IS_DELTA_X)) {
658 			insertKlaymen<KmScene1306>(515, 440);
659 			_klaymen->setDoDeltaX(1);
660 		} else {
661 			insertKlaymen<KmScene1306>(355, 440);
662 		}
663 		setMessageList(0x004AFBC8);
664 		sendMessage(this, 0x2000, 0);
665 		addCollisionSprite(_asTape);
666 	} else if (which == 3) {
667 		// Klaymen returning from window
668 		insertKlaymen<KmScene1306>(534, 440);
669 		setMessageList(0x004AFC30);
670 		sendMessage(this, 0x2000, 0);
671 		addCollisionSprite(_asTape);
672 	} else if (which == 4) {
673 		// Klaymen teleporting out
674 		insertKlaymen<KmScene1306>(136, 440);
675 		sendMessage(_klaymen, 0x2000, 1);
676 		setMessageList(0x004AFC38);
677 		sendMessage(this, 0x2000, 1);
678 		addCollisionSprite(_asTape);
679 	} else if (which == 5) {
680 		// Klaymen returning from teleporter
681 		insertKlaymen<KmScene1306>(136, 440);
682 		sendMessage(_klaymen, 0x2000, 1);
683 		setMessageList(0x004AFB00);
684 		sendMessage(this, 0x2000, 1);
685 		addCollisionSprite(_asTape);
686 	} else {
687 		// Klaymen coming up in elevator
688 		insertKlaymen<KmScene1306>(286, 408);
689 		setSurfacePriority(_asElevator->getSurface(), 1100);
690 		setSurfacePriority(_asElevatorDoor->getSurface(), 1090);
691 		setSurfacePriority(_sprite1->getSurface(), 1080);
692 		sendMessage(this, 0x2000, 0);
693 		SetMessageHandler(&Scene1306::handleMessage416EB0);
694 		clearRectList();
695 		sendMessage(_asElevator, NM_KLAYMEN_OPEN_DOOR, 0);
696 	}
697 }
698 
~Scene1306()699 Scene1306::~Scene1306() {
700 	setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0);
701 }
702 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)703 uint32 Scene1306::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
704 	Scene::handleMessage(messageNum, param, sender);
705 	switch (messageNum) {
706 	case NM_ANIMATION_START:
707 		if (param.asInteger() == 0x402064D8)
708 			sendEntityMessage(_klaymen, 0x1014, _ssButton);
709 		else if (param.asInteger() == 0x01C66840) {
710 			if (sendMessage(_asElevator, 0x2001, 0) != 0)
711 				setMessageList(0x004AFBD8);
712 			else
713 				setMessageList(0x004AFAE0);
714 		} else if (param.asInteger() == 0x8E646E00) {
715 			setMessageList(0x004AFAD8);
716 			clearRectList();
717 			SetMessageHandler(&Scene1306::handleMessage416EB0);
718 		}
719 		break;
720 	case NM_ANIMATION_UPDATE:
721 		if (param.asInteger() != 0) {
722 			setRectList(0x004AFD28);
723 			_klaymen->setKlaymenIdleTable3();
724 		} else {
725 			setRectList(0x004AFD18);
726 			_klaymen->setKlaymenIdleTable1();
727 		}
728 		break;
729 	case 0x480B:
730 		if (sender == _ssButton)
731 			sendMessage(_asElevator, NM_KLAYMEN_OPEN_DOOR, 0);
732 		break;
733 	case 0x4826:
734 		if (sender == _asKey) {
735 			if (_klaymen->getX() >= 249) {
736 				sendEntityMessage(_klaymen, 0x1014, _asKey);
737 				setMessageList(0x004AFC58);
738 			}
739 		} else if (sender == _asTape) {
740 			if (_klaymen->getX() >= 249) {
741 				sendEntityMessage(_klaymen, 0x1014, _asTape);
742 				setMessageList(0x004AFC68);
743 			}
744 		}
745 		break;
746 	case NM_MOVE_TO_BACK:
747 		setSurfacePriority(_asElevator->getSurface(), 1100);
748 		setSurfacePriority(_asElevatorDoor->getSurface(), 1090);
749 		setSurfacePriority(_sprite1->getSurface(), 1080);
750 		break;
751 	case NM_MOVE_TO_FRONT:
752 		setSurfacePriority(_asElevator->getSurface(), 100);
753 		setSurfacePriority(_asElevatorDoor->getSurface(), 90);
754 		setSurfacePriority(_sprite1->getSurface(), 80);
755 		sendMessage(this, 0x2000, 0);
756 		addCollisionSprite(_asTape);
757 		break;
758 	default:
759 		break;
760 	}
761 	return 0;
762 }
763 
handleMessage416EB0(int messageNum,const MessageParam & param,Entity * sender)764 uint32 Scene1306::handleMessage416EB0(int messageNum, const MessageParam &param, Entity *sender) {
765 	Scene::handleMessage(messageNum, param, sender);
766 	switch (messageNum) {
767 	case NM_KLAYMEN_OPEN_DOOR:
768 		setMessageList(0x004AFBD0);
769 		SetMessageHandler(&Scene1306::handleMessage);
770 		break;
771 	case NM_KLAYMEN_CLOSE_DOOR:
772 		leaveScene(1);
773 		break;
774 	case NM_MOVE_TO_BACK:
775 		setSurfacePriority(_asElevator->getSurface(), 1100);
776 		setSurfacePriority(_asElevatorDoor->getSurface(), 1090);
777 		setSurfacePriority(_sprite1->getSurface(), 1080);
778 		break;
779 	case NM_MOVE_TO_FRONT:
780 		setSurfacePriority(_asElevator->getSurface(), 100);
781 		setSurfacePriority(_asElevatorDoor->getSurface(), 90);
782 		setSurfacePriority(_sprite1->getSurface(), 80);
783 		sendMessage(this, 0x2000, 0);
784 		addCollisionSprite(_asTape);
785 		break;
786 	default:
787 		break;
788 	}
789 	return 0;
790 }
791 
Scene1307(NeverhoodEngine * vm,Module * parentModule)792 Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule)
793 	: Scene(vm, parentModule), _countdown(0), _asCurrKey(NULL),
794 	_isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) {
795 
796 	Sprite *tempSprite;
797 
798 	_vm->gameModule()->initKeySlotsPuzzle();
799 
800 	_dataResource.load(0x22102142);
801 	_keyHolePoints = _dataResource.getPointArray(0xAC849240);
802 
803 	for (uint i = 0; i < 16; i++) {
804 		NPoint pt = (*_keyHolePoints)[i];
805 		_keyHoleRects[i].x1 = pt.x - 15;
806 		_keyHoleRects[i].y1 = pt.y - 15;
807 		_keyHoleRects[i].x2 = pt.x + 15;
808 		_keyHoleRects[i].y2 = pt.y + 15;
809 	}
810 
811 	SetMessageHandler(&Scene1307::handleMessage);
812 	SetUpdateHandler(&Scene1307::update);
813 
814 	setBackground(0xA8006200);
815 	setPalette(0xA8006200);
816 	addEntity(_palette);
817 	insertPuzzleMouse(0x06204A88, 20, 620);
818 
819 	tempSprite = insertStaticSprite(0x00A3621C, 800);
820 	_clipRects[0].set(tempSprite->getDrawRect().x, 0, 640, 480);
821 	tempSprite = insertStaticSprite(0x00A3641C, 600);
822 	_clipRects[1].set(tempSprite->getDrawRect().x, 0, 640, 480);
823 	tempSprite = insertStaticSprite(0x00A3681C, 400);
824 	_clipRects[2].set(tempSprite->getDrawRect().x, 0, 640, 480);
825 	tempSprite = insertStaticSprite(0x00A3701C, 200);
826 	_clipRects[3].set(tempSprite->getDrawRect().x, 0, 640, 480);
827 
828 	for (uint keyIndex = 0; keyIndex < 3; keyIndex++) {
829 		if (getSubVar(VA_IS_KEY_INSERTED, keyIndex)) {
830 			_asKeys[keyIndex] = insertSprite<AsScene1307Key>(this, keyIndex, _clipRects);
831 			addCollisionSprite(_asKeys[keyIndex]);
832 		} else {
833 			_asKeys[keyIndex] = NULL;
834 		}
835 	}
836 
837 	loadSound(0, 0x68E25540);
838 }
839 
update()840 void Scene1307::update() {
841 	Scene::update();
842 	if (_countdown && (--_countdown == 0))
843 		_doLeaveScene = true;
844 	else if (_countdown == 20)
845 		_palette->startFadeToWhite(40);
846 	if (_doLeaveScene && !isSoundPlaying(0)) {
847 		leaveScene(1);
848 		setGlobalVar(V_KEYDOOR_UNLOCKED, 1);
849 	}
850 }
851 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)852 uint32 Scene1307::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
853 	uint32 messageResult = 0;
854 	Scene::handleMessage(messageNum, param, sender);
855 	switch (messageNum) {
856 	case NM_MOUSE_CLICK:
857 		if (!_isPuzzleSolved) {
858 			if (param.asPoint().x > 20 && param.asPoint().x < 620) {
859 				if (_asCurrKey && !_isInsertingKey) {
860 					int16 mouseX = param.asPoint().x;
861 					int16 mouseY = param.asPoint().y;
862 					uint clickedKeyHoleIndex;
863 					for (clickedKeyHoleIndex = 0; clickedKeyHoleIndex < 16; clickedKeyHoleIndex++) {
864 						if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 &&
865 							mouseY >= _keyHoleRects[clickedKeyHoleIndex].y1 && mouseY <= _keyHoleRects[clickedKeyHoleIndex].y2)
866 							break;
867 					}
868 					if (clickedKeyHoleIndex < 16) {
869 						// Check if the clicked keyhole is already occupied with a key
870 						bool occupied = false;
871 						for (uint keyIndex = 0; keyIndex < 3 && !occupied; keyIndex++) {
872 							if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex] != _asCurrKey) {
873 								if (getSubVar(VA_CURR_KEY_SLOT_NUMBERS, keyIndex) == clickedKeyHoleIndex)
874 									occupied = true;
875 							}
876 						}
877 						if (!occupied) {
878 							// If the keyhole is free, insert the current key
879 							sendMessage(_asCurrKey, 0x2001, clickedKeyHoleIndex);
880 							_isInsertingKey = true;
881 							_mouseClicked = false;
882 						}
883 					}
884 				}
885 			} else if (_countdown == 0 && !_asCurrKey && !_isInsertingKey)
886 				leaveScene(0);
887 		}
888 		break;
889 	case NM_POSITION_CHANGE:
890 		// Check if all keys are in the correct keyholes
891 		if (getSubVar(VA_IS_KEY_INSERTED, 0) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 0) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 0) &&
892 			getSubVar(VA_IS_KEY_INSERTED, 1) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 1) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 1) &&
893 			getSubVar(VA_IS_KEY_INSERTED, 2) && getSubVar(VA_CURR_KEY_SLOT_NUMBERS, 2) == getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 2)) {
894 			// Play unlock animations for all keys
895 			for (uint keyIndex = 0; keyIndex < 3; keyIndex++) {
896 				if (_asKeys[keyIndex])
897 					sendMessage(_asKeys[keyIndex], 0x2003, 1);
898 			}
899 			playSound(0);
900 			_isPuzzleSolved = true;
901 			_countdown = 47;
902 		} else {
903 			for (uint keyIndex = 0; keyIndex < 3; keyIndex++)
904 				if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex])
905 					sendMessage(_asKeys[keyIndex], 0x2000, 1);
906 			sendMessage(_asCurrKey, 0x2004, 1);
907 		}
908 		_asCurrKey = NULL;
909 		_isInsertingKey = false;
910 		break;
911 	case 0x4826:
912 		_asCurrKey = (Sprite*)sender;
913 		for (uint keyIndex = 0; keyIndex < 3; keyIndex++)
914 			if (getSubVar(VA_IS_KEY_INSERTED, keyIndex) && _asKeys[keyIndex])
915 				sendMessage(_asKeys[keyIndex], 0x2000, 0);
916 		break;
917 	default:
918 		break;
919 	}
920 	return messageResult;
921 }
922 
923 static const uint32 kScene1308NumberFileHashes[] = {
924 	0x08006320, 0x10006320, 0x20006320,
925 	0x40006320, 0x80006320, 0x00006321,
926 	0x00006322, 0x00006324, 0x00006328,
927 	0x08306320, 0x10306320, 0x20306320,
928 	0x40306320, 0x80306320, 0x00306321,
929 	0x00306322
930 };
931 
Scene1308(NeverhoodEngine * vm,Module * parentModule,int which)932 Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which)
933 	: Scene(vm, parentModule), _isProjecting(false), _asProjector(NULL) {
934 
935 	_vm->gameModule()->initKeySlotsPuzzle();
936 
937 	SetMessageHandler(&Scene1308::handleMessage);
938 
939 	setBackground(0x41024202);
940 	setPalette(0x41024202);
941 	insertScreenMouse(0x24206418);
942 
943 	_asTape = insertSprite<AsScene1201Tape>(this, 17, 1100, 502, 445, 0x9148A011);
944 	addCollisionSprite(_asTape);
945 
946 	if (getGlobalVar(V_MOUSE_SUCKED_IN)) {
947 		insertSprite<AsScene1308Mouse>();
948 		insertSprite<AnimatedSprite>(0x461A1490, 200, 235, 429);
949 	}
950 
951 	_sprite1 = insertStaticSprite(0x0A042060, 1100);
952 	_asJaggyDoor = insertSprite<AsScene1308JaggyDoor>(this);
953 	_asLightWallSymbols = insertSprite<AsScene1308LightWallSymbols>(this);
954 	_ssNumber1 = insertSprite<SsScene1308Number>(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 1)], 0);
955 	_ssNumber2 = insertSprite<SsScene1308Number>(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 0)], 1);
956 	_ssNumber3 = insertSprite<SsScene1308Number>(kScene1308NumberFileHashes[getSubVar(VA_GOOD_KEY_SLOT_NUMBERS, 2)], 2);
957 	_sprite2 = insertStaticSprite(0x40043120, 995);
958 	_sprite3 = insertStaticSprite(0x43003100, 995);
959 	_sprite4 = NULL;
960 	_sprite5 = nullptr;
961 
962 	if (which < 0) {
963 		// Restoring game
964 		insertKlaymen<KmScene1308>(380, 440);
965 		setMessageList(0x004B57C0);
966 		if (getGlobalVar(V_KEYDOOR_UNLOCKED)) {
967 			_sprite4 = insertStaticSprite(0x0101A624, 1100);
968 			setRectList(0x004B5990);
969 		} else {
970 			_sprite5 = insertStaticSprite(0x080811A0, 100);
971 			setRectList(0x004B5980);
972 		}
973 	} else if (which == 1) {
974 		// Klaymen entering from the right
975 		insertKlaymen<KmScene1308>(640, 440);
976 		setMessageList(0x004B57C8);
977 		if (getGlobalVar(V_KEYDOOR_UNLOCKED)) {
978 			_sprite4 = insertStaticSprite(0x0101A624, 1100);
979 			setRectList(0x004B5990);
980 		} else {
981 			_sprite5 = insertStaticSprite(0x080811A0, 100);
982 			setRectList(0x004B5980);
983 		}
984 	} else if (which == 2) {
985 		// Klaymen returning from keyslots panel
986 		insertKlaymen<KmScene1308>(475, 440);
987 		setMessageList(0x004B58B0);
988 		if (getGlobalVar(V_KEYDOOR_UNLOCKED)) {
989 			_sprite5 = insertSprite<AsScene1308KeyboardDoor>(this);
990 			_sprite4 = insertStaticSprite(0x0101A624, 1100);
991 			_sprite4->setVisible(false);
992 		} else {
993 			_sprite5 = insertStaticSprite(0x080811A0, 100);
994 			setRectList(0x004B5980);
995 		}
996 	} else {
997 		// Klaymen entering from the left
998 		insertKlaymen<KmScene1308>(41, 440);
999 		setMessageList(0x004B57D0);
1000 		sendMessage(_asJaggyDoor, NM_KLAYMEN_OPEN_DOOR, 0);
1001 		_sprite1->setVisible(false);
1002 		if (getGlobalVar(V_KEYDOOR_UNLOCKED)) {
1003 			_sprite4 = insertStaticSprite(0x0101A624, 1100);
1004 			_klaymen->setVisible(false);
1005 		} else {
1006 			_sprite5 = insertStaticSprite(0x080811A0, 100);
1007 			_klaymen->setVisible(false);
1008 		}
1009 	}
1010 
1011 	if (_sprite4)
1012 		_klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite4->getDrawRect().x2(), 480);
1013 	else
1014 		_klaymen->setClipRect(_sprite1->getDrawRect().x, 0, 640, 480);
1015 
1016 	if (getGlobalVar(V_PROJECTOR_LOCATION) == 4) {
1017 		_asProjector = insertSprite<AsCommonProjector>(this, _klaymen, (Sprite*)NULL);
1018 		addCollisionSprite(_asProjector);
1019 		_asProjector->setClipRect(0, 0, 640, _sprite2->getDrawRect().y2());
1020 		_asProjector->setRepl(64, 0);
1021 	}
1022 
1023 }
1024 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)1025 uint32 Scene1308::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
1026 	Scene::handleMessage(messageNum, param, sender);
1027 	switch (messageNum) {
1028 	case NM_ANIMATION_START:
1029 		if (param.asInteger() == 0x88C11390) {
1030 			setRectList(0x004B59A0);
1031 			_isProjecting = true;
1032 		} else if (param.asInteger() == 0x08821382) {
1033 			sendEntityMessage(_klaymen, 0x1014, _asProjector);
1034 			if (getGlobalVar(V_KEYDOOR_UNLOCKED))
1035 				setRectList(0x004B5990);
1036 			else
1037 				setRectList(0x004B5980);
1038 			_isProjecting = false;
1039 		} else if (param.asInteger() == 0x4AC68808) {
1040 			clearRectList();
1041 			sendMessage(_asJaggyDoor, NM_KLAYMEN_CLOSE_DOOR, 0);
1042 			_sprite1->setVisible(false);
1043 			_klaymen->setVisible(false);
1044 		}
1045 		break;
1046 	case NM_PRIORITY_CHANGE:
1047 		if (sender == _asProjector) {
1048 			if (param.asInteger() >= 1000)
1049 				setSurfacePriority(_sprite3->getSurface(), 1100);
1050 			else
1051 				setSurfacePriority(_sprite3->getSurface(), 995);
1052 		}
1053 		break;
1054 	case NM_ANIMATION_UPDATE:
1055 		if (getGlobalVar(V_KEYDOOR_UNLOCKED))
1056 			setRectList(0x004B5990);
1057 		else
1058 			setRectList(0x004B5980);
1059 		setMessageList(0x004B57E8, false);
1060 		_sprite1->setVisible(true);
1061 		_klaymen->setVisible(true);
1062 		break;
1063 	case 0x2001:
1064 		leaveScene(0);
1065 		break;
1066 	case 0x2003:
1067 		_ssNumber1->setVisible(false);
1068 		_ssNumber2->setVisible(false);
1069 		_ssNumber3->setVisible(false);
1070 		break;
1071 	case 0x2004:
1072 		_sprite4->setVisible(true);
1073 		setRectList(0x004B5990);
1074 		break;
1075 	case NM_KLAYMEN_RAISE_LEVER:
1076 		sendMessage(_asLightWallSymbols, 0x2003, 0);
1077 		break;
1078 	case NM_KLAYMEN_LOWER_LEVER:
1079 		sendMessage(_asLightWallSymbols, NM_POSITION_CHANGE, 0);
1080 		_ssNumber1->setVisible(true);
1081 		_ssNumber2->setVisible(true);
1082 		_ssNumber3->setVisible(true);
1083 		break;
1084 	case 0x4826:
1085 		if (sender == _asProjector) {
1086 			if (_isProjecting)
1087 				setMessageList2(0x004B5868);
1088 			else {
1089 				if (param.asInteger() == 1) {
1090 					sendEntityMessage(_klaymen, 0x1014, _asProjector);
1091 					setMessageList2(0x004B5848);
1092 				} else if (sendMessage(_asProjector, 0x480C, _klaymen->getX() <= _asProjector->getX() ? 0 : 1) != 0) {
1093 					sendEntityMessage(_klaymen, 0x1014, _asProjector);
1094 					setMessageList2(0x004B5830);
1095 				} else
1096 					setMessageList2(0x004B5800);
1097 			}
1098 		} else if (sender == _asTape) {
1099 			if (_isProjecting)
1100 				setMessageList2(0x004B5868);
1101 			else if (_messageListStatus != 2) {
1102 				sendEntityMessage(_klaymen, 0x1014, _asTape);
1103 				setMessageList2(0x004B58E0);
1104 			}
1105 		}
1106 		break;
1107 	default:
1108 		break;
1109 	}
1110 	return 0;
1111 }
1112 
Scene1317(NeverhoodEngine * vm,Module * parentModule)1113 Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule)
1114 	: Scene(vm, parentModule) {
1115 
1116 	SetMessageHandler(&Scene1317::handleMessage);
1117 	_smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08982841, true, false));
1118 	_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
1119 	insertScreenMouse(0x08284011);
1120 	showMouse(false);
1121 	_smackerFileHash = 0;
1122 	_keepLastSmackerFrame = false;
1123 }
1124 
update()1125 void Scene1317::update() {
1126 	if (_smackerFileHash) {
1127 		_smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame);
1128 		_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
1129 		_smackerFileHash = 0;
1130 	}
1131 	Scene::update();
1132 }
1133 
upChooseKing()1134 void Scene1317::upChooseKing() {
1135 	if (!_klaymenBlinks && _klaymenBlinkCountdown != 0 && (--_klaymenBlinkCountdown == 0))
1136 		_klaymenBlinks = true;
1137 
1138 	if (!_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 2) {
1139 		_smackerPlayer->rewind();
1140 	} else if (_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 6) {
1141 		_smackerPlayer->rewind();
1142 		_klaymenBlinks = false;
1143 		_klaymenBlinkCountdown = _vm->_rnd->getRandomNumber(30 - 1) + 15;
1144 	}
1145 
1146 	if (!_klaymenBlinks && _decisionCountdown != 0 && (--_decisionCountdown == 0))
1147 		stNoDecisionYet();
1148 
1149 	if (_smackerFileHash) {
1150 		_smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame);
1151 		_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
1152 		_smackerFileHash = 0;
1153 	}
1154 
1155 	Scene::update();
1156 
1157 }
1158 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)1159 uint32 Scene1317::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
1160 	uint32 messageResult = Scene::handleMessage(messageNum, param, sender);
1161 	switch (messageNum) {
1162 	case NM_ANIMATION_STOP:
1163 		stChooseKing();
1164 		break;
1165 	default:
1166 		break;
1167 	}
1168 	return messageResult;
1169 }
1170 
hmChooseKing(int messageNum,const MessageParam & param,Entity * sender)1171 uint32 Scene1317::hmChooseKing(int messageNum, const MessageParam &param, Entity *sender) {
1172 	uint32 messageResult = Scene::handleMessage(messageNum, param, sender);
1173 	switch (messageNum) {
1174 	case NM_MOUSE_CLICK:
1175 		if (param.asPoint().x >= 21 && param.asPoint().y >= 24 &&
1176 			param.asPoint().x <= 261 && param.asPoint().y <= 280) {
1177 			stHoborgAsKing();
1178 		} else if (param.asPoint().x >= 313 && param.asPoint().y >= 184 &&
1179 			param.asPoint().x <= 399 && param.asPoint().y <= 379) {
1180 			stKlaymenAsKing();
1181 		} else if (param.asPoint().x >= 347 && param.asPoint().y >= 380 &&
1182 			param.asPoint().x <= 418 && param.asPoint().y <= 474) {
1183 			stKlaymenAsKing();
1184 		}
1185 		break;
1186 	default:
1187 		break;
1188 	}
1189 	return messageResult;
1190 }
1191 
hmHoborgAsKing(int messageNum,const MessageParam & param,Entity * sender)1192 uint32 Scene1317::hmHoborgAsKing(int messageNum, const MessageParam &param, Entity *sender) {
1193 	uint32 messageResult = Scene::handleMessage(messageNum, param, sender);
1194 	switch (messageNum) {
1195 	case NM_ANIMATION_STOP:
1196 		stEndMovie();
1197 		break;
1198 	default:
1199 		break;
1200 	}
1201 	return messageResult;
1202 }
1203 
hmEndMovie(int messageNum,const MessageParam & param,Entity * sender)1204 uint32 Scene1317::hmEndMovie(int messageNum, const MessageParam &param, Entity *sender) {
1205 	uint32 messageResult = Scene::handleMessage(messageNum, param, sender);
1206 	switch (messageNum) {
1207 	case NM_ANIMATION_STOP:
1208 		leaveScene(0);
1209 		break;
1210 	default:
1211 		break;
1212 	}
1213 	return messageResult;
1214 }
1215 
stChooseKing()1216 void Scene1317::stChooseKing() {
1217 	showMouse(true);
1218 	_smackerFileHash = 0x10982841;
1219 	_keepLastSmackerFrame = true;
1220 	_decisionCountdown = 450;
1221 	_klaymenBlinks = false;
1222 	_klaymenBlinkCountdown = _vm->_rnd->getRandomNumber(30 - 1) + 15;
1223 	SetMessageHandler(&Scene1317::hmChooseKing);
1224 	SetUpdateHandler(&Scene1317::upChooseKing);
1225 }
1226 
stNoDecisionYet()1227 void Scene1317::stNoDecisionYet() {
1228 	showMouse(false);
1229 	_smackerFileHash = 0x20982841;
1230 	_keepLastSmackerFrame = false;
1231 	SetMessageHandler(&Scene1317::handleMessage);
1232 	SetUpdateHandler(&Scene1317::update);
1233 }
1234 
stHoborgAsKing()1235 void Scene1317::stHoborgAsKing() {
1236 	showMouse(false);
1237 	_smackerFileHash = 0x40982841;
1238 	_keepLastSmackerFrame = false;
1239 	SetMessageHandler(&Scene1317::hmHoborgAsKing);
1240 	SetUpdateHandler(&Scene1317::update);
1241 }
1242 
stKlaymenAsKing()1243 void Scene1317::stKlaymenAsKing() {
1244 	showMouse(false);
1245 	_smackerFileHash = 0x80982841;
1246 	_keepLastSmackerFrame = false;
1247 	SetMessageHandler(&Scene1317::hmEndMovie);
1248 	SetUpdateHandler(&Scene1317::update);
1249 }
1250 
stEndMovie()1251 void Scene1317::stEndMovie() {
1252 	showMouse(false);
1253 	_smackerFileHash = 0x40800711;
1254 	_keepLastSmackerFrame = false;
1255 	SetMessageHandler(&Scene1317::hmEndMovie);
1256 	SetUpdateHandler(&Scene1317::update);
1257 }
1258 
1259 } // End of namespace Neverhood
1260