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/modules/module1000_sprites.h"
24 
25 namespace Neverhood {
26 
AsScene1001Door(NeverhoodEngine * vm)27 AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm)
28 	: AnimatedSprite(vm, 1100) {
29 
30 	createSurface(800, 137, 242);
31 	_x = 726;
32 	_y = 440;
33 	stShowIdleDoor();
34 	loadSound(1, 0xED403E03);
35 	SetUpdateHandler(&AnimatedSprite::update);
36 	SetMessageHandler(&AsScene1001Door::handleMessage);
37 }
38 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)39 uint32 AsScene1001Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
40 	Sprite::handleMessage(messageNum, param, sender);
41 	switch (messageNum) {
42 	case NM_ANIMATION_UPDATE:
43 		hammerHitsDoor();
44 		break;
45 	case NM_ANIMATION_STOP:
46 		gotoNextState();
47 		break;
48 	default:
49 		break;
50 	}
51 	return 0;
52 }
53 
hammerHitsDoor()54 void AsScene1001Door::hammerHitsDoor() {
55 	switch (getGlobalVar(V_DOOR_STATUS)) {
56 	case 0:
57 	case 1:
58 		playSound(0, 0x65482F03);
59 		startAnimation(0x624C0498, 1, 3);
60 		NextState(&AsScene1001Door::stShowIdleDoor);
61 		break;
62 	case 2:
63 		playSound(1);
64 		startAnimation(0x624C0498, 6, 6);
65 		NextState(&AsScene1001Door::stBustedDoorMove);
66 		break;
67 	default:
68 		// Nothing
69 		break;
70 	}
71 	incGlobalVar(V_DOOR_STATUS, 1);
72 }
73 
stShowIdleDoor()74 void AsScene1001Door::stShowIdleDoor() {
75 	switch (getGlobalVar(V_DOOR_STATUS)) {
76 	case 1:
77 		startAnimation(0x624C0498, 4, -1);
78 		_newStickFrameIndex = 4;
79 		break;
80 	case 2:
81 		startAnimation(0x624C0498, 1, -1);
82 		_newStickFrameIndex = 1;
83 		break;
84 	case 3:
85 		stopAnimation();
86 		setVisible(false);
87 		break;
88 	default:
89 		startAnimation(0x624C0498, 0, -1);
90 		_newStickFrameIndex = 0;
91 		break;
92 	}
93 }
94 
stBustedDoorMove()95 void AsScene1001Door::stBustedDoorMove() {
96 	setGlobalVar(V_DOOR_BUSTED, 1);
97 	startAnimation(0x624C0498, 6, 6);
98 	NextState(&AsScene1001Door::stBustedDoorGone);
99 	_x = 30;
100 }
101 
stBustedDoorGone()102 void AsScene1001Door::stBustedDoorGone() {
103 	playSound(0);
104 	stopAnimation();
105 	setVisible(false);
106 }
107 
AsScene1001Hammer(NeverhoodEngine * vm,Sprite * asDoor)108 AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor)
109 	: AnimatedSprite(vm, 1100), _asDoor(asDoor) {
110 
111 	_x = 547;
112 	_y = 206;
113 	createSurface(900, 177, 192);
114 	startAnimation(0x022C90D4, -1, -1);
115 	_newStickFrameIndex = STICK_LAST_FRAME;
116 	SetUpdateHandler(&AnimatedSprite::update);
117 	SetMessageHandler(&AsScene1001Hammer::handleMessage);
118 }
119 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)120 uint32 AsScene1001Hammer::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
121 	Sprite::handleMessage(messageNum, param, sender);
122 	switch (messageNum) {
123 	case NM_ANIMATION_START:
124 		if (param.asInteger() == 0x00352100)
125 			sendMessage(_asDoor, 0x2000, 0);
126 		else if (param.asInteger() == 0x0A1A0109)
127 			playSound(0, 0x66410886);
128 		break;
129 	case NM_ANIMATION_UPDATE:
130 		startAnimation(0x022C90D4, 1, -1);
131 		playSound(0, 0xE741020A);
132 		_newStickFrameIndex = STICK_LAST_FRAME;
133 		break;
134 	default:
135 		break;
136 	}
137 	return 0;
138 }
139 
AsScene1001Window(NeverhoodEngine * vm)140 AsScene1001Window::AsScene1001Window(NeverhoodEngine *vm)
141 	: AnimatedSprite(vm, 1200) {
142 
143 	_x = 320;
144 	_y = 240;
145 	createSurface(100, 66, 129);
146 	startAnimation(0xC68C2299, 0, -1);
147 	_newStickFrameIndex = 0;
148 	SetUpdateHandler(&AnimatedSprite::update);
149 	SetMessageHandler(&AsScene1001Window::handleMessage);
150 }
151 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)152 uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
153 	Sprite::handleMessage(messageNum, param, sender);
154 	switch (messageNum) {
155 	case NM_ANIMATION_START:
156 		if (param.asInteger() == 0x0E0A1410)
157 			playSound(0, 0x60803F10);
158 		break;
159 	case 0x2001:
160 		startAnimation(0xC68C2299, 0, -1);
161 		break;
162 	case NM_ANIMATION_STOP:
163 		SetMessageHandler(NULL);
164 		setGlobalVar(V_WINDOW_OPEN, 1);
165 		setVisible(false);
166 		break;
167 	default:
168 		break;
169 	}
170 	return 0;
171 }
172 
AsScene1001Lever(NeverhoodEngine * vm,Scene * parentScene,int16 x,int16 y,int deltaXType)173 AsScene1001Lever::AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType)
174 	: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
175 
176 	createSurface(1010, 71, 73);
177 	setDoDeltaX(deltaXType);
178 	startAnimation(0x04A98C36, 0, -1);
179 	_newStickFrameIndex = 0;
180 	_x = x;
181 	_y = y;
182 	SetUpdateHandler(&AnimatedSprite::update);
183 	SetMessageHandler(&AsScene1001Lever::handleMessage);
184 }
185 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)186 uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
187 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
188 	switch (messageNum) {
189 	case NM_ANIMATION_START:
190 		if (param.asInteger() == 0x00C0C444)
191 			sendMessage(_parentScene, NM_KLAYMEN_LOWER_LEVER, 0);
192 		else if (param.asInteger() == 0xC41A02C0)
193 			playSound(0, 0x40581882);
194 		break;
195 	case 0x1011:
196 		sendMessage(_parentScene, 0x4826, 0);
197 		messageResult = 1;
198 		break;
199 	case NM_ANIMATION_STOP:
200 		startAnimation(0x04A98C36, 0, -1);
201 		_newStickFrameIndex = 0;
202 		break;
203 	case NM_KLAYMEN_LOWER_LEVER:
204 		startAnimation(0x04A98C36, 0, -1);
205 		break;
206 	case NM_MOVE_TO_BACK:
207 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
208 		break;
209 	case NM_MOVE_TO_FRONT:
210 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
211 		break;
212 	default:
213 		break;
214 	}
215 	return messageResult;
216 }
217 
SsCommonButtonSprite(NeverhoodEngine * vm,Scene * parentScene,uint32 fileHash,int surfacePriority,uint32 soundFileHash)218 SsCommonButtonSprite::SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash)
219 	: StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene), _countdown(0) {
220 
221 	_priority = 1100;
222 	_soundFileHash = soundFileHash ? soundFileHash : 0x44141000;
223 	setVisible(false);
224 	SetUpdateHandler(&SsCommonButtonSprite::update);
225 	SetMessageHandler(&SsCommonButtonSprite::handleMessage);
226 }
227 
update()228 void SsCommonButtonSprite::update() {
229 	if (_countdown != 0 && (--_countdown) == 0)
230 		setVisible(false);
231 }
232 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)233 uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
234 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
235 	switch (messageNum) {
236 	case 0x480B:
237 		sendMessage(_parentScene, 0x480B, 0);
238 		setVisible(true);
239 		_countdown = 8;
240 		playSound(0, _soundFileHash);
241 		break;
242 	default:
243 		break;
244 	}
245 	return messageResult;
246 }
247 
AsScene1002Ring(NeverhoodEngine * vm,Scene * parentScene,bool isSpecial,int16 x,int16 y,int16 clipY1,bool isRingLow)248 AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool isSpecial, int16 x, int16 y, int16 clipY1, bool isRingLow)
249 	: AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) {
250 
251 	SetUpdateHandler(&AsScene1002Ring::update);
252 
253 	if (_isSpecial) {
254 		createSurface(990, 68, 314);
255 		if (isRingLow) {
256 			startAnimation(0x04103090, 0, -1);
257 			SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
258 		} else {
259 			startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1);
260 			SetMessageHandler(&AsScene1002Ring::hmRingIdle);
261 		}
262 	} else {
263 		createSurface(990, 68, 138);
264 		startAnimation(0xA85C4011, _vm->_rnd->getRandomNumber(15), -1);
265 		SetMessageHandler(&AsScene1002Ring::hmRingIdle);
266 	}
267 
268 	setClipRect(0, clipY1, 640, 480);
269 
270 	_x = x;
271 	_y = y;
272 
273 	setDoDeltaX(_vm->_rnd->getRandomNumber(1));
274 
275 }
276 
update()277 void AsScene1002Ring::update() {
278 	updateAnim();
279 	updatePosition();
280 }
281 
hmRingIdle(int messageNum,const MessageParam & param,Entity * sender)282 uint32 AsScene1002Ring::hmRingIdle(int messageNum, const MessageParam &param, Entity *sender) {
283 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
284 	switch (messageNum) {
285 	case NM_KLAYMEN_USE_OBJECT:
286 		setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
287 		sendMessage(_parentScene, NM_KLAYMEN_USE_OBJECT, 0);
288 		SetMessageHandler(&AsScene1002Ring::hmRingPulled1);
289 		startAnimation(_isSpecial ? 0x87502558 : 0x80DD4010, 0, -1);
290 		break;
291 	case NM_KLAYMEN_LOWER_LEVER:
292 		setDoDeltaX(((Sprite*)sender)->isDoDeltaX() ? 1 : 0);
293 		sendMessage(_parentScene, NM_KLAYMEN_LOWER_LEVER, 0);
294 		SetMessageHandler(&AsScene1002Ring::hmRingPulled2);
295 		startAnimation(0x861A2020, 0, -1);
296 		break;
297 	case NM_MOVE_TO_BACK:
298 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
299 		break;
300 	case NM_MOVE_TO_FRONT:
301 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
302 		break;
303 	default:
304 		break;
305 	}
306 	return messageResult;
307 }
308 
hmRingPulled1(int messageNum,const MessageParam & param,Entity * sender)309 uint32 AsScene1002Ring::hmRingPulled1(int messageNum, const MessageParam &param, Entity *sender) {
310 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
311 	switch (messageNum) {
312 	case NM_ANIMATION_STOP:
313 		startAnimation(_isSpecial ? 0x78D0A812 : 0xB85D2A10, 0, -1);
314 		SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
315 		break;
316 	case NM_KLAYMEN_RAISE_LEVER:
317 		sendMessage(_parentScene, NM_KLAYMEN_RAISE_LEVER, 0);
318 		setDoDeltaX(_vm->_rnd->getRandomNumber(1));
319 		startAnimation(0x8258A030, 0, -1);
320 		SetMessageHandler(&AsScene1002Ring::hmRingReleased);
321 		break;
322 	case NM_MOVE_TO_BACK:
323 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
324 		break;
325 	case NM_MOVE_TO_FRONT:
326 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
327 		break;
328 	default:
329 		break;
330 	}
331 	return messageResult;
332 }
333 
hmRingPulled2(int messageNum,const MessageParam & param,Entity * sender)334 uint32 AsScene1002Ring::hmRingPulled2(int messageNum, const MessageParam &param, Entity *sender) {
335 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
336 	switch (messageNum) {
337 	case NM_ANIMATION_STOP:
338 		startAnimation(0x04103090, 0, -1);
339 		SetMessageHandler(&AsScene1002Ring::hmRingHangingLow);
340 		break;
341 	case NM_MOVE_TO_BACK:
342 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
343 		break;
344 	case NM_MOVE_TO_FRONT:
345 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
346 		break;
347 	default:
348 		break;
349 	}
350 	return messageResult;
351 }
352 
hmRingHangingLow(int messageNum,const MessageParam & param,Entity * sender)353 uint32 AsScene1002Ring::hmRingHangingLow(int messageNum, const MessageParam &param, Entity *sender) {
354 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
355 	switch (messageNum) {
356 	case NM_KLAYMEN_RAISE_LEVER:
357 		sendMessage(_parentScene, NM_KLAYMEN_RAISE_LEVER, 0);
358 		setDoDeltaX(_vm->_rnd->getRandomNumber(1));
359 		startAnimation(0x8258A030, 0, -1);
360 		SetMessageHandler(&AsScene1002Ring::hmRingReleased);
361 		break;
362 	case NM_MOVE_TO_BACK:
363 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
364 		break;
365 	case NM_MOVE_TO_FRONT:
366 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
367 		break;
368 	default:
369 		break;
370 	}
371 	return messageResult;
372 }
373 
hmRingReleased(int messageNum,const MessageParam & param,Entity * sender)374 uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam &param, Entity *sender) {
375 	uint32 messageResult = hmRingIdle(messageNum, param, sender);
376 	switch (messageNum) {
377 	case NM_ANIMATION_START:
378 		if (param.asInteger() == 0x05410F72)
379 			playSound(0, 0x21EE40A9);
380 		break;
381 	case NM_ANIMATION_STOP:
382 		startAnimation(0xA85C4011, 0, -1);
383 		break;
384 	case NM_MOVE_TO_BACK:
385 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 990);
386 		break;
387 	case NM_MOVE_TO_FRONT:
388 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1010);
389 		break;
390 	default:
391 		break;
392 	}
393 	return messageResult;
394 }
395 
AsScene1002Door(NeverhoodEngine * vm,NRect & clipRect)396 AsScene1002Door::AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect)
397 	: StaticSprite(vm, 1200) {
398 
399 	loadSprite(0x1052370F, kSLFDefDrawOffset | kSLFSetPosition, 800, 526, getGlobalVar(V_FLYTRAP_RING_DOOR) ? 49 : 239);
400 	setClipRect(clipRect);
401 	SetUpdateHandler(&AsScene1002Door::update);
402 	SetMessageHandler(&AsScene1002Door::handleMessage);
403 	SetSpriteUpdate(NULL);
404 }
405 
update()406 void AsScene1002Door::update() {
407 	handleSpriteUpdate();
408 	updatePosition();
409 }
410 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)411 uint32 AsScene1002Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
412 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
413 	switch (messageNum) {
414 	case NM_KLAYMEN_OPEN_DOOR:
415 		setGlobalVar(V_FLYTRAP_RING_DOOR, 1);
416 		SetSpriteUpdate(&AsScene1002Door::suOpenDoor);
417 		break;
418 	case NM_KLAYMEN_CLOSE_DOOR:
419 		setGlobalVar(V_FLYTRAP_RING_DOOR, 0);
420 		SetSpriteUpdate(&AsScene1002Door::suCloseDoor);
421 		break;
422 	default:
423 		break;
424 	}
425 	return messageResult;
426 }
427 
suOpenDoor()428 void AsScene1002Door::suOpenDoor() {
429 	if (_y > 49) {
430 		_y -= 8;
431 		if (_y < 49) {
432 			SetSpriteUpdate(NULL);
433 			_y = 49;
434 		}
435 		_needRefresh = true;
436 	}
437 }
438 
suCloseDoor()439 void AsScene1002Door::suCloseDoor() {
440 	if (_y < 239) {
441 		_y += 8;
442 		if (_y > 239) {
443 			SetSpriteUpdate(NULL);
444 			_y = 239;
445 		}
446 		_needRefresh = true;
447 	}
448 }
449 
AsScene1002BoxingGloveHitEffect(NeverhoodEngine * vm)450 AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine *vm)
451 	: AnimatedSprite(vm, 1400) {
452 
453 	createSurface(1025, 88, 165);
454 	setVisible(false);
455 	SetUpdateHandler(&AnimatedSprite::update);
456 	SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage);
457 }
458 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)459 uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
460 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
461 	switch (messageNum) {
462 	case 0x2004:
463 		_x = ((Sprite*)sender)->getX() - 98;
464 		_y = ((Sprite*)sender)->getY() - 111;
465 		startAnimation(0x0422255A, 0, -1);
466 		setVisible(true);
467 		break;
468 	case NM_ANIMATION_STOP:
469 		stopAnimation();
470 		setVisible(false);
471 		break;
472 	default:
473 		break;
474 	}
475 	return messageResult;
476 }
477 
AsScene1002DoorSpy(NeverhoodEngine * vm,NRect & clipRect,Scene * parentScene,Sprite * asDoor,Sprite * asScene1002BoxingGloveHitEffect)478 AsScene1002DoorSpy::AsScene1002DoorSpy(NeverhoodEngine *vm, NRect &clipRect, Scene *parentScene, Sprite *asDoor, Sprite *asScene1002BoxingGloveHitEffect)
479 	: AnimatedSprite(vm, 1300), _clipRect(clipRect), _parentScene(parentScene), _asDoor(asDoor), _asBoxingGloveHitEffect(asScene1002BoxingGloveHitEffect) {
480 
481 	createSurface(800, 136, 147);
482 	setClipRect(clipRect);
483 	suDoorSpy();
484 	loadSound(0, 0xC0C40298);
485 	startAnimation(0x586C1D48, 0, 0);
486 	SetUpdateHandler(&AnimatedSprite::update);
487 	SetMessageHandler(&AsScene1002DoorSpy::handleMessage);
488 	SetSpriteUpdate(&AsScene1002DoorSpy::suDoorSpy);
489 }
490 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)491 uint32 AsScene1002DoorSpy::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
492 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
493 	switch (messageNum) {
494 	case NM_ANIMATION_START:
495 		if (param.asInteger() == 0xA61CA1C2)
496 			sendMessage(_asBoxingGloveHitEffect, 0x2004, 0);
497 		else if (param.asInteger() == 0x14CE0620)
498 			playSound(0);
499 		break;
500 	case 0x2003:
501 		stDoorSpyBoxingGlove();
502 		break;
503 	default:
504 		break;
505 	}
506 	return messageResult;
507 }
508 
hmDoorSpyAnimation(int messageNum,const MessageParam & param,Entity * sender)509 uint32 AsScene1002DoorSpy::hmDoorSpyAnimation(int messageNum, const MessageParam &param, Entity *sender) {
510 	uint32 messageResult = handleMessage(messageNum, param, sender);
511 	switch (messageNum) {
512 	case NM_ANIMATION_STOP:
513 		gotoNextState();
514 		break;
515 	default:
516 		break;
517 	}
518 	return messageResult;
519 }
520 
suDoorSpy()521 void AsScene1002DoorSpy::suDoorSpy() {
522 	_x = _asDoor->getX() + 34;
523 	_y = _asDoor->getY() + 175;
524 }
525 
stDoorSpyIdle()526 void AsScene1002DoorSpy::stDoorSpyIdle() {
527 	setClipRect(_clipRect);
528 	_parentScene->setSurfacePriority(getSurface(), 800);
529 	startAnimation(0x586C1D48, 0, 0);
530 	SetMessageHandler(&AsScene1002DoorSpy::handleMessage);
531 }
532 
stDoorSpyBoxingGlove()533 void AsScene1002DoorSpy::stDoorSpyBoxingGlove() {
534 	setClipRect(0, 0, 640, 480);
535 	_parentScene->setSurfacePriority(getSurface(), 1200);
536 	startAnimation(0x586C1D48, 1, -1);
537 	SetMessageHandler(&AsScene1002DoorSpy::hmDoorSpyAnimation);
538 	NextState(&AsScene1002DoorSpy::stDoorSpyIdle);
539 }
540 
SsCommonPressButton(NeverhoodEngine * vm,Scene * parentScene,uint32 fileHash1,uint32 fileHash2,int surfacePriority,uint32 soundFileHash)541 SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
542 	: StaticSprite(vm, 1100), _parentScene(parentScene), _status(0), _countdown(0) {
543 
544 	_soundFileHash = soundFileHash != 0 ? soundFileHash : 0x44141000;
545 	_fileHashes[0] = fileHash1;
546 	_fileHashes[1] = fileHash2;
547 	createSurface(surfacePriority, 40, 40);
548 	loadSprite(fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
549 	setVisible(false);
550 	SetUpdateHandler(&SsCommonPressButton::update);
551 	SetMessageHandler(&SsCommonPressButton::handleMessage);
552 }
553 
setFileHashes(uint32 fileHash1,uint32 fileHash2)554 void SsCommonPressButton::setFileHashes(uint32 fileHash1, uint32 fileHash2) {
555 	_fileHashes[0] = fileHash1;
556 	_fileHashes[1] = fileHash2;
557 	loadSprite(_status == 2 ? fileHash2 : fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
558 }
559 
update()560 void SsCommonPressButton::update() {
561 	if (_countdown != 0 && (--_countdown) == 0) {
562 		if (_status == 1) {
563 			_status = 2;
564 			loadSprite(_fileHashes[1], kSLFDefDrawOffset | kSLFDefPosition);
565 			_countdown = 4;
566 		} else if (_status == 2) {
567 			_status = 3;
568 			loadSprite(_fileHashes[0], kSLFDefDrawOffset | kSLFDefPosition);
569 			_countdown = 4;
570 		} else if (_status == 3) {
571 			_status = 0;
572 			setVisible(false);
573 		}
574 	}
575 }
576 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)577 uint32 SsCommonPressButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
578 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
579 	switch (messageNum) {
580 	case 0x480B:
581 		sendMessage(_parentScene, 0x480B, 0);
582 		_status = 1;
583 		_countdown = 4;
584 		setVisible(true);
585 		playSound(0, _soundFileHash);
586 		break;
587 	default:
588 		break;
589 	}
590 	return messageResult;
591 }
592 
AsScene1002VenusFlyTrap(NeverhoodEngine * vm,Scene * parentScene,Sprite * klaymen,bool isSecond)593 AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *parentScene, Sprite *klaymen, bool isSecond)
594 	: AnimatedSprite(vm, 1100), _parentScene(parentScene), _klaymen(klaymen), _isSecond(isSecond), _countdown(0) {
595 
596 	createSurface(995, 175, 195);
597 	if (!_isSecond) {
598 		if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
599 			setDoDeltaX(1);
600 			_x = 366;
601 			_y = 435;
602 			stRingGrabbed();
603 		} else {
604 			_x = 174 + getGlobalVar(V_FLYTRAP_POSITION_1) * 32;
605 			_y = 435;
606 			stIdle();
607 		}
608 	} else {
609 		_x = 186 + getGlobalVar(V_FLYTRAP_POSITION_2) * 32;
610 		_y = 364;
611 		if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE)) {
612 			stRingGrabbed();
613 		} else {
614 			stIdle();
615 		}
616 	}
617 	_flags = 4;
618 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
619 	SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
620 	SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
621 }
622 
update()623 void AsScene1002VenusFlyTrap::update() {
624 	if (_countdown != 0 && (--_countdown == 0))
625 		gotoNextState();
626 	AnimatedSprite::update();
627 }
628 
upIdle()629 void AsScene1002VenusFlyTrap::upIdle() {
630 	if (_countdown == 0 && _klaymen->getX() - 20 > _x)
631 		setDoDeltaX(1);
632 	else if (_klaymen->getX() + 20 < _x)
633 		setDoDeltaX(0);
634 	update();
635 }
636 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)637 uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
638 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
639 	switch (messageNum) {
640 	case NM_ANIMATION_START:
641 		if (param.asInteger() == 0x000890C4)
642 			playSound(0, 0xC21190D8);
643 		else if (param.asInteger() == 0x522200A0)
644 			playSound(0, 0x931080C8);
645 		break;
646 	case 0x1011:
647 		if (_isSecond) {
648 			if (_x >= 154 && _x <= 346) {
649 				sendMessage(_parentScene, 0x2000, 0);
650 				messageResult = 1;
651 			}
652 		} else {
653 			if (_x >= 174 && _x <= 430) {
654 				sendMessage(_parentScene, 0x2000, 0);
655 				messageResult = 1;
656 			}
657 		}
658 		break;
659 	case 0x480B:
660 		setDoDeltaX(param.asInteger() != 0 ? 1 : 0);
661 		if (!_isSecond) {
662 			if (getGlobalVar(V_FLYTRAP_RING_DOOR))
663 				stRelease();
664 			else
665 				stWalk();
666 		} else {
667 			if (getGlobalVar(V_FLYTRAP_RING_BRIDGE) || getGlobalVar(V_FLYTRAP_RING_FENCE))
668 				stRelease();
669 			else
670 				stWalk();
671 		}
672 		break;
673 	case 0x480C:
674 		if (_isSecond) {
675 			if (_x >= 154 && _x <= 346)
676 				messageResult = 1;
677 			else
678 				messageResult = 0;
679 		} else {
680 			if (_x >= 174 && _x <= 430)
681 				messageResult = 1;
682 			else
683 				messageResult = 0;
684 		}
685 		break;
686 	case 0x480E:
687 		if (param.asInteger() == 1)
688 			stGrabRing();
689 		break;
690 	case 0x4810:
691 		swallowKlaymen();
692 		break;
693 	case NM_MOVE_TO_BACK:
694 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 995);
695 		break;
696 	case NM_MOVE_TO_FRONT:
697 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1015);
698 		break;
699 	default:
700 		break;
701 	}
702 	return messageResult;
703 }
704 
hmAnimationSimple(int messageNum,const MessageParam & param,Entity * sender)705 uint32 AsScene1002VenusFlyTrap::hmAnimationSimple(int messageNum, const MessageParam &param, Entity *sender) {
706 	uint32 messageResult = handleMessage(messageNum, param, sender);
707 	switch (messageNum) {
708 	case NM_ANIMATION_STOP:
709 		gotoNextState();
710 		break;
711 	default:
712 		break;
713 	}
714 	return messageResult;
715 }
716 
hmAnimationExt(int messageNum,const MessageParam & param,Entity * sender)717 uint32 AsScene1002VenusFlyTrap::hmAnimationExt(int messageNum, const MessageParam &param, Entity *sender) {
718 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
719 	switch (messageNum) {
720 	case NM_ANIMATION_START:
721 		if (param.asInteger() == 0x000890C4)
722 			playSound(0, 0xC21190D8);
723 		else if (param.asInteger() == 0x41881801) {
724 			if (_isSecond) {
725 				if (_x > 330)
726 					sendMessage(_klaymen, 0x4811, 2);
727 				else
728 					sendMessage(_klaymen, 0x4811, 0);
729 			} else {
730 				sendMessage(_klaymen, 0x4811, 0);
731 			}
732 		} else if (param.asInteger() == 0x522200A0)
733 			playSound(0, 0x931080C8);
734 		break;
735 	case NM_ANIMATION_STOP:
736 		gotoNextState();
737 		break;
738 	case NM_MOVE_TO_BACK:
739 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 995);
740 		break;
741 	case NM_MOVE_TO_FRONT:
742 		sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1015);
743 		break;
744 	default:
745 		break;
746 	}
747 	return messageResult;
748 }
749 
stWalkBack()750 void AsScene1002VenusFlyTrap::stWalkBack() {
751 	setDoDeltaX(2);
752 	startAnimation(0xC4080034, 0, -1);
753 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
754 	SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
755 	NextState(&AsScene1002VenusFlyTrap::stIdle);
756 }
757 
stWalk()758 void AsScene1002VenusFlyTrap::stWalk() {
759 	startAnimation(0xC4080034, 0, -1);
760 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
761 	SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
762 	NextState(&AsScene1002VenusFlyTrap::stIdle);
763 }
764 
stRelease()765 void AsScene1002VenusFlyTrap::stRelease() {
766 	sendMessage(_parentScene, NM_KLAYMEN_RAISE_LEVER, 0);
767 	startAnimation(0x82292851, 0, -1);
768 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
769 	SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
770 	NextState(&AsScene1002VenusFlyTrap::stIdle);
771 }
772 
stGrabRing()773 void AsScene1002VenusFlyTrap::stGrabRing() {
774 	setDoDeltaX(1);
775 	startAnimation(0x86A82A11, 0, -1);
776 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
777 	SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationSimple);
778 	NextState(&AsScene1002VenusFlyTrap::stRingGrabbed);
779 }
780 
stRingGrabbed()781 void AsScene1002VenusFlyTrap::stRingGrabbed() {
782 	startAnimation(0xB5A86034, 0, -1);
783 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
784 	SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
785 }
786 
stKlaymenInside()787 void AsScene1002VenusFlyTrap::stKlaymenInside() {
788 	startAnimation(0x31303094, 0, -1);
789 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
790 	SetMessageHandler(NULL);
791 	NextState(&AsScene1002VenusFlyTrap::stKlaymenInsideMoving);
792 	_countdown = 24;
793 }
794 
stIdle()795 void AsScene1002VenusFlyTrap::stIdle() {
796 	startAnimation(0xC8204250, 0, -1);
797 	SetUpdateHandler(&AsScene1002VenusFlyTrap::upIdle);
798 	SetMessageHandler(&AsScene1002VenusFlyTrap::handleMessage);
799 	if (_isSecond) {
800 		if (_x >= 154 && _x <= 346)
801 			setGlobalVar(V_FLYTRAP_POSITION_2, (_x - 186) / 32);
802 		else {
803 			NextState(&AsScene1002VenusFlyTrap::stWalkBack);
804 			_countdown = 12;
805 		}
806 	} else {
807 		if (_x >= 174 && _x <= 430)
808 			setGlobalVar(V_FLYTRAP_POSITION_1, (_x - 174) / 32);
809 		else {
810 			NextState(&AsScene1002VenusFlyTrap::stWalkBack);
811 			_countdown = 12;
812 		}
813 	}
814 }
815 
stKlaymenInsideMoving()816 void AsScene1002VenusFlyTrap::stKlaymenInsideMoving() {
817 	startAnimation(0x152920C4, 0, -1);
818 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
819 	SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
820 	NextState(&AsScene1002VenusFlyTrap::stSpitOutKlaymen);
821 }
822 
stSpitOutKlaymen()823 void AsScene1002VenusFlyTrap::stSpitOutKlaymen() {
824 	startAnimation(0x84001117, 0, -1);
825 	SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
826 	SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
827 	NextState(&AsScene1002VenusFlyTrap::stIdle);
828 }
829 
swallowKlaymen()830 void AsScene1002VenusFlyTrap::swallowKlaymen() {
831 	if (_x - 15 < _klaymen->getX() && _x + 15 > _klaymen->getX()) {
832 		if (_isSecond)
833 			setDoDeltaX(_x > 265 && _x < 330 ? 1 : 0);
834 		else
835 			setDoDeltaX(_x > 320 ? 1 : 0);
836 		sendMessage(_klaymen, 0x2001, 0);
837 		startAnimation(0x8C2C80D4, 0, -1);
838 		SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
839 		SetMessageHandler(&AsScene1002VenusFlyTrap::hmAnimationExt);
840 		NextState(&AsScene1002VenusFlyTrap::stKlaymenInside);
841 	}
842 }
843 
AsScene1002OutsideDoorBackground(NeverhoodEngine * vm)844 AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngine *vm)
845 	: AnimatedSprite(vm, 1200), _countdown(0), _isDoorClosed(true) {
846 
847 	createSurface(850, 186, 212);
848 	_x = 320;
849 	_y = 240;
850 	if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
851 		startAnimation(0x004A4495, -1, -1);
852 		_newStickFrameIndex = STICK_LAST_FRAME;
853 	} else
854 		setVisible(false);
855 	SetUpdateHandler(&AsScene1002OutsideDoorBackground::update);
856 	SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
857 }
858 
update()859 void AsScene1002OutsideDoorBackground::update() {
860 	if (_countdown != 0 && (--_countdown == 0)) {
861 		if (_isDoorClosed)
862 			stCloseDoor();
863 		else
864 			stOpenDoor();
865 	}
866 	AnimatedSprite::update();
867 }
868 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)869 uint32 AsScene1002OutsideDoorBackground::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
870 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
871 	switch (messageResult) {
872 	case NM_KLAYMEN_OPEN_DOOR:
873 		_isDoorClosed = false;
874 		_countdown = 2;
875 		break;
876 	case NM_KLAYMEN_CLOSE_DOOR:
877 		_isDoorClosed = true;
878 		_countdown = 2;
879 		break;
880 	default:
881 		break;
882 	}
883 	return messageResult;
884 }
885 
hmAnimation(int messageNum,const MessageParam & param,Entity * sender)886 uint32 AsScene1002OutsideDoorBackground::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
887 	uint32 messageResult = handleMessage(messageNum, param, sender);
888 	switch (messageResult) {
889 	case NM_ANIMATION_STOP:
890 		gotoNextState();
891 		break;
892 	default:
893 		break;
894 	}
895 	return messageResult;
896 }
897 
stOpenDoor()898 void AsScene1002OutsideDoorBackground::stOpenDoor() {
899 	startAnimation(0x004A4495, 0, -1);
900 	_newStickFrameIndex = STICK_LAST_FRAME;
901 	setVisible(true);
902 	SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
903 }
904 
stCloseDoor()905 void AsScene1002OutsideDoorBackground::stCloseDoor() {
906 	startAnimation(0x004A4495, -1, -1);
907 	_playBackwards = true;
908 	setVisible(true);
909 	SetMessageHandler(&AsScene1002OutsideDoorBackground::hmAnimation);
910 	NextState(&AsScene1002OutsideDoorBackground::stDoorClosed);
911 }
912 
stDoorClosed()913 void AsScene1002OutsideDoorBackground::stDoorClosed() {
914 	setVisible(false);
915 	stopAnimation();
916 }
917 
AsScene1002KlaymenLadderHands(NeverhoodEngine * vm,Klaymen * klaymen)918 AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen)
919 	: AnimatedSprite(vm, 1200), _klaymen(klaymen) {
920 
921 	createSurface(1200, 40, 163);
922 	setVisible(false);
923 	SetUpdateHandler(&AsScene1002KlaymenLadderHands::update);
924 	SetMessageHandler(&Sprite::handleMessage);
925 }
926 
update()927 void AsScene1002KlaymenLadderHands::update() {
928 	if (_klaymen->getCurrAnimFileHash() == 0x3A292504) {
929 		startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1);
930 		_newStickFrameIndex = _klaymen->getFrameIndex();
931 		setVisible(true);
932 		_x = _klaymen->getX();
933 		_y = _klaymen->getY();
934 		setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
935 	} else if (_klaymen->getCurrAnimFileHash() == 0x122D1505) {
936 		startAnimation(0x1319150C, _klaymen->getFrameIndex(), -1);
937 		_newStickFrameIndex = _klaymen->getFrameIndex();
938 		setVisible(true);
939 		_x = _klaymen->getX();
940 		_y = _klaymen->getY();
941 		setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
942 	} else
943 		setVisible(false);
944 	AnimatedSprite::update();
945 }
946 
AsScene1002KlaymenPeekHand(NeverhoodEngine * vm,Scene * parentScene,Klaymen * klaymen)947 AsScene1002KlaymenPeekHand::AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen)
948 	: AnimatedSprite(vm, 1200), _parentScene(parentScene), _klaymen(klaymen),
949 	_isClipRectSaved(false) {
950 
951 	createSurface(1000, 33, 41);
952 	setVisible(false);
953 	SetUpdateHandler(&AsScene1002KlaymenPeekHand::update);
954 	SetMessageHandler(&AsScene1002KlaymenPeekHand::handleMessage);
955 }
956 
update()957 void AsScene1002KlaymenPeekHand::update() {
958 	if (_klaymen->getCurrAnimFileHash() == 0xAC20C012 && _klaymen->getFrameIndex() < 50) {
959 		startAnimation(0x9820C913, _klaymen->getFrameIndex(), -1);
960 		_newStickFrameIndex = _klaymen->getFrameIndex();
961 		setVisible(true);
962 		_x = _klaymen->getX();
963 		_y = _klaymen->getY();
964 		setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
965 	} else
966 		setVisible(false);
967 	AnimatedSprite::update();
968 }
969 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)970 uint32 AsScene1002KlaymenPeekHand::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
971 	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
972 	switch (messageNum) {
973 	case NM_ANIMATION_START:
974 		if (param.asInteger() == 0x4AB28209) {
975 			sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1200);
976 			_isClipRectSaved = true;
977 			_savedClipRect = _surface->getClipRect();
978 			setClipRect(0, 0, 640, 480);
979 		} else if (param.asInteger() == 0x88001184) {
980 			sendMessage(_parentScene, NM_PRIORITY_CHANGE, 1000);
981 			if (_isClipRectSaved)
982 				setClipRect(_savedClipRect);
983 		}
984 		break;
985 	default:
986 		break;
987 	}
988 	return messageResult;
989 }
990 
AsScene1004TrashCan(NeverhoodEngine * vm)991 AsScene1004TrashCan::AsScene1004TrashCan(NeverhoodEngine *vm)
992 	: AnimatedSprite(vm, 1100) {
993 
994 	_x = 330;
995 	_y = 327;
996 	createSurface(800, 56, 50);
997 	setVisible(false);
998 	SetUpdateHandler(&AnimatedSprite::update);
999 	SetMessageHandler(&AsScene1004TrashCan::handleMessage);
1000 }
1001 
handleMessage(int messageNum,const MessageParam & param,Entity * sender)1002 uint32 AsScene1004TrashCan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
1003 	Sprite::handleMessage(messageNum, param, sender);
1004 	switch (messageNum) {
1005 	case NM_ANIMATION_START:
1006 		if (param.asInteger() == 0x225A8587)
1007 			playSound(0, 0x109AFC4C);
1008 		break;
1009 	case NM_POSITION_CHANGE:
1010 		startAnimation(0xEB312C11, 0, -1);
1011 		setVisible(true);
1012 		break;
1013 	case NM_ANIMATION_STOP:
1014 		stopAnimation();
1015 		setVisible(false);
1016 		break;
1017 	default:
1018 		break;
1019 	}
1020 	return 0;
1021 }
1022 
1023 static const KlaymenIdleTableItem klaymenIdleTable1002[] = {
1024 	{1, kIdlePickEar},
1025 	{2, kIdleWonderAbout}
1026 };
1027 
KmScene1001(NeverhoodEngine * vm,Scene * parentScene,int16 x,int16 y)1028 KmScene1001::KmScene1001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
1029 	: Klaymen(vm, parentScene, x, y) {
1030 }
1031 
xHandleMessage(int messageNum,const MessageParam & param)1032 uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
1033 	switch (messageNum) {
1034 	case 0x4001:
1035 	case 0x4800:
1036 		startWalkToX(param.asPoint().x, false);
1037 		break;
1038 	case NM_KLAYMEN_STAND_IDLE:
1039 		GotoState(&Klaymen::stTryStandIdle);
1040 		break;
1041 	case 0x4804:
1042 		if (param.asInteger() == 2)
1043 			GotoState(&KmScene1001::stSleeping);
1044 		break;
1045 	case 0x480D:
1046 		GotoState(&KmScene1001::stPullHammerLever);
1047 		break;
1048 	case NM_KLAYMEN_PICKUP:
1049 		GotoState(&Klaymen::stPickUpGeneric);
1050 		break;
1051 	case NM_KLAYMEN_PRESS_BUTTON:
1052 		if (param.asInteger() == 1)
1053 			GotoState(&Klaymen::stPressButton);
1054 		else if (param.asInteger() == 2)
1055 			GotoState(&Klaymen::stPressFloorButton);
1056 		else
1057 			GotoState(&Klaymen::stPressButtonSide);
1058 		break;
1059 	case 0x4817:
1060 		setDoDeltaX(param.asInteger());
1061 		gotoNextStateExt();
1062 		break;
1063 	case 0x481B:
1064 		if (param.asPoint().y != 0)
1065 			startWalkToXDistance(param.asPoint().y, param.asPoint().x);
1066 		else
1067 			startWalkToAttachedSpriteXDistance(param.asPoint().x);
1068 		break;
1069 	case 0x481F:
1070 		if (param.asInteger() == 0)
1071 			GotoState(&Klaymen::stWonderAboutHalf);
1072 		else if (param.asInteger() == 1)
1073 			GotoState(&Klaymen::stWonderAboutAfter);
1074 		else if (param.asInteger() == 3)
1075 			GotoState(&Klaymen::stTurnToUseHalf);
1076 		else if (param.asInteger() == 4)
1077 			GotoState(&Klaymen::stTurnAwayFromUse);
1078 		else
1079 			GotoState(&Klaymen::stWonderAbout);
1080 		break;
1081 	case 0x482D:
1082 		setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
1083 		gotoNextStateExt();
1084 		break;
1085 	case 0x4836:
1086 		if (param.asInteger() == 1) {
1087 			sendMessage(_parentScene, NM_POSITION_CHANGE, 0);
1088 			GotoState(&KmScene1001::stWakeUp);
1089 		}
1090 		break;
1091 	case 0x483F:
1092 		startSpecialWalkRight(param.asInteger());
1093 		break;
1094 	case 0x4840:
1095 		startSpecialWalkLeft(param.asInteger());
1096 		break;
1097 	default:
1098 		break;
1099 	}
1100 	return 0;
1101 }
1102 
stWakeUp()1103 void KmScene1001::stWakeUp() {
1104 	_busyStatus = 1;
1105 	_acceptInput = false;
1106 	startAnimation(0x527AC970, 0, -1);
1107 	SetUpdateHandler(&Klaymen::update);
1108 	SetMessageHandler(&Klaymen::hmLowLevelAnimation);
1109 	SetSpriteUpdate(NULL);
1110 }
1111 
stSleeping()1112 void KmScene1001::stSleeping() {
1113 	_busyStatus = 0;
1114 	_acceptInput = true;
1115 	startAnimation(0x5A38C110, 0, -1);
1116 	SetUpdateHandler(&Klaymen::update);
1117 	SetMessageHandler(&KmScene1001::hmSleeping);
1118 	SetSpriteUpdate(NULL);
1119 }
1120 
hmSleeping(int messageNum,const MessageParam & param,Entity * sender)1121 uint32 KmScene1001::hmSleeping(int messageNum, const MessageParam &param, Entity *sender) {
1122 	uint32 messageResult = hmLowLevel(messageNum, param, sender);
1123 	switch (messageNum) {
1124 	case NM_ANIMATION_START:
1125 		if (param.asInteger() == 0x03060012) {
1126 			playSound(0, 0xC0238244);
1127 		}
1128 		break;
1129 	default:
1130 		break;
1131 	}
1132 	return messageResult;
1133 }
1134 
stPullHammerLever()1135 void KmScene1001::stPullHammerLever() {
1136 	if (!stStartAction(AnimationCallback(&KmScene1001::stPullHammerLever))) {
1137 		_busyStatus = 2;
1138 		_acceptInput = false;
1139 		startAnimation(0x00648953, 0, -1);
1140 		SetUpdateHandler(&Klaymen::update);
1141 		SetMessageHandler(&KmScene1001::hmPullHammerLever);
1142 		SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
1143 	}
1144 }
1145 
hmPullHammerLever(int messageNum,const MessageParam & param,Entity * sender)1146 uint32 KmScene1001::hmPullHammerLever(int messageNum, const MessageParam &param, Entity *sender) {
1147 	uint32 messageResult = Klaymen::hmLever(messageNum, param, sender);
1148 	switch (messageNum) {
1149 	case NM_ANIMATION_START:
1150 		if (param.asInteger() == 0x4AB28209)
1151 			sendMessage(_attachedSprite, NM_KLAYMEN_LOWER_LEVER, 0);
1152 		break;
1153 	default:
1154 		break;
1155 	}
1156 	return messageResult;
1157 }
1158 
KmScene1002(NeverhoodEngine * vm,Scene * parentScene,int16 x,int16 y)1159 KmScene1002::KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
1160 	: Klaymen(vm, parentScene, x, y) {
1161 
1162 	setKlaymenIdleTable1();
1163 }
1164 
xUpdate()1165 void KmScene1002::xUpdate() {
1166 	if (_x >= 250 && _x <= 435 && _y >= 420) {
1167 		if (_idleTableNum == 0) {
1168 			setKlaymenIdleTable(klaymenIdleTable1002, ARRAYSIZE(klaymenIdleTable1002));
1169 			_idleTableNum = 1;
1170 		}
1171 	} else if (_idleTableNum == 1) {
1172 		setKlaymenIdleTable1();
1173 		_idleTableNum = 0;
1174 	}
1175 }
1176 
xHandleMessage(int messageNum,const MessageParam & param)1177 uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
1178 	switch (messageNum) {
1179 	case 0x2001:
1180 		GotoState(&Klaymen::stStandIdleSpecial);
1181 		break;
1182 	case NM_CAR_MOVE_TO_PREV_POINT:
1183 		_otherSprite = (Sprite*)param.asEntity();
1184 		break;
1185 	case 0x4001:
1186 	case 0x4800:
1187 		startWalkToX(param.asPoint().x, false);
1188 		break;
1189 	case NM_KLAYMEN_STAND_IDLE:
1190 		GotoState(&Klaymen::stTryStandIdle);
1191 		break;
1192 	case 0x4803:
1193 		if (param.asInteger() == 1)
1194 			GotoState(&KmScene1002::stJumpAndFall);
1195 		else if (param.asInteger() == 2)
1196 			GotoState(&KmScene1002::stDropFromRing);
1197 		break;
1198 	case 0x4804:
1199 		GotoState(&Klaymen::stPeekWall);
1200 		break;
1201 	case 0x4805:
1202 		switch (param.asInteger()) {
1203 		case 1:
1204 			GotoState(&KmScene1002::stJumpToRing1);
1205 			break;
1206 		case 2:
1207 			GotoState(&KmScene1002::stJumpToRing2);
1208 			break;
1209 		case 3:
1210 			GotoState(&KmScene1002::stJumpToRing3);
1211 			break;
1212 		case 4:
1213 			GotoState(&KmScene1002::stJumpToRing4);
1214 			break;
1215 		default:
1216 			break;
1217 		}
1218 		break;
1219 	case NM_KLAYMEN_MOVE_OBJECT:
1220 		GotoState(&KmScene1002::stMoveVenusFlyTrap);
1221 		break;
1222 	case 0x480D:
1223 		GotoState(&KmScene1002::stJumpToRingVenusFlyTrap);
1224 		break;
1225 	case NM_KLAYMEN_PRESS_BUTTON:
1226 		if (param.asInteger() == 0)
1227 			GotoState(&KmScene1002::stPressDoorButton);
1228 		break;
1229 	case 0x4817:
1230 		setDoDeltaX(param.asInteger());
1231 		gotoNextStateExt();
1232 		break;
1233 	case 0x481B:
1234 		startWalkToAttachedSpriteXDistance(param.asInteger());
1235 		break;
1236 	case 0x4820:
1237 		sendMessage(_parentScene, NM_KLAYMEN_CLIMB_LADDER, 0);
1238 		GotoState(&Klaymen::stContinueClimbLadderUp);
1239 		break;
1240 	case 0x4821:
1241 		sendMessage(_parentScene, NM_KLAYMEN_CLIMB_LADDER, 0);
1242 		_destY = param.asInteger();
1243 		GotoState(&Klaymen::stStartClimbLadderDown);
1244 		break;
1245 	case 0x4822:
1246 		sendMessage(_parentScene, NM_KLAYMEN_CLIMB_LADDER, 0);
1247 		_destY = param.asInteger();
1248 		GotoState(&Klaymen::stStartClimbLadderUp);
1249 		break;
1250 	case 0x4823:
1251 		sendMessage(_parentScene, NM_KLAYMEN_STOP_CLIMBING, 0);
1252 		GotoState(&Klaymen::stClimbLadderHalf);
1253 		break;
1254 	case 0x482E:
1255 		if (param.asInteger() == 1)
1256 			GotoState(&Klaymen::stWalkToFrontNoStep);
1257 		else
1258 			GotoState(&Klaymen::stWalkToFront);
1259 		break;
1260 	case 0x482F:
1261 		if (param.asInteger() == 1)
1262 			GotoState(&Klaymen::stTurnToFront);
1263 		else
1264 			GotoState(&Klaymen::stTurnToBack);
1265 		break;
1266 	case 0x483F:
1267 		startSpecialWalkRight(param.asInteger());
1268 		break;
1269 	case 0x4840:
1270 		startSpecialWalkLeft(param.asInteger());
1271 		break;
1272 	default:
1273 		break;
1274 	}
1275 	return 0;
1276 }
1277 
setupJumpToRing()1278 void KmScene1002::setupJumpToRing() {
1279 	_acceptInput = false;
1280 	SetUpdateHandler(&Klaymen::update);
1281 	SetMessageHandler(&KmScene1002::hmJumpToRing);
1282 	SetSpriteUpdate(&Klaymen::suUpdateDestX);
1283 	NextState(&KmScene1002::stHangOnRing);
1284 	sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1285 }
1286 
hmJumpToRing(int messageNum,const MessageParam & param,Entity * sender)1287 uint32 KmScene1002::hmJumpToRing(int messageNum, const MessageParam &param, Entity *sender) {
1288 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1289 	switch (messageNum) {
1290 	case NM_ANIMATION_START:
1291 		if (param.asInteger() == 0x168050A0) {
1292 			sendMessage(_attachedSprite, NM_KLAYMEN_USE_OBJECT, 0);
1293 			_acceptInput = true;
1294 		} else if (param.asInteger() == 0x320AC306) {
1295 			playSound(0, 0x5860C640);
1296 		} else if (param.asInteger() == 0x4AB28209) {
1297 			sendMessage(_attachedSprite, NM_MOVE_TO_BACK, 0);
1298 		} else if (param.asInteger() == 0x88001184) {
1299 			sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1300 		}
1301 		break;
1302 	default:
1303 		break;
1304 	}
1305 	return messageResult;
1306 }
1307 
stHangOnRing()1308 void KmScene1002::stHangOnRing() {
1309 	_busyStatus = 0;
1310 	_acceptInput = true;
1311 	startAnimation(0x4829E0B8, 0, -1);
1312 	SetUpdateHandler(&Klaymen::update);
1313 	SetMessageHandler(&Klaymen::hmLowLevel);
1314 	SetSpriteUpdate(NULL);
1315 }
1316 
stJumpToRing1()1317 void KmScene1002::stJumpToRing1() {
1318 	if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing1))) {
1319 		_busyStatus = 0;
1320 		startAnimation(0xD82890BA, 0, -1);
1321 		setupJumpToRing();
1322 	}
1323 }
1324 
stJumpToRing2()1325 void KmScene1002::stJumpToRing2() {
1326 	if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing2))) {
1327 		_busyStatus = 0;
1328 		startAnimation(0x900980B2, 0, -1);
1329 		setupJumpToRing();
1330 	}
1331 }
1332 
stJumpToRing3()1333 void KmScene1002::stJumpToRing3() {
1334 	if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing3))) {
1335 		_busyStatus = 0;
1336 		_acceptInput = false;
1337 		startAnimation(0xBA1910B2, 0, -1);
1338 		SetUpdateHandler(&Klaymen::update);
1339 		SetSpriteUpdate(&Klaymen::suUpdateDestX);
1340 		SetMessageHandler(&KmScene1002::hmJumpToRing3);
1341 		NextState(&KmScene1002::stHoldRing3);
1342 		sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1343 	}
1344 }
1345 
hmJumpToRing3(int messageNum,const MessageParam & param,Entity * sender)1346 uint32 KmScene1002::hmJumpToRing3(int messageNum, const MessageParam &param, Entity *sender) {
1347 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1348 	switch (messageNum) {
1349 	case NM_ANIMATION_START:
1350 		if (param.asInteger() == 0x168050A0) {
1351 			sendMessage(_attachedSprite, NM_KLAYMEN_USE_OBJECT, 0);
1352 		} else if (param.asInteger() == 0x320AC306) {
1353 			playSound(0, 0x5860C640);
1354 		} else if (param.asInteger() == 0x4AB28209) {
1355 			sendMessage(_attachedSprite, NM_MOVE_TO_BACK, 0);
1356 		} else if (param.asInteger() == 0x88001184) {
1357 			sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1358 		}
1359 		break;
1360 	default:
1361 		break;
1362 	}
1363 	return messageResult;
1364 }
1365 
stHoldRing3()1366 void KmScene1002::stHoldRing3() {
1367 	_busyStatus = 0;
1368 	_acceptInput = true;
1369 	startAnimation(0x4A293FB0, 0, -1);
1370 	SetUpdateHandler(&Klaymen::update);
1371 	SetMessageHandler(&KmScene1002::hmHoldRing3);
1372 	SetSpriteUpdate(NULL);
1373 }
1374 
hmHoldRing3(int messageNum,const MessageParam & param,Entity * sender)1375 uint32 KmScene1002::hmHoldRing3(int messageNum, const MessageParam &param, Entity *sender) {
1376 	if (messageNum == 0x1008) {
1377 		stReleaseRing();
1378 		return 0;
1379 	}
1380 	return hmLowLevel(messageNum, param, sender);
1381 }
1382 
stJumpToRing4()1383 void KmScene1002::stJumpToRing4() {
1384 	if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRing4))) {
1385 		_busyStatus = 0;
1386 		startAnimation(0xB8699832, 0, -1);
1387 		setupJumpToRing();
1388 	}
1389 }
1390 
stJumpToRingVenusFlyTrap()1391 void KmScene1002::stJumpToRingVenusFlyTrap() {
1392 	if (!stStartAction(AnimationCallback(&KmScene1002::stJumpToRingVenusFlyTrap))) {
1393 		_busyStatus = 2;
1394 		_acceptInput = false;
1395 		startAnimation(0x584984B4, 0, -1);
1396 		SetUpdateHandler(&Klaymen::update);
1397 		SetMessageHandler(&KmScene1002::hmJumpToRingVenusFlyTrap);
1398 		SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
1399 		NextState(&KmScene1002::stLandOnFeet);
1400 		sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1401 	}
1402 }
1403 
hmJumpToRingVenusFlyTrap(int messageNum,const MessageParam & param,Entity * sender)1404 uint32 KmScene1002::hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
1405 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1406 	switch (messageNum) {
1407 	case NM_ANIMATION_START:
1408 		if (param.asInteger() == 0x168050A0) {
1409 			sendMessage(_attachedSprite, NM_KLAYMEN_LOWER_LEVER, 0);
1410 		} else if (param.asInteger() == 0x586B0300) {
1411 			sendMessage(_otherSprite, 0x480E, 1);
1412 		} else if (param.asInteger() == 0x4AB28209) {
1413 			sendMessage(_attachedSprite, NM_MOVE_TO_BACK, 0);
1414 		} else if (param.asInteger() == 0x88001184) {
1415 			sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1416 		}
1417 		break;
1418 	default:
1419 		break;
1420 	}
1421 	return messageResult;
1422 }
1423 
stJumpAndFall()1424 void KmScene1002::stJumpAndFall() {
1425 	if (!stStartAction(AnimationCallback(&KmScene1002::stJumpAndFall))) {
1426 		sendMessage(_parentScene, 0x1024, 3);
1427 		_busyStatus = 2;
1428 		_acceptInput = false;
1429 		startAnimation(0xB93AB151, 0, -1);
1430 		SetUpdateHandler(&Klaymen::update);
1431 		SetMessageHandler(&KmScene1002::hmJumpAndFall);
1432 		SetSpriteUpdate(&Klaymen::suFallDown);
1433 		NextState(&KmScene1002::stLandOnFeet);
1434 	}
1435 }
1436 
stDropFromRing()1437 void KmScene1002::stDropFromRing() {
1438 	if (_attachedSprite) {
1439 		_x = _attachedSprite->getX();
1440 		sendMessage(_attachedSprite, NM_KLAYMEN_RAISE_LEVER, 0);
1441 		_attachedSprite = NULL;
1442 	}
1443 	_busyStatus = 2;
1444 	_acceptInput = false;
1445 	startAnimation(0x586984B1, 0, -1);
1446 	SetUpdateHandler(&Klaymen::update);
1447 	SetMessageHandler(&Klaymen::hmLowLevel);
1448 	SetSpriteUpdate(&Klaymen::suFallDown);
1449 	NextState(&KmScene1002::stLandOnFeet);
1450 }
1451 
hmJumpAndFall(int messageNum,const MessageParam & param,Entity * sender)1452 uint32 KmScene1002::hmJumpAndFall(int messageNum, const MessageParam &param, Entity *sender) {
1453 	uint32 messageResult = hmLowLevel(messageNum, param, sender);
1454 	switch (messageNum) {
1455 	case NM_ANIMATION_START:
1456 		if (param.asInteger() == 0x1307050A) {
1457 			playSound(0, 0x40428A09);
1458 		}
1459 		break;
1460 	default:
1461 		break;
1462 	}
1463 	return messageResult;
1464 }
1465 
stMoveVenusFlyTrap()1466 void KmScene1002::stMoveVenusFlyTrap() {
1467 	if (!stStartAction(AnimationCallback(&KmScene1002::stMoveVenusFlyTrap))) {
1468 		_busyStatus = 2;
1469 		_isMoveObjectRequested = false;
1470 		_acceptInput = true;
1471 		setDoDeltaX(_attachedSprite->getX() < _x ? 1 : 0);
1472 		startAnimation(0x5C01A870, 0, -1);
1473 		SetUpdateHandler(&Klaymen::update);
1474 		SetMessageHandler(&KmScene1002::hmMoveVenusFlyTrap);
1475 		SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
1476 		FinalizeState(&KmScene1002::evMoveVenusFlyTrapDone);
1477 	}
1478 }
1479 
stContinueMovingVenusFlyTrap()1480 void KmScene1002::stContinueMovingVenusFlyTrap() {
1481 	_isMoveObjectRequested = false;
1482 	_acceptInput = true;
1483 	startAnimationByHash(0x5C01A870, 0x01084280, 0);
1484 	SetUpdateHandler(&Klaymen::update);
1485 	SetMessageHandler(&KmScene1002::hmMoveVenusFlyTrap);
1486 	SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
1487 	FinalizeState(&KmScene1002::evMoveVenusFlyTrapDone);
1488 }
1489 
evMoveVenusFlyTrapDone()1490 void KmScene1002::evMoveVenusFlyTrapDone() {
1491 	sendMessage(_attachedSprite, NM_MOVE_TO_BACK, 0);
1492 }
1493 
hmMoveVenusFlyTrap(int messageNum,const MessageParam & param,Entity * sender)1494 uint32 KmScene1002::hmMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
1495 	switch (messageNum) {
1496 	case NM_ANIMATION_START:
1497 		if (param.asInteger() == 0x01084280) {
1498 			sendMessage(_attachedSprite, 0x480B, (uint32)_doDeltaX);
1499 		} else if (param.asInteger() == 0x02421405) {
1500 			if (_isMoveObjectRequested) {
1501 				if (sendMessage(_attachedSprite, 0x480C, (uint32)_doDeltaX) != 0)
1502 					stContinueMovingVenusFlyTrap();
1503 			} else {
1504 				SetMessageHandler(&KmScene1002::hmFirstMoveVenusFlyTrap);
1505 			}
1506 		} else if (param.asInteger() == 0x4AB28209) {
1507 			sendMessage(_attachedSprite, NM_MOVE_TO_BACK, 0);
1508 		} else if (param.asInteger() == 0x88001184) {
1509 			sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1510 		} else if (param.asInteger() == 0x32180101) {
1511 			playSound(0, 0x405002D8);
1512 		} else if (param.asInteger() == 0x0A2A9098) {
1513 			playSound(0, 0x0460E2FA);
1514 		}
1515 		break;
1516 	case NM_KLAYMEN_MOVE_OBJECT:
1517 		_isMoveObjectRequested = true;
1518 		return 0;
1519 	default:
1520 		break;
1521 	}
1522 	return hmLowLevelAnimation(messageNum, param, sender);
1523 }
1524 
hmFirstMoveVenusFlyTrap(int messageNum,const MessageParam & param,Entity * sender)1525 uint32 KmScene1002::hmFirstMoveVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender) {
1526 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1527 	switch (messageNum) {
1528 	case NM_ANIMATION_START:
1529 		if (param.asInteger() == 0x4AB28209) {
1530 			sendMessage(_attachedSprite, NM_MOVE_TO_BACK, 0);
1531 		} else if (param.asInteger() == 0x88001184) {
1532 			sendMessage(_attachedSprite, NM_MOVE_TO_FRONT, 0);
1533 		} else if (param.asInteger() == 0x32180101) {
1534 			playSound(0, 0x405002D8);
1535 		} else if (param.asInteger() == 0x0A2A9098) {
1536 			playSound(0, 0x0460E2FA);
1537 		}
1538 		break;
1539 	default:
1540 		break;
1541 	}
1542 	return messageResult;
1543 }
1544 
stPressDoorButton()1545 void KmScene1002::stPressDoorButton() {
1546 	_busyStatus = 2;
1547 	_acceptInput = true;
1548 	setDoDeltaX(0);
1549 	startAnimation(0x1CD89029, 0, -1);
1550 	SetUpdateHandler(&Klaymen::update);
1551 	SetMessageHandler(&KmScene1002::hmPressDoorButton);
1552 	SetSpriteUpdate(&Klaymen::suAction);
1553 }
1554 
stHitByBoxingGlove()1555 void KmScene1002::stHitByBoxingGlove() {
1556 	_busyStatus = 1;
1557 	_acceptInput = false;
1558 	startAnimation(0x35AA8059, 0, -1);
1559 	SetUpdateHandler(&Klaymen::update);
1560 	SetMessageHandler(&KmScene1002::hmHitByBoxingGlove);
1561 	SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
1562 	FinalizeState(&KmScene1002::evHitByBoxingGloveDone);
1563 }
1564 
evHitByBoxingGloveDone()1565 void KmScene1002::evHitByBoxingGloveDone() {
1566 	sendMessage(_parentScene, 0x1024, 1);
1567 }
1568 
hmPressDoorButton(int messageNum,const MessageParam & param,Entity * sender)1569 uint32 KmScene1002::hmPressDoorButton(int messageNum, const MessageParam &param, Entity *sender) {
1570 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1571 	switch (messageNum) {
1572 	case NM_ANIMATION_START:
1573 		if (param.asInteger() == 0x942D2081) {
1574 			_acceptInput = false;
1575 			sendMessage(_attachedSprite, 0x2003, 0);
1576 		} else if (param.asInteger() == 0xDA600012) {
1577 			stHitByBoxingGlove();
1578 		} else if (param.asInteger() == 0x0D01B294) {
1579 			_acceptInput = false;
1580 			sendMessage(_attachedSprite, 0x480B, 0);
1581 		}
1582 		break;
1583 	default:
1584 		break;
1585 	}
1586 	return messageResult;
1587 }
1588 
hmHitByBoxingGlove(int messageNum,const MessageParam & param,Entity * sender)1589 uint32 KmScene1002::hmHitByBoxingGlove(int messageNum, const MessageParam &param, Entity *sender) {
1590 	int16 speedUpFrameIndex;
1591 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1592 	switch (messageNum) {
1593 	case 0x1008:
1594 		speedUpFrameIndex = getFrameIndex(kKlaymenSpeedUpHash);
1595 		if (_currFrameIndex < speedUpFrameIndex) {
1596 			startAnimation(0x35AA8059, speedUpFrameIndex, -1);
1597 			_y = 435;
1598 		}
1599 		messageResult = 0;
1600 		break;
1601 	case NM_ANIMATION_START:
1602 		if (param.asInteger() == 0x1A1A0785) {
1603 			playSound(0, 0x40F0A342);
1604 		} else if (param.asInteger() == 0x60428026) {
1605 			playSound(0, 0x40608A59);
1606 		}
1607 		break;
1608 	default:
1609 		break;
1610 	}
1611 	return messageResult;
1612 }
1613 
KmScene1004(NeverhoodEngine * vm,Scene * parentScene,int16 x,int16 y)1614 KmScene1004::KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
1615 	: Klaymen(vm, parentScene, x, y) {
1616 
1617 	_dataResource.load(0x01900A04);
1618 }
1619 
xHandleMessage(int messageNum,const MessageParam & param)1620 uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam &param) {
1621 	switch (messageNum) {
1622 	case 0x4001:
1623 	case 0x4800:
1624 		startWalkToX(param.asPoint().x, false);
1625 		break;
1626 	case NM_KLAYMEN_STAND_IDLE:
1627 		GotoState(&Klaymen::stTryStandIdle);
1628 		break;
1629 	case 0x4817:
1630 		setDoDeltaX(param.asInteger());
1631 		gotoNextStateExt();
1632 		break;
1633 	case 0x4818:
1634 		startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
1635 		break;
1636 	case NM_KLAYMEN_RETURN_FROM_USE:
1637 		GotoState(&KmScene1004::stReadNote);
1638 		break;
1639 	case 0x4820:
1640 		sendMessage(_parentScene, 0x2000, 0);
1641 		GotoState(&Klaymen::stContinueClimbLadderUp);
1642 		break;
1643 	case 0x4821:
1644 		sendMessage(_parentScene, 0x2000, 0);
1645 		_destY = param.asInteger();
1646 		GotoState(&Klaymen::stStartClimbLadderDown);
1647 		break;
1648 	case 0x4822:
1649 		sendMessage(_parentScene, 0x2000, 0);
1650 		_destY = param.asInteger();
1651 		GotoState(&Klaymen::stStartClimbLadderUp);
1652 		break;
1653 	case 0x4823:
1654 		sendMessage(_parentScene, 0x2001, 0);
1655 		GotoState(&Klaymen::stClimbLadderHalf);
1656 		break;
1657 	case 0x4824:
1658 		sendMessage(_parentScene, 0x2000, 0);
1659 		_destY = _dataResource.getPoint(param.asInteger()).y;
1660 		GotoState(&Klaymen::stStartClimbLadderDown);
1661 		break;
1662 	case 0x4825:
1663 		sendMessage(_parentScene, 0x2000, 0);
1664 		_destY = _dataResource.getPoint(param.asInteger()).y;
1665 		GotoState(&Klaymen::stStartClimbLadderUp);
1666 		break;
1667 	case 0x4828:
1668 		GotoState(&Klaymen::stTurnToBackToUse);
1669 		break;
1670 	case 0x483F:
1671 		startSpecialWalkRight(param.asInteger());
1672 		break;
1673 	case 0x4840:
1674 		startSpecialWalkLeft(param.asInteger());
1675 		break;
1676 	default:
1677 		break;
1678 	}
1679 	return 0;
1680 }
1681 
hmReadNote(int messageNum,const MessageParam & param,Entity * sender)1682 uint32 KmScene1004::hmReadNote(int messageNum, const MessageParam &param, Entity *sender) {
1683 	uint32 messageResult = hmLowLevelAnimation(messageNum, param, sender);
1684 	switch (messageNum) {
1685 	case NM_ANIMATION_START:
1686 		if (param.asInteger() == 0x04684052) {
1687 			_acceptInput = true;
1688 			sendMessage(_parentScene, NM_POSITION_CHANGE, 0);
1689 		}
1690 		break;
1691 	default:
1692 		break;
1693 	}
1694 	return messageResult;
1695 }
1696 
stReadNote()1697 void KmScene1004::stReadNote() {
1698 	_busyStatus = 2;
1699 	_acceptInput = false;
1700 	startAnimation(0x123E9C9F, 0, -1);
1701 	SetUpdateHandler(&Klaymen::update);
1702 	SetMessageHandler(&KmScene1004::hmReadNote);
1703 	SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
1704 }
1705 
1706 } // End of namespace Neverhood
1707