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