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 "lastexpress/game/action.h"
24 
25 #include "lastexpress/data/animation.h"
26 #include "lastexpress/data/cursor.h"
27 #include "lastexpress/data/snd.h"
28 #include "lastexpress/data/scene.h"
29 
30 #include "lastexpress/entities/abbot.h"
31 #include "lastexpress/entities/anna.h"
32 
33 #include "lastexpress/game/beetle.h"
34 #include "lastexpress/game/entities.h"
35 #include "lastexpress/game/inventory.h"
36 #include "lastexpress/game/logic.h"
37 #include "lastexpress/game/object.h"
38 #include "lastexpress/game/savegame.h"
39 #include "lastexpress/game/savepoint.h"
40 #include "lastexpress/game/scenes.h"
41 #include "lastexpress/game/state.h"
42 
43 #include "lastexpress/sound/queue.h"
44 
45 #include "lastexpress/lastexpress.h"
46 #include "lastexpress/resource.h"
47 
48 namespace LastExpress {
49 
50 static const int _animationListSize = 273;
51 
52 // List of animations
53 static const struct {
54 	const char *filename;
55 	uint16 time;
56 } _animationList[_animationListSize] = {
57 	{"", 0},
58 	{"1002",    255},
59 	{"1002D",   255},
60 	{"1003",    0},
61 	{"1005",    195},
62 	{"1006",    750},   // 5
63 	{"1006A",   750},
64 	{"1008",    765},
65 	{"1008N",   765},
66 	{"1008A",   750},
67 	{"1008AN",  750},   // 10
68 	{"1009",    0},
69 	{"1011",    1005},
70 	{"1011A",   780},
71 	{"1012",    300},
72 	{"1013",    285},
73 	{"1017",    870},   // 15
74 	{"1017A",   0},     // Not in the data files?
75 	{"1019",    120},
76 	{"1019D",   120},
77 	{"1020",    120},   // 20
78 	{"1022",    525},
79 	{"1022A",   180},
80 	{"1022AD",  210},
81 	{"1022B",   210},
82 	{"1022C",   210},   // 25
83 	{"1023",    135},
84 	{"1025",    945},
85 	{"1028",    300},
86 	{"1030",    390},
87 	{"1031",    375},   // 30
88 	{"1032",    1050},
89 	{"1033",    945},
90 	{"1034",    495},
91 	{"1035",    1230},
92 	{"1037",    1425},  // 35
93 	{"1038",    195},
94 	{"1038A",   405},
95 	{"1039",    600},
96 	{"1040",    945},
97 	{"1041",    510},   // 40
98 	{"1042",    540},
99 	{"1043",    855},
100 	{"1044",    645},
101 	{"1046",    0},
102 	{"1047",    0},     // 45
103 	{"1047A",   0},
104 	{"1059",    1005},
105 	{"1060",    255},
106 	{"1063",    0},
107 	{"1101",    255},   // 50
108 	{"1102",    1320},
109 	{"1103",    210},
110 	{"1104",    120},
111 	{"1105",    1350},
112 	{"1106",    315},   // 55
113 	{"1106A",   315},
114 	{"1106D",   315},
115 	{"1107",    1},
116 	{"1107A",   660},
117 	{"1108",    300},   // 60
118 	{"1109",    1305},
119 	{"1110",    300},
120 	{"1112",    0},
121 	{"1115",    0},
122 	{"1115A",   0},     // 65
123 	{"1115B",   0},
124 	{"1115C",   0},
125 	{"1115D",   0},
126 	{"1115E",   0},
127 	{"1115F",   0},     // 70
128 	{"1115G",   0},
129 	{"1115H",   0},
130 	{"1116",    0},
131 	{"1117",    0},
132 	{"1118",    105},   // 75
133 	{"1202",    510},
134 	{"1202A",   510},
135 	{"1203",    720},
136 	{"1204",    120},
137 	{"1205",    465},   // 80
138 	{"1206",    690},
139 	{"1206A",   450},
140 	{"1208",    465},
141 	{"1210",    1020},
142 	{"1211",    600},   // 85
143 	{"1212",    435},
144 	{"1213",    525},
145 	{"1213A",   150},
146 	{"1215",    390},
147 	{"1216",    0},     // 90
148 	{"1219",    240},
149 	{"1222",    1095},
150 	{"1223",    0},
151 	{"1224",    720},
152 	{"1225",    1005},  // 95
153 	{"1227",    840},
154 	{"1227A",   840},
155 	{"1303",    450},
156 	{"1303N",   450},
157 	{"1304",    450},   // 100
158 	{"1304N",   450},
159 	{"1305",    630},
160 	{"1309",    0},
161 	{"1311",    1710},
162 	{"1312",    240},   // 105
163 	{"1312D",   240},
164 	{"1313",    930},
165 	{"1315",    1035},
166 	{"1315A",   1035},
167 	{"1401",    540},   // 110
168 	{"1402",    150},
169 	{"1402B",   150},
170 	{"1403",    90},
171 	{"1404",    885},
172 	{"1404A",   0},     // 115
173 	{"1405",    135},
174 	{"1406",    1665},
175 	{"1501",    285},
176 	{"1501A",   285},
177 	{"1502",    165},   // 120
178 	{"1502A",   165},
179 	{"1502D",   165},
180 	{"1503",    0},
181 	{"1504",    0},
182 	{"1505",    0},     // 125
183 	{"1505A",   0},
184 	{"1506",    300},
185 	{"1506A",   180},
186 	{"1508",    0},
187 	{"1509",    450},   // 130
188 	{"1509S",   450},
189 	{"1509A",   450},
190 	{"1509AS",  450},
191 	{"1509N",   450},
192 	{"1509SN",  450},   // 135
193 	{"1509AN",  450},
194 	{"1509BN",  450},
195 	{"1511",    150},
196 	{"1511A",   150},
197 	{"1511B",   90},    // 140
198 	{"1511BA",  90},
199 	{"1511C",   135},
200 	{"1511D",   105},
201 	{"1930",    0},
202 	{"1511E",   150},   // 145
203 	{"1512",    165},
204 	{"1513",    180},
205 	{"1517",    0},
206 	{"1517A",   165},
207 	{"1518",    165},   // 150
208 	{"1518A",   165},
209 	{"1518B",   165},
210 	{"1591",    450},
211 	{"1592",    450},
212 	{"1593",    450},   // 155
213 	{"1594",    450},
214 	{"1595",    450},
215 	{"1596",    450},
216 	{"1601",    0},
217 	{"1603",    0},     // 160
218 	{"1606B",   315},
219 	{"1607A",   0},
220 	{"1610",    0},
221 	{"1611",    0},
222 	{"1612",    0},     // 165
223 	{"1615",    0},
224 	{"1619",    0},
225 	{"1620",    120},
226 	{"1621",    105},
227 	{"1622",    105},   // 170
228 	{"1629",    450},
229 	{"1630",    450},
230 	{"1631",    525},
231 	{"1632",    0},
232 	{"1633",    615},   // 175
233 	{"1634",    180},
234 	{"1702",    180},
235 	{"1702DD",  180},
236 	{"1702NU",  180},
237 	{"1702ND",  180},   // 180
238 	{"1704",    300},
239 	{"1704D",   300},
240 	{"1705",    195},
241 	{"1705D",   195},
242 	{"1706",    195},   // 185
243 	{"1706DD",  195},
244 	{"1706ND",  195},
245 	{"1706NU",  195},
246 	{"1901",    135},
247 	{"1902",    1410},  // 190
248 	{"1903",    0},
249 	{"1904",    1920},
250 	{"1908",    600},
251 	{"1908A",   195},
252 	{"1908B",   105},   // 195
253 	{"1908C",   165},
254 	{"1908CD",  0},
255 	{"1909A",   150},
256 	{"1909B",   150},
257 	{"1909C",   150},   // 200
258 	{"1910A",   180},
259 	{"1910B",   180},
260 	{"1910C",   180},
261 	{"1911A",   90},
262 	{"1911B",   90},    // 205
263 	{"1911C",   90},
264 	{"1912",    0},
265 	{"1913",    0},
266 	{"1917",    0},
267 	{"1918",    390},   // 210
268 	{"1919",    360},
269 	{"1919A",   105},
270 	{"1920",    75},
271 	{"1922",    75},
272 	{"1923",    150},   // 215
273 	{"8001",    120},
274 	{"8001A",   120},
275 	{"8002",    120},
276 	{"8002A",   120},
277 	{"8002B",   120},   // 220
278 	{"8003",    105},
279 	{"8003A",   105},
280 	{"8004",    105},
281 	{"8004A",   105},
282 	{"8005",    270},   // 225
283 	{"8005B",   270},
284 	{"8010",    270},
285 	{"8013",    120},
286 	{"8013A",   120},
287 	{"8014",    165},   // 230
288 	{"8014A",   165},
289 	{"8014R",   165},
290 	{"8014AR",  165},
291 	{"8015",    150},
292 	{"8015A",   150},   // 235
293 	{"8015R",   150},
294 	{"8015AR",  150},
295 	{"8017",    120},
296 	{"8017A",   120},
297 	{"8017R",   120},   // 240
298 	{"8017AR",  120},
299 	{"8017N",   90},
300 	{"8023",    135},
301 	{"8023A",   135},
302 	{"8023M",   135},   // 245
303 	{"8024",    150},
304 	{"8024A",   180},
305 	{"8024M",   180},
306 	{"8025",    150},
307 	{"8025A",   150},   // 250
308 	{"8025M",   150},
309 	{"8027",    75},
310 	{"8028",    75},
311 	{"8029",    120},
312 	{"8029A",   120},   // 255
313 	{"8031",    375},
314 	{"8032",    0},
315 	{"8032A",   0},
316 	{"8033",    105},
317 	{"8035",    195},   // 260
318 	{"8035A",   120},
319 	{"8035B",   180},
320 	{"8035C",   135},
321 	{"8036",    105},
322 	{"8037",    195},   // 265
323 	{"8037A",   195},
324 	{"8040",    240},
325 	{"8040A",   240},
326 	{"8041",    195},
327 	{"8041A",   195},   // 270
328 	{"8042",    600},
329 	{"8042A",   600}
330 };
331 
332 template<class Arg, class Res, class T>
333 class Functor1MemConst : public Common::Functor1<Arg, Res> {
334 public:
335 	typedef Res (T::*FuncType)(Arg) const;
336 
Functor1MemConst(T * t,const FuncType & func)337 	Functor1MemConst(T *t, const FuncType &func) : _t(t), _func(func) {}
338 
isValid() const339 	bool isValid() const { return _func != 0 && _t != 0; }
operator ()(Arg v1) const340 	Res operator()(Arg v1) const {
341 		return (_t->*_func)(v1);
342 	}
343 private:
344 	mutable T *_t;
345 	const FuncType _func;
346 };
347 
Action(LastExpressEngine * engine)348 Action::Action(LastExpressEngine *engine) : _engine(engine) {
349 	ADD_ACTION(dummy);
350 	ADD_ACTION(inventory);
351 	ADD_ACTION(savePoint);
352 	ADD_ACTION(playSound);
353 	ADD_ACTION(playMusic);
354 	ADD_ACTION(knock);                    // 5
355 	ADD_ACTION(compartment);
356 	ADD_ACTION(playSounds);
357 	ADD_ACTION(playAnimation);
358 	ADD_ACTION(openCloseObject);
359 	ADD_ACTION(setModel);                 // 10
360 	ADD_ACTION(setItem);
361 	ADD_ACTION(knockInside);
362 	ADD_ACTION(pickItem);
363 	ADD_ACTION(dropItem);
364 	ADD_ACTION(dummy);                    // 15
365 	ADD_ACTION(enterCompartment);
366 	ADD_ACTION(dummy);
367 	ADD_ACTION(leanOutWindow);
368 	ADD_ACTION(almostFall);
369 	ADD_ACTION(climbInWindow);           // 20
370 	ADD_ACTION(climbLadder);
371 	ADD_ACTION(climbDownTrain);
372 	ADD_ACTION(kronosSanctum);
373 	ADD_ACTION(escapeBaggage);
374 	ADD_ACTION(enterBaggage);            // 25
375 	ADD_ACTION(bombPuzzle);
376 	ADD_ACTION(27);
377 	ADD_ACTION(kronosConcert);
378 	ADD_ACTION(29);
379 	ADD_ACTION(catchBeetle);              // 30
380 	ADD_ACTION(exitCompartment);
381 	ADD_ACTION(outsideTrain);
382 	ADD_ACTION(firebirdPuzzle);
383 	ADD_ACTION(openMatchBox);
384 	ADD_ACTION(openBed);                 // 35
385 	ADD_ACTION(dummy);
386 	ADD_ACTION(dialog);
387 	ADD_ACTION(eggBox);
388 	ADD_ACTION(39);
389 	ADD_ACTION(bed);                     // 40
390 	ADD_ACTION(playMusicChapter);
391 	ADD_ACTION(playMusicChapterSetupTrain);
392 	ADD_ACTION(switchChapter);
393 	ADD_ACTION(44);
394 }
395 
~Action()396 Action::~Action() {
397 	for (uint i = 0; i < _actions.size(); i++)
398 		SAFE_DELETE(_actions[i]);
399 
400 	_actions.clear();
401 
402 	// Zero-out passed pointers
403 	_engine = NULL;
404 }
405 
406 //////////////////////////////////////////////////////////////////////////
407 // Processing hotspot
408 //////////////////////////////////////////////////////////////////////////
processHotspot(const SceneHotspot & hotspot)409 SceneIndex Action::processHotspot(const SceneHotspot &hotspot) {
410 	if (!hotspot.action || hotspot.action >= (int)_actions.size())
411 		return kSceneInvalid;
412 
413 	return (*_actions[hotspot.action])(hotspot);
414 }
415 
416 //////////////////////////////////////////////////////////////////////////
417 // Actions
418 //////////////////////////////////////////////////////////////////////////
419 
420 //////////////////////////////////////////////////////////////////////////
421 // Action 0
422 IMPLEMENT_ACTION(dummy)
423 	error("[Action::action_dummy] Dummy action function called (hotspot action: %d)", hotspot.action);
424 }
425 
426 //////////////////////////////////////////////////////////////////////////
427 // Action 1
428 IMPLEMENT_ACTION(inventory)
429 	if (!getState()->sceneUseBackup)
430 		return kSceneInvalid;
431 
432 	SceneIndex index = kSceneNone;
433 	if (getState()->sceneBackup2) {
434 		index = getState()->sceneBackup2;
435 		getState()->sceneBackup2 = kSceneNone;
436 	} else {
437 		getState()->sceneUseBackup = false;
438 		index = getState()->sceneBackup;
439 
440 		Scene *backup = getScenes()->get(getState()->sceneBackup);
441 		if (getEntities()->getPosition(backup->car, backup->position))
442 			index = getScenes()->processIndex(getState()->sceneBackup);
443 	}
444 
445 	getScenes()->loadScene(index);
446 
447 	if (!getInventory()->getSelectedItem())
448 		return kSceneInvalid;
449 
450 	if (!getInventory()->getSelectedEntry()->isSelectable || (!getState()->sceneBackup2 && getInventory()->getFirstExaminableItem()))
451 		getInventory()->selectItem(getInventory()->getFirstExaminableItem());
452 
453 	return kSceneInvalid;
454 }
455 
456 //////////////////////////////////////////////////////////////////////////
457 // Action 2
458 IMPLEMENT_ACTION(savePoint)
459 	getSavePoints()->push(kEntityPlayer, (EntityIndex)hotspot.param1, (ActionIndex)hotspot.param2);
460 
461 	return kSceneInvalid;
462 }
463 
464 //////////////////////////////////////////////////////////////////////////
465 // Action 3
466 IMPLEMENT_ACTION(playSound)
467 
468 	// Check that the file is not already buffered
469 	if (hotspot.param2 || !getSoundQueue()->isBuffered(Common::String::format("LIB%03d", hotspot.param1), true))
470 		getSound()->playSoundEvent(kEntityPlayer, hotspot.param1, hotspot.param2);
471 
472 	return kSceneInvalid;
473 }
474 
475 //////////////////////////////////////////////////////////////////////////
476 // Action 4
477 IMPLEMENT_ACTION(playMusic)
478 	// Check that the file is not already buffered
479 	Common::String filename = Common::String::format("MUS%03d", hotspot.param1);
480 
481 	if (!getSoundQueue()->isBuffered(filename) && (hotspot.param1 != 50 || getProgress().chapter == kChapter5))
482 		getSound()->playSound(kEntityPlayer, filename, kVolumeFull, hotspot.param2);
483 
484 	return kSceneInvalid;
485 }
486 
487 //////////////////////////////////////////////////////////////////////////
488 // Action 5
489 IMPLEMENT_ACTION(knock)
490 	ObjectIndex object = (ObjectIndex)hotspot.param1;
491 	if (object >= kObjectMax)
492 		return kSceneInvalid;
493 
494 	if (getObjects()->get(object).entity) {
495 		getSavePoints()->push(kEntityPlayer, getObjects()->get(object).entity, kActionKnock, object);
496 	} else {
497 		if (!getSoundQueue()->isBuffered("LIB012", true))
498 			getSound()->playSoundEvent(kEntityPlayer, 12);
499 	}
500 
501 	return kSceneInvalid;
502 }
503 
504 //////////////////////////////////////////////////////////////////////////
505 // Action 6
506 IMPLEMENT_ACTION(compartment)
507 	ObjectIndex compartment = (ObjectIndex)hotspot.param1;
508 
509 	if (compartment >= kObjectMax)
510 		return kSceneInvalid;
511 
512 	if (getObjects()->get(compartment).entity) {
513 		getSavePoints()->push(kEntityPlayer, getObjects()->get(compartment).entity, kActionOpenDoor, compartment);
514 
515 		// Stop processing further
516 		return kSceneNone;
517 	}
518 
519 	if (handleOtherCompartment(compartment, true, true)) {
520 		// Stop processing further
521 		return kSceneNone;
522 	}
523 
524 	ObjectLocation location = getObjects()->get(compartment).status;
525 	if (location == kObjectLocation1 || location == kObjectLocation3 || getEntities()->checkFields2(compartment)) {
526 
527 		if (location != kObjectLocation1 || getEntities()->checkFields2(compartment)
528 		 || (getInventory()->getSelectedItem() != kItemKey
529 		 && (compartment != kObjectCompartment1
530 		  || !getInventory()->hasItem(kItemKey)
531 		  || (getInventory()->getSelectedItem() != kItemFirebird && getInventory()->getSelectedItem() != kItemBriefcase)))) {
532 			if (!getSoundQueue()->isBuffered("LIB13"))
533 				getSound()->playSoundEvent(kEntityPlayer, 13);
534 
535 			// Stop processing further
536 			return kSceneNone;
537 		}
538 
539 		getSound()->playSoundEvent(kEntityPlayer, 32);
540 
541 		if ((compartment >= kObjectCompartment1 && compartment <= kObjectCompartment3) || (compartment >= kObjectCompartmentA && compartment <= kObjectCompartmentF))
542 			getObjects()->update(compartment, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand);
543 
544 		getSound()->playSoundEvent(kEntityPlayer, 15, 22);
545 		getInventory()->unselectItem();
546 
547 		return kSceneInvalid;
548 	}
549 
550 	if (hotspot.action != SceneHotspot::kActionEnterCompartment || getInventory()->getSelectedItem() != kItemKey) {
551 		if (compartment == kObjectCageMax) {
552 			getSound()->playSoundEvent(kEntityPlayer, 26);
553 		} else {
554 			getSound()->playSoundEvent(kEntityPlayer, 14);
555 			getSound()->playSoundEvent(kEntityPlayer, 15, 22);
556 		}
557 		return kSceneInvalid;
558 	}
559 
560 	getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand);
561 	getSound()->playSoundEvent(kEntityPlayer, 16);
562 	getInventory()->unselectItem();
563 
564 	// Stop processing further
565 	return kSceneNone;
566 }
567 
568 //////////////////////////////////////////////////////////////////////////
569 // Action 7
570 IMPLEMENT_ACTION(playSounds)
571 	getSound()->playSoundEvent(kEntityPlayer, hotspot.param1);
572 	getSound()->playSoundEvent(kEntityPlayer, hotspot.param3, hotspot.param2);
573 
574 	return kSceneInvalid;
575 }
576 
577 //////////////////////////////////////////////////////////////////////////
578 // Action 8
579 IMPLEMENT_ACTION(playAnimation)
580 	if (getEvent(hotspot.param1))
581 		return kSceneInvalid;
582 
583 	playAnimation((EventIndex)hotspot.param1);
584 
585 	if (!hotspot.scene)
586 		getScenes()->processScene();
587 
588 	return kSceneInvalid;
589 }
590 
591 //////////////////////////////////////////////////////////////////////////
592 // Action 9
593 IMPLEMENT_ACTION(openCloseObject)
594 	ObjectIndex object = (ObjectIndex)hotspot.param1;
595 	ObjectLocation location = (ObjectLocation)hotspot.param2;
596 
597 	if (object >= kObjectMax)
598 		return kSceneInvalid;
599 
600 	getObjects()->update(object, getObjects()->get(object).entity, location, kCursorKeepValue, kCursorKeepValue);
601 
602 	bool isNotWindow = ((object <= kObjectCompartment8  || object >= kObjectHandleBathroom) && (object <= kObjectCompartmentH || object >= kObject48));
603 
604 	switch (location) {
605 	default:
606 		break;
607 
608 	case kObjectLocation1:
609 		if (isNotWindow)
610 			getSound()->playSoundEvent(kEntityPlayer, 24);
611 		else
612 			getSound()->playSoundEvent(kEntityPlayer, 21);
613 		break;
614 
615 	case kObjectLocation2:
616 		if (isNotWindow)
617 			getSound()->playSoundEvent(kEntityPlayer, 36);
618 		else
619 			getSound()->playSoundEvent(kEntityPlayer, 20);
620 		break;
621 	}
622 
623 	return kSceneInvalid;
624 }
625 
626 //////////////////////////////////////////////////////////////////////////
627 // Action 10
628 IMPLEMENT_ACTION(setModel)
629 	ObjectIndex object = (ObjectIndex)hotspot.param1;
630 	ObjectModel model = (ObjectModel)hotspot.param2;
631 
632 	if (object >= kObjectMax)
633 		return kSceneInvalid;
634 
635 	getObjects()->updateModel(object, model);
636 
637 	if (object != kObject112 || getSoundQueue()->isBuffered("LIB096")) {
638 		if (object == 1)
639 			getSound()->playSoundEvent(kEntityPlayer, 73);
640 	} else {
641 		getSound()->playSoundEvent(kEntityPlayer, 96);
642 	}
643 
644 	return kSceneInvalid;
645 }
646 
647 //////////////////////////////////////////////////////////////////////////
648 // Action 11
649 IMPLEMENT_ACTION(setItem)
650 	InventoryItem item = (InventoryItem)hotspot.param1;
651 	if (item >= kPortraitOriginal)
652 		return kSceneInvalid;
653 
654 	Inventory::InventoryEntry *entry = getInventory()->get(item);
655 	if (entry->inPocket)
656 		return kSceneInvalid;
657 
658 	entry->location = (ObjectLocation)hotspot.param2;
659 
660 	if (item == kItemCorpse) {
661 		ObjectLocation corpseLocation = getInventory()->get(kItemCorpse)->location;
662 		getProgress().eventCorpseMovedFromFloor = (corpseLocation == kObjectLocation3 || corpseLocation == kObjectLocation4);
663 	}
664 
665 	return kSceneInvalid;
666 }
667 
668 //////////////////////////////////////////////////////////////////////////
669 // Action 12
670 IMPLEMENT_ACTION(knockInside)
671 	ObjectIndex object = (ObjectIndex)hotspot.param1;
672 	if (object >= kObjectMax)
673 		return kSceneInvalid;
674 
675 	if (getObjects()->get(object).entity)
676 		getSavePoints()->push(kEntityPlayer, getObjects()->get(object).entity, kActionKnock, object);
677 
678 	return kSceneInvalid;
679 }
680 
681 //////////////////////////////////////////////////////////////////////////
682 // Action 13
683 IMPLEMENT_ACTION(pickItem)
684 	InventoryItem item = (InventoryItem)hotspot.param1;
685 	ObjectLocation location = (ObjectLocation)hotspot.param2;
686 	bool process = (hotspot.scene == 0);
687 	SceneIndex sceneIndex = kSceneInvalid;
688 
689 	if (item >= kPortraitOriginal)
690 		return kSceneInvalid;
691 
692 	Inventory::InventoryEntry *entry = getInventory()->get(item);
693 	if (!entry->location)
694 		return kSceneInvalid;
695 
696 	// Special case for corpse
697 	if (item == kItemCorpse) {
698 		pickCorpse(location, process);
699 		return kSceneInvalid;
700 	}
701 
702 	// Add and process items
703 	getInventory()->addItem(item);
704 
705 	switch (item) {
706 	default:
707 		break;
708 
709 	case kItemGreenJacket:
710 		pickGreenJacket(process);
711 		break;
712 
713 	case kItemScarf:
714 		pickScarf(process);
715 
716 		// stop processing
717 		return kSceneInvalid;
718 
719 	case kItemParchemin:
720 		if (location != kObjectLocation2)
721 			break;
722 
723 		getInventory()->addItem(kItemParchemin);
724 		getInventory()->get(kItem11)->location = kObjectLocation1;
725 		getSound()->playSoundEvent(kEntityPlayer, 9);
726 		break;
727 
728 	case kItemBomb:
729 		RESET_ENTITY_STATE(kEntityAbbot, Abbot, setup_catchCath);
730 		break;
731 
732 	case kItemBriefcase:
733 		getSound()->playSoundEvent(kEntityPlayer, 83);
734 		break;
735 	}
736 
737 	// Load item scene
738 	if (getInventory()->get(item)->scene) {
739 		if (!getState()->sceneUseBackup) {
740 			getState()->sceneUseBackup = true;
741 			getState()->sceneBackup = (hotspot.scene ? hotspot.scene : getState()->scene);
742 		}
743 
744 		getScenes()->loadScene(getInventory()->get(item)->scene);
745 
746 		// do not process further
747 		sceneIndex = kSceneNone;
748 	}
749 
750 	// Select item
751 	if (getInventory()->get(item)->isSelectable) {
752 		getInventory()->selectItem(item);
753 		_engine->getCursor()->setStyle(getInventory()->get(item)->cursor);
754 	}
755 
756 	return sceneIndex;
757 }
758 
759 //////////////////////////////////////////////////////////////////////////
760 // Action 14
761 IMPLEMENT_ACTION(dropItem)
762 	InventoryItem item = (InventoryItem)hotspot.param1;
763 	ObjectLocation location = (ObjectLocation)hotspot.param2;
764 	bool process = (hotspot.scene == kSceneNone);
765 
766 	if (item >= kPortraitOriginal)
767 		return kSceneInvalid;
768 
769 	if (!getInventory()->hasItem(item))
770 		return kSceneInvalid;
771 
772 	if (location < kObjectLocation1)
773 		return kSceneInvalid;
774 
775 	// Handle actions
776 	if (item == kItemBriefcase) {
777 		getSound()->playSoundEvent(kEntityPlayer, 82);
778 
779 		if (location == kObjectLocation2) {
780 			if (!getProgress().field_58) {
781 				getSaveLoad()->saveGame(kSavegameTypeTime, kEntityPlayer, kTimeNone);
782 				getProgress().field_58 = 1;
783 			}
784 
785 			if (getInventory()->get(kItemParchemin)->location == kObjectLocation2) {
786 				getInventory()->addItem(kItemParchemin);
787 				getInventory()->get(kItem11)->location = kObjectLocation1;
788 				getSound()->playSoundEvent(kEntityPlayer, 9);
789 			}
790 		}
791 	}
792 
793 	// Update item location
794 	getInventory()->removeItem(item, location);
795 
796 	if (item == kItemCorpse)
797 		dropCorpse(process);
798 
799 	// Unselect item
800 	getInventory()->unselectItem();
801 
802 	return kSceneInvalid;
803 }
804 
805 //////////////////////////////////////////////////////////////////////////
806 // Action 15: Dummy action
807 
808 //////////////////////////////////////////////////////////////////////////
809 // Action 16
810 IMPLEMENT_ACTION(enterCompartment)
811 	if (getObjects()->get(kObjectCompartment1).status == kObjectLocation1 || getObjects()->get(kObjectCompartment1).status == kObjectLocation3 || getInventory()->getSelectedItem() == kItemKey)
812 		return action_compartment(hotspot);
813 
814 	if (getProgress().eventCorpseFound) {
815 		if (hotspot.action != SceneHotspot::kActionEnterCompartment || getInventory()->get(kItemBriefcase)->location != kObjectLocation2)
816 			return action_compartment(hotspot);
817 
818 		getSound()->playSoundEvent(kEntityPlayer, 14);
819 		getSound()->playSoundEvent(kEntityPlayer, 15, 22);
820 
821 		if (getProgress().field_78 && !getSoundQueue()->isBuffered("MUS003")) {
822 			getSound()->playSound(kEntityPlayer, "MUS003", kVolumeFull);
823 			getProgress().field_78 = 0;
824 		}
825 
826 		getScenes()->loadSceneFromPosition(kCarGreenSleeping, 77);
827 
828 		return kSceneNone;
829 	}
830 
831 	getSaveLoad()->saveGame(kSavegameTypeTime, kEntityPlayer, kTimeNone);
832 	getSound()->playSound(kEntityPlayer, "LIB014");
833 	playAnimation(kEventCathFindCorpse);
834 	getSound()->playSound(kEntityPlayer, "LIB015");
835 	getProgress().eventCorpseFound = true;
836 
837 	return kSceneCompartmentCorpse;
838 }
839 
840 //////////////////////////////////////////////////////////////////////////
841 // Action 17: Dummy action
842 
843 //////////////////////////////////////////////////////////////////////////
844 // Action 18
845 IMPLEMENT_ACTION(leanOutWindow)
846 	ObjectIndex object = (ObjectIndex)hotspot.param1;
847 
848 	if ((getEvent(kEventCathLookOutsideWindowDay) || getEvent(kEventCathLookOutsideWindowNight) || getObjects()->get(kObjectCompartment1).model == kObjectModel1)
849 	  && getProgress().isTrainRunning
850 	  && (object != kObjectOutsideAnnaCompartment || (!getEntities()->isInsideCompartment(kEntityRebecca, kCarRedSleeping, kPosition_4840) && getObjects()->get(kObjectOutsideBetweenCompartments).status == kObjectLocation2))
851 	  && getInventory()->getSelectedItem() != kItemFirebird
852 	  && getInventory()->getSelectedItem() != kItemBriefcase) {
853 
854 		switch (object) {
855 		default:
856 			return kSceneInvalid;
857 
858 		case kObjectOutsideTylerCompartment:
859 			getEvent(kEventCathLookOutsideWindowDay) = 1;
860 			playAnimation(isNight() ? kEventCathGoOutsideTylerCompartmentNight : kEventCathGoOutsideTylerCompartmentDay);
861 			getProgress().field_C8 = 1;
862 			break;
863 
864 		case kObjectOutsideBetweenCompartments:
865 			getEvent(kEventCathLookOutsideWindowDay) = 1;
866 			playAnimation(isNight() ? kEventCathGoOutsideNight : kEventCathGoOutsideDay);
867 			getProgress().field_C8 = 1;
868 			break;
869 
870 		case kObjectOutsideAnnaCompartment:
871 			getEvent(kEventCathLookOutsideWindowDay) = 1;
872 			playAnimation(isNight() ? kEventCathGetInsideNight : kEventCathGetInsideDay);
873 			if (!hotspot.scene)
874 				getScenes()->processScene();
875 			break;
876 		}
877 	} else {
878 		if (object == kObjectOutsideTylerCompartment || object == kObjectOutsideBetweenCompartments || object == kObjectOutsideAnnaCompartment) {
879 			playAnimation(isNight() ? kEventCathLookOutsideWindowNight : kEventCathLookOutsideWindowDay);
880 			getScenes()->processScene();
881 			return kSceneNone;
882 		}
883 	}
884 
885 	return kSceneInvalid;
886 }
887 
888 //////////////////////////////////////////////////////////////////////////
889 // Action 19
890 IMPLEMENT_ACTION(almostFall)
891 	switch((ObjectIndex)hotspot.param1) {
892 	default:
893 		return kSceneInvalid;
894 
895 	case kObjectOutsideTylerCompartment:
896 		playAnimation(isNight() ? kEventCathSlipTylerCompartmentNight : kEventCathSlipTylerCompartmentDay);
897 		break;
898 
899 	case kObjectOutsideBetweenCompartments:
900 		playAnimation(isNight() ? kEventCathSlipNight : kEventCathSlipDay);
901 		break;
902 	}
903 
904 	getProgress().field_C8 = 0;
905 
906 	if (!hotspot.scene)
907 		getScenes()->processScene();
908 
909 	return kSceneInvalid;
910 }
911 
912 //////////////////////////////////////////////////////////////////////////
913 // Action 20
914 IMPLEMENT_ACTION(climbInWindow)
915 	switch ((ObjectIndex)hotspot.param1) {
916 	default:
917 		return kSceneInvalid;
918 
919 	case kObjectOutsideTylerCompartment:
920 		playAnimation(isNight() ? kEventCathGetInsideTylerCompartmentNight : kEventCathGetInsideTylerCompartmentDay);
921 		break;
922 
923 	case kObjectOutsideBetweenCompartments:
924 		playAnimation(isNight() ? kEventCathGetInsideNight : kEventCathGetInsideDay);
925 		break;
926 
927 	case kObjectOutsideAnnaCompartment:
928 		playAnimation(kEventCathGettingInsideAnnaCompartment);
929 		break;
930 	}
931 
932 	if (!hotspot.scene)
933 		getScenes()->processScene();
934 
935 	return kSceneInvalid;
936 }
937 
938 //////////////////////////////////////////////////////////////////////////
939 // Action 21
940 IMPLEMENT_ACTION(climbLadder)
941 	byte action = hotspot.param1;
942 
943 	if (action != 1 && action != 2)
944 		return kSceneInvalid;
945 
946 	switch (getProgress().chapter) {
947 	default:
948 		break;
949 
950 	case kChapter2:
951 	case kChapter3:
952 		if (action == 2)
953 			playAnimation(kEventCathClimbUpTrainGreenJacket);
954 
955 		playAnimation(kEventCathTopTrainGreenJacket);
956 		break;
957 
958 	case kChapter5:
959 		if (action == 2)
960 			playAnimation(getProgress().isNightTime ? kEventCathClimbUpTrainNoJacketNight : kEventCathClimbUpTrainNoJacketDay);
961 
962 		playAnimation(getProgress().isNightTime ? kEventCathTopTrainNoJacketNight : kEventCathTopTrainNoJacketDay);
963 		break;
964 	}
965 
966 	if (!hotspot.scene)
967 		getScenes()->processScene();
968 
969 	return kSceneInvalid;
970 }
971 
972 //////////////////////////////////////////////////////////////////////////
973 // Action 22
974 IMPLEMENT_ACTION(climbDownTrain)
975 	EventIndex evt = kEventNone;
976 	switch (getProgress().chapter) {
977 	default:
978 		return kSceneInvalid;
979 
980 	case kChapter2:
981 	case kChapter3:
982 		evt = kEventCathClimbDownTrainGreenJacket;
983 		break;
984 
985 	case kChapter5:
986 		evt = (getProgress().isNightTime ? kEventCathClimbDownTrainNoJacketNight : kEventCathClimbDownTrainNoJacketDay);
987 		break;
988 	}
989 
990 	playAnimation(evt);
991 	if (evt == kEventCathClimbDownTrainNoJacketDay)
992 		getSound()->playSoundEvent(kEntityPlayer, 37);
993 
994 	if (!hotspot.scene)
995 		getScenes()->processScene();
996 
997 	return kSceneInvalid;
998 }
999 
1000 //////////////////////////////////////////////////////////////////////////
1001 // Action 23
1002 IMPLEMENT_ACTION(kronosSanctum)
1003 	switch (hotspot.param1) {
1004 	default:
1005 		break;
1006 
1007 	case 1:
1008 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kActionBreakCeiling);
1009 		break;
1010 
1011 	case 2:
1012 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kActionJumpDownCeiling);
1013 		break;
1014 
1015 	case 3:
1016 		if (getInventory()->getSelectedItem() == kItemBriefcase) {
1017 			getInventory()->removeItem(kItemBriefcase, kObjectLocation3);
1018 			getSound()->playSoundEvent(kEntityPlayer, 82);
1019 			getInventory()->unselectItem();
1020 		}
1021 
1022 		// Show animation with or without briefcase
1023 		playAnimation((getInventory()->get(kItemBriefcase)->location - 3) ? kEventCathJumpUpCeilingBriefcase : kEventCathJumpUpCeiling);
1024 
1025 		if (!hotspot.scene)
1026 			getScenes()->processScene();
1027 
1028 		break;
1029 
1030 	case 4:
1031 		if (getProgress().chapter == kChapter1)
1032 			getSavePoints()->push(kEntityPlayer, kEntityKronos, kAction202621266);
1033 		break;
1034 	}
1035 
1036 	return kSceneInvalid;
1037 }
1038 
1039 //////////////////////////////////////////////////////////////////////////
1040 // Action 24
1041 IMPLEMENT_ACTION(escapeBaggage)
1042 	byte action = hotspot.param1;
1043 
1044 	switch (action) {
1045 	default:
1046 		break;
1047 
1048 	case 1:
1049 		playAnimation(kEventCathStruggleWithBonds);
1050 		if (hotspot.scene)
1051 			getScenes()->processScene();
1052 		break;
1053 
1054 	case 2:
1055 		playAnimation(kEventCathBurnRope);
1056 		if (hotspot.scene)
1057 			getScenes()->processScene();
1058 		break;
1059 
1060 	case 3:
1061 		if (getEvent(kEventCathBurnRope)) {
1062 			playAnimation(kEventCathRemoveBonds);
1063 			getProgress().field_84 = 0;
1064 			getScenes()->loadSceneFromPosition(kCarBaggageRear, 89);
1065 			return kSceneNone;
1066 		}
1067 		break;
1068 
1069 	case 4:
1070 		if (!getEvent(kEventCathStruggleWithBonds2)) {
1071 			playAnimation(kEventCathStruggleWithBonds2);
1072 			getSound()->playSoundEvent(kEntityPlayer, 101);
1073 			getInventory()->setLocationAndProcess(kItemMatch, kObjectLocation2);
1074 			if (!hotspot.scene)
1075 				getScenes()->processScene();
1076 		}
1077 		break;
1078 
1079 	case 5:
1080 		getSavePoints()->push(kEntityPlayer, kEntityIvo, kAction192637492);
1081 		break;
1082 	}
1083 
1084 	return kSceneInvalid;
1085 }
1086 
1087 //////////////////////////////////////////////////////////////////////////
1088 // Action 25
1089 IMPLEMENT_ACTION(enterBaggage)
1090 	switch(hotspot.param1) {
1091 	default:
1092 		break;
1093 
1094 	case 1:
1095 		getSavePoints()->push(kEntityPlayer, kEntityAnna, kAction272177921);
1096 		break;
1097 
1098 	case 2:
1099 		if (!getSoundQueue()->isBuffered("MUS021"))
1100 			getSound()->playSound(kEntityPlayer, "MUS021", kVolumeFull);
1101 		break;
1102 
1103 	case 3:
1104 		getSound()->playSoundEvent(kEntityPlayer, 43);
1105 		if (!getInventory()->hasItem(kItemKey) && !getEvent(kEventAnnaBaggageArgument)) {
1106 			RESET_ENTITY_STATE(kEntityAnna, Anna, setup_baggageFight);
1107 			return kSceneNone;
1108 		}
1109 		break;
1110 	}
1111 
1112 	return kSceneInvalid;
1113 }
1114 
1115 //////////////////////////////////////////////////////////////////////////
1116 // Action 26
1117 IMPLEMENT_ACTION(bombPuzzle)
1118 	switch(hotspot.param1) {
1119 	default:
1120 		return kSceneInvalid;
1121 
1122 	case 1:
1123 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kAction158610240);
1124 		break;
1125 
1126 	case 2:
1127 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kAction225367984);
1128 		getInventory()->unselectItem();
1129 		return kSceneNone;
1130 
1131 	case 3:
1132 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kAction191001984);
1133 		return kSceneNone;
1134 
1135 	case 4:
1136 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kAction201959744);
1137 		return kSceneNone;
1138 
1139 	case 5:
1140 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kAction169300225);
1141 		break;
1142 	}
1143 
1144 	return kSceneInvalid;
1145 }
1146 
1147 //////////////////////////////////////////////////////////////////////////
1148 // Action 27
1149 IMPLEMENT_ACTION(27)
1150 	if (!getSoundQueue()->isBuffered("LIB031", true))
1151 		getSound()->playSoundEvent(kEntityPlayer, 31);
1152 
1153 	switch (getEntityData(kEntityPlayer)->car) {
1154 	default:
1155 		break;
1156 
1157 	case kCarGreenSleeping:
1158 		getSavePoints()->push(kEntityPlayer, kEntityMertens, kAction225358684, hotspot.param1);
1159 		break;
1160 
1161 	case kCarRedSleeping:
1162 		getSavePoints()->push(kEntityPlayer, kEntityCoudert, kAction225358684, hotspot.param1);
1163 		break;
1164 	}
1165 
1166 	return kSceneInvalid;
1167 }
1168 
1169 //////////////////////////////////////////////////////////////////////////
1170 // Action 28
1171 IMPLEMENT_ACTION(kronosConcert)
1172 	switch(hotspot.param1) {
1173 	default:
1174 		return kSceneInvalid;
1175 
1176 	case 1:
1177 		playAnimation(kEventConcertSit);
1178 		break;
1179 
1180 	case 2:
1181 		playAnimation(kEventConcertCough);
1182 		break;
1183 	}
1184 
1185 	if (!hotspot.scene)
1186 		getScenes()->processScene();
1187 
1188 	return kSceneInvalid;
1189 }
1190 
1191 //////////////////////////////////////////////////////////////////////////
1192 // Action 29
1193 IMPLEMENT_ACTION(29)
1194 	getProgress().field_C = 1;
1195 	getSound()->playSoundEvent(kEntityPlayer, hotspot.param1, hotspot.param2);
1196 
1197 	Common::String filename = Common::String::format("MUS%03d", hotspot.param3);
1198 	if (!getSoundQueue()->isBuffered(filename))
1199 		getSound()->playSound(kEntityPlayer, filename, kVolumeFull);
1200 
1201 	return kSceneInvalid;
1202 }
1203 
1204 //////////////////////////////////////////////////////////////////////////
1205 // Action 30
1206 IMPLEMENT_ACTION(catchBeetle)
1207 	if (!getBeetle()->isLoaded())
1208 		return kSceneInvalid;
1209 
1210 	if (getBeetle()->catchBeetle()) {
1211 		getBeetle()->unload();
1212 		getInventory()->get(kItemBeetle)->location = kObjectLocation1;
1213 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kActionCatchBeetle);
1214 	}
1215 
1216 	return kSceneInvalid;
1217 }
1218 
1219 //////////////////////////////////////////////////////////////////////////
1220 // Action 31
1221 IMPLEMENT_ACTION(exitCompartment)
1222 	if (!getProgress().field_30 && getProgress().jacket != kJacketOriginal) {
1223 		getSaveLoad()->saveGame(kSavegameTypeTime, kEntityPlayer, kTimeNone);
1224 		getProgress().field_30 = 1;
1225 	}
1226 
1227 	getObjects()->updateModel(kObjectCompartment1, (ObjectModel)hotspot.param2);
1228 
1229 	// fall to case enterCompartment action
1230 	return action_enterCompartment(hotspot);
1231 }
1232 
1233 //////////////////////////////////////////////////////////////////////////
1234 // Action 32
1235 IMPLEMENT_ACTION(outsideTrain)
1236 	switch(hotspot.param1) {
1237 	default:
1238 		break;
1239 
1240 	case 1:
1241 		getSavePoints()->push(kEntityPlayer, kEntitySalko, kAction167992577);
1242 		break;
1243 
1244 	case 2:
1245 		getSavePoints()->push(kEntityPlayer, kEntityVesna, kAction202884544);
1246 		break;
1247 
1248 	case 3:
1249 		if (getProgress().chapter == kChapter5) {
1250 			getSavePoints()->push(kEntityPlayer, kEntityAbbot, kAction168646401);
1251 			getSavePoints()->push(kEntityPlayer, kEntityMilos, kAction168646401);
1252 		} else {
1253 			getSavePoints()->push(kEntityPlayer, kEntityTrain, kAction203339360);
1254 		}
1255 		// Stop processing further scenes
1256 		return kSceneNone;
1257 
1258 	case 4:
1259 		getSavePoints()->push(kEntityPlayer, kEntityMilos, kAction169773228);
1260 		break;
1261 
1262 	case 5:
1263 		getSavePoints()->push(kEntityPlayer, kEntityVesna, kAction167992577);
1264 		break;
1265 
1266 	case 6:
1267 		getSavePoints()->push(kEntityPlayer, kEntityAugust, kAction203078272);
1268 		break;
1269 	}
1270 
1271 	return kSceneInvalid;
1272 }
1273 
1274 //////////////////////////////////////////////////////////////////////////
1275 // Action 33
1276 IMPLEMENT_ACTION(firebirdPuzzle)
1277 	EventIndex evt = kEventNone;
1278 	SceneIndex sceneIndex = kSceneInvalid;
1279 
1280 	switch (hotspot.param1) {
1281 	default:
1282 		break;
1283 
1284 	case 1:
1285 		if (getEvent(kEventKronosBringFirebird)) {
1286 			getSavePoints()->push(kEntityPlayer, kEntityAnna, kAction205294778);
1287 			break;
1288 		}
1289 
1290 		if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_8200)) {
1291 			evt = kEventCathOpenEgg;
1292 
1293 			Scene *scene = getScenes()->get(hotspot.scene);
1294 			if (scene->getHotspot())
1295 				sceneIndex = scene->getHotspot()->scene;
1296 
1297 		} else {
1298 			evt = kEventCathOpenEggNoBackground;
1299 		}
1300 		getProgress().isEggOpen = true;
1301 		break;
1302 
1303 	case 2:
1304 		if (getEvent(kEventKronosBringFirebird)) {
1305 			getSavePoints()->push(kEntityPlayer, kEntityAnna, kAction224309120);
1306 			break;
1307 		}
1308 
1309 		evt = (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_8200)) ? kEventCathCloseEgg : kEventCathCloseEggNoBackground;
1310 		getProgress().isEggOpen = false;
1311 		break;
1312 
1313 	case 3:
1314 		if (getEvent(kEventKronosBringFirebird)) {
1315 			getSavePoints()->push(kEntityPlayer, kEntityAnna, kActionUseWhistle);
1316 			break;
1317 		}
1318 
1319 		evt = (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_8200)) ? kEventCathUseWhistleOpenEgg : kEventCathUseWhistleOpenEggNoBackground;
1320 		break;
1321 
1322 	}
1323 
1324 	if (evt != kEventNone) {
1325 		playAnimation(evt);
1326 		if (sceneIndex == kSceneNone || !hotspot.scene)
1327 			getScenes()->processScene();
1328 	}
1329 
1330 	return sceneIndex;
1331 }
1332 
1333 //////////////////////////////////////////////////////////////////////////
1334 // Action 34
1335 IMPLEMENT_ACTION(openMatchBox)
1336 	// If the match is already in the inventory, do nothing
1337 	if (!getInventory()->get(kItemMatch)->location
1338 	 || getInventory()->get(kItemMatch)->inPocket)
1339 		return kSceneInvalid;
1340 
1341 	getInventory()->addItem(kItemMatch);
1342 	getSound()->playSoundEvent(kEntityPlayer, 102);
1343 
1344 	return kSceneInvalid;
1345 }
1346 
1347 //////////////////////////////////////////////////////////////////////////
1348 // Action 35
1349 IMPLEMENT_ACTION(openBed)
1350 	getSound()->playSoundEvent(kEntityPlayer, 59);
1351 
1352 	return kSceneInvalid;
1353 }
1354 
1355 //////////////////////////////////////////////////////////////////////////
1356 // Action 36: Dummy action
1357 
1358 //////////////////////////////////////////////////////////////////////////
1359 // Action 37
1360 IMPLEMENT_ACTION(dialog)
1361 	getSound()->playDialog(kEntityTables4, (EntityIndex)hotspot.param1, kVolumeFull, 0);
1362 
1363 	return kSceneInvalid;
1364 }
1365 
1366 //////////////////////////////////////////////////////////////////////////
1367 // Action 38
1368 IMPLEMENT_ACTION(eggBox)
1369 	getSound()->playSoundEvent(kEntityPlayer, 43);
1370 	if (getProgress().field_7C && !getSoundQueue()->isBuffered("MUS003")) {
1371 		getSound()->playSound(kEntityPlayer, "MUS003", kVolumeFull);
1372 		getProgress().field_7C = 0;
1373 	}
1374 
1375 	return kSceneInvalid;
1376 }
1377 
1378 //////////////////////////////////////////////////////////////////////////
1379 // Action 39
1380 IMPLEMENT_ACTION(39)
1381 	getSound()->playSoundEvent(kEntityPlayer, 24);
1382 	if (getProgress().field_80 && !getSoundQueue()->isBuffered("MUS003")) {
1383 		getSound()->playSound(kEntityPlayer, "MUS003", kVolumeFull);
1384 		getProgress().field_80 = 0;
1385 	}
1386 
1387 	return kSceneInvalid;
1388 }
1389 
1390 //////////////////////////////////////////////////////////////////////////
1391 // Action 40
1392 IMPLEMENT_ACTION(bed)
1393 	getSound()->playSoundEvent(kEntityPlayer, 85);
1394 	// falls to case knockNoSound
1395 	return action_knockInside(hotspot);
1396 }
1397 
1398 //////////////////////////////////////////////////////////////////////////
1399 // Action 41
1400 IMPLEMENT_ACTION(playMusicChapter)
1401 	byte id = 0;
1402 	switch (getProgress().chapter) {
1403 	default:
1404 		break;
1405 
1406 	case kChapter1:
1407 		id = hotspot.param1;
1408 		break;
1409 
1410 	case kChapter2:
1411 	case kChapter3:
1412 		id = hotspot.param2;
1413 		break;
1414 
1415 	case kChapter4:
1416 	case kChapter5:
1417 		id = hotspot.param3;
1418 		break;
1419 	}
1420 
1421 	if (id) {
1422 		Common::String filename = Common::String::format("MUS%03d", id);
1423 
1424 		if (!getSoundQueue()->isBuffered(filename))
1425 			getSound()->playSound(kEntityPlayer, filename, kVolumeFull);
1426 	}
1427 
1428 	return kSceneInvalid;
1429 }
1430 
1431 //////////////////////////////////////////////////////////////////////////
1432 // Action 42
1433 IMPLEMENT_ACTION(playMusicChapterSetupTrain)
1434 	int id = 0;
1435 	switch (getProgress().chapter) {
1436 	default:
1437 		break;
1438 
1439 	case kChapter1:
1440 		id = 1;
1441 		break;
1442 
1443 	case kChapter2:
1444 	case kChapter3:
1445 		id = 2;
1446 		break;
1447 
1448 	case kChapter4:
1449 	case kChapter5:
1450 		id = 4;
1451 		break;
1452 	}
1453 
1454 	Common::String filename = Common::String::format("MUS%03d", hotspot.param1);
1455 
1456 	if (!getSoundQueue()->isBuffered(filename) && hotspot.param3 & id) {
1457 		getSound()->playSound(kEntityPlayer, filename, kVolumeFull);
1458 
1459 		getSavePoints()->call(kEntityPlayer, kEntityTrain, kAction203863200, filename);
1460 		getSavePoints()->push(kEntityPlayer, kEntityTrain, kAction222746496, hotspot.param2);
1461 	}
1462 
1463 	return kSceneInvalid;
1464 }
1465 
1466 //////////////////////////////////////////////////////////////////////////
1467 // // Action 43
1468 IMPLEMENT_ACTION(switchChapter)
1469 	// Nothing to do here as an hotspot action
1470 	return kSceneInvalid;
1471 }
1472 
1473 //////////////////////////////////////////////////////////////////////////
1474 // Action 44
1475 IMPLEMENT_ACTION(44)
1476 	switch (hotspot.param1) {
1477 	default:
1478 		break;
1479 
1480 	case 1:
1481 		getSavePoints()->push(kEntityPlayer, kEntityRebecca, kAction205034665);
1482 		break;
1483 
1484 	case 2:
1485 		getSavePoints()->push(kEntityPlayer, kEntityChapters, kAction225358684);
1486 		break;
1487 	}
1488 
1489 	return kSceneInvalid;
1490 }
1491 
1492 //////////////////////////////////////////////////////////////////////////
1493 // Helper functions
1494 //////////////////////////////////////////////////////////////////////////
1495 void Action::pickGreenJacket(bool process) const {
1496 	getProgress().jacket = kJacketGreen;
1497 	getInventory()->addItem(kItemMatchBox);
1498 
1499 	getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue);
1500 	playAnimation(kEventPickGreenJacket);
1501 
1502 	getInventory()->setPortrait(kPortraitGreen);
1503 
1504 	if (process)
1505 		getScenes()->processScene();
1506 }
1507 
1508 void Action::pickScarf(bool process) const {
1509 	playAnimation(getProgress().jacket == kJacketGreen ? kEventPickScarfGreen : kEventPickScarfOriginal);
1510 
1511 	if (process)
1512 		getScenes()->processScene();
1513 }
1514 
1515 void Action::pickCorpse(ObjectLocation bedPosition, bool process) const {
1516 
1517 	if (getProgress().jacket == kJacketOriginal)
1518 		getProgress().jacket = kJacketBlood;
1519 
1520 	switch(getInventory()->get(kItemCorpse)->location) {
1521 	// No way to pick the corpse
1522 	default:
1523 		break;
1524 
1525 	// Floor
1526 	case kObjectLocation1:
1527 		// Bed is fully opened, move corpse directly there
1528 		if (bedPosition == 4) {
1529 			playAnimation(kEventCorpsePickFloorOpenedBedOriginal);
1530 
1531 			getInventory()->get(kItemCorpse)->location = kObjectLocation5;
1532 			break;
1533 		}
1534 
1535 		playAnimation(getProgress().jacket == kJacketGreen ? kEventCorpsePickFloorGreen : kEventCorpsePickFloorOriginal);
1536 		break;
1537 
1538 	// Bed
1539 	case kObjectLocation2:
1540 		playAnimation(getProgress().jacket == kJacketGreen ? kEventCorpsePickBedGreen : kEventCorpsePickBedOriginal);
1541 		break;
1542 	}
1543 
1544 	if (process)
1545 		getScenes()->processScene();
1546 
1547 	// Add corpse to inventory
1548 	if (bedPosition != 4) { // bed is not fully opened
1549 		getInventory()->addItem(kItemCorpse);
1550 		getInventory()->selectItem(kItemCorpse);
1551 		_engine->getCursor()->setStyle(kCursorCorpse);
1552 	}
1553 }
1554 
1555 void Action::dropCorpse(bool process) const {
1556 	switch(getInventory()->get(kItemCorpse)->location) {
1557 	default:
1558 		break;
1559 
1560 	case kObjectLocation1:	// Floor
1561 		playAnimation(getProgress().jacket == kJacketGreen ? kEventCorpseDropFloorGreen : kEventCorpseDropFloorOriginal);
1562 		break;
1563 
1564 	case kObjectLocation2:	// Bed
1565 		playAnimation(getProgress().jacket == kJacketGreen ? kEventCorpseDropBedGreen : kEventCorpseDropBedOriginal);
1566 		break;
1567 
1568 	case kObjectLocation4: // Window
1569 		// Say goodbye to an old friend
1570 		getInventory()->get(kItemCorpse)->location = kObjectLocationNone;
1571 		getProgress().eventCorpseThrown = true;
1572 
1573 		if (getState()->time <= kTime1138500) {
1574 			playAnimation(getProgress().jacket == kJacketGreen ? kEventCorpseDropWindowGreen : kEventCorpseDropWindowOriginal);
1575 
1576 			getProgress().field_24 = true;
1577 		} else {
1578 			playAnimation(kEventCorpseDropBridge);
1579 		}
1580 
1581 		getProgress().eventCorpseMovedFromFloor = true;
1582 		break;
1583 	}
1584 
1585 	if (process)
1586 		getScenes()->processScene();
1587 }
1588 
1589 bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool doLoadScene) const {
1590 #define ENTITY_PARAMS(entity, index, id) \
1591 	((EntityData::EntityParametersIIII*)getEntities()->get(entity)->getParamData()->getParameters(8, index))->param##id
1592 
1593 	// Only handle compartments
1594 	if (getEntityData(kEntityPlayer)->location != kLocationOutsideCompartment
1595 	|| ((object < kObjectCompartment2 || object > kObjectCompartment8) && (object < kObjectCompartmentA || object > kObjectCompartmentH)))
1596 		return false;
1597 
1598 	//////////////////////////////////////////////////////////////////////////
1599 	// Gendarmes
1600 	if (getEntityData(kEntityPlayer)->car == getEntityData(kEntityGendarmes)->car
1601 	&& getEntityData(kEntityGendarmes)->location == kLocationOutsideCompartment
1602 	&& !getEntities()->compare(kEntityPlayer, kEntityGendarmes)) {
1603 		if (doPlaySound)
1604 			playCompartmentSoundEvents(object);
1605 
1606 		if (doLoadScene)
1607 			getScenes()->loadSceneFromObject(object);
1608 
1609 		return true;
1610 	}
1611 
1612 	//////////////////////////////////////////////////////////////////////////
1613 	// Mertens
1614 	if (getEntityData(kEntityPlayer)->car == kCarGreenSleeping
1615 	 && getEntityData(kEntityMertens)->car == kCarGreenSleeping
1616 	 && !getEntityData(kEntityMertens)->location
1617 	 && !ENTITY_PARAMS(kEntityMertens, 0, 1)) {
1618 
1619 		if (!getEntities()->compare(kEntityPlayer, kEntityMertens)) {
1620 
1621 			if (getEntityData(kEntityMertens)->entityPosition < kPosition_2740
1622 			 && getEntityData(kEntityMertens)->entityPosition > kPosition_850
1623 			 && (getEntityData(kEntityCoudert)->car != kCarGreenSleeping || getEntityData(kEntityCoudert)->entityPosition > kPosition_2740)
1624 			 && (getEntityData(kEntityVerges)->car != kCarGreenSleeping || getEntityData(kEntityVerges)->entityPosition > kPosition_2740)) {
1625 				if (doPlaySound)
1626 					playCompartmentSoundEvents(object);
1627 
1628 				if (!getSoundQueue()->isBuffered(kEntityMertens))
1629 					getSound()->playWarningCompartment(kEntityMertens, object);
1630 
1631 				getSavePoints()->push(kEntityPlayer, kEntityMertens, kAction305159806);
1632 
1633 				if (doLoadScene)
1634 					getScenes()->loadSceneFromObject(object);
1635 
1636 				return true;
1637 			}
1638 
1639 			if (getEntityData(kEntityMertens)->direction == kDirectionUp
1640 			 && getEntityData(kEntityMertens)->entityPosition < getEntityData(kEntityPlayer)->entityPosition) {
1641 				if (doPlaySound)
1642 					playCompartmentSoundEvents(object);
1643 
1644 				if (!getSoundQueue()->isBuffered(kEntityMertens))
1645 					getSound()->playSound(kEntityMertens, (rnd(2)) ? "JAC1000" : "JAC1000A");
1646 
1647 				if (doLoadScene)
1648 					getScenes()->loadSceneFromObject(object);
1649 			}
1650 
1651 			if (getEntityData(kEntityMertens)->direction == kDirectionDown
1652 			 && getEntityData(kEntityMertens)->entityPosition > getEntityData(kEntityPlayer)->entityPosition) {
1653 				if (doPlaySound)
1654 					playCompartmentSoundEvents(object);
1655 
1656 				if (!getSoundQueue()->isBuffered(kEntityMertens))
1657 					getSound()->playSound(kEntityMertens, (rnd(2)) ? "JAC1000" : "JAC1000A");
1658 
1659 				if (doLoadScene)
1660 					getScenes()->loadSceneFromObject(object, true);
1661 			}
1662 		}
1663 	}
1664 
1665 	//////////////////////////////////////////////////////////////////////////
1666 	// Coudert
1667 	if (getEntityData(kEntityPlayer)->car != kCarRedSleeping
1668 	 || !getEntityData(kEntityCoudert)->car
1669 	 || getEntityData(kEntityCoudert)->location != kLocationOutsideCompartment
1670 	 || ENTITY_PARAMS(kEntityCoudert, 0, 1))
1671 	 return false;
1672 
1673 	if (!getEntities()->compare(kEntityPlayer, kEntityCoudert)) {
1674 
1675 		if (getEntityData(kEntityCoudert)->entityPosition < kPosition_2740
1676 		 && getEntityData(kEntityCoudert)->entityPosition > kPosition_850
1677 		 && (getEntityData(kEntityMertens)->car != kCarRedSleeping || getEntityData(kEntityMertens)->entityPosition > kPosition_2740)
1678 		 && (getEntityData(kEntityVerges)->car != kCarRedSleeping || getEntityData(kEntityVerges)->entityPosition > kPosition_2740)
1679 		 && (getEntityData(kEntityMmeBoutarel)->car != kCarRedSleeping || getEntityData(kEntityMmeBoutarel)->entityPosition > kPosition_2740)) {
1680 			if (doPlaySound)
1681 				playCompartmentSoundEvents(object);
1682 
1683 			if (!getSoundQueue()->isBuffered(kEntityCoudert))
1684 				getSound()->playWarningCompartment(kEntityCoudert, object);
1685 
1686 			getSavePoints()->push(kEntityPlayer, kEntityCoudert, kAction305159806);
1687 
1688 			if (doLoadScene)
1689 				getScenes()->loadSceneFromObject(object);
1690 
1691 			return true;
1692 		}
1693 
1694 		// Direction = Up
1695 		if (getEntityData(kEntityCoudert)->direction == kDirectionUp
1696 		 && getEntityData(kEntityCoudert)->entityPosition < getEntityData(kEntityPlayer)->entityPosition) {
1697 			if (doPlaySound)
1698 				playCompartmentSoundEvents(object);
1699 
1700 			if (!getSoundQueue()->isBuffered(kEntityCoudert))
1701 				getSound()->playSound(kEntityCoudert, (rnd(2)) ? "JAC1000" : "JAC1000A");
1702 
1703 			if (doLoadScene)
1704 				getScenes()->loadSceneFromObject(object);
1705 
1706 			return true;
1707 		}
1708 
1709 		// Direction = down
1710 		if (getEntityData(kEntityCoudert)->direction == kDirectionDown
1711 		 && getEntityData(kEntityCoudert)->entityPosition > getEntityData(kEntityPlayer)->entityPosition) {
1712 			if (doPlaySound)
1713 				playCompartmentSoundEvents(object);
1714 
1715 			if (!getSoundQueue()->isBuffered(kEntityCoudert))
1716 				getSound()->playSound(kEntityCoudert, (rnd(2)) ? "JAC1000" : "JAC1000A");
1717 
1718 			if (doLoadScene)
1719 				getScenes()->loadSceneFromObject(object, true);
1720 		}
1721 	}
1722 
1723 	return false;
1724 }
1725 
1726 void Action::playCompartmentSoundEvents(ObjectIndex object) const {
1727 	if (getObjects()->get(object).status == kObjectLocation1 || getObjects()->get(object).status == kObjectLocation3 || getEntities()->checkFields2(object)) {
1728 		getSound()->playSoundEvent(kEntityPlayer, 13);
1729 	} else {
1730 		getSound()->playSoundEvent(kEntityPlayer, 14);
1731 		getSound()->playSoundEvent(kEntityPlayer, 15, 3);
1732 	}
1733 }
1734 
1735 //////////////////////////////////////////////////////////////////////////
1736 // Cursors
1737 //////////////////////////////////////////////////////////////////////////
1738 CursorStyle Action::getCursor(const SceneHotspot &hotspot) const {
1739 	// Simple cursor style
1740 	if (hotspot.cursor != kCursorProcess)
1741 		return (CursorStyle)hotspot.cursor;
1742 
1743 	ObjectIndex object = (ObjectIndex)hotspot.param1;
1744 
1745 	switch (hotspot.action) {
1746 	default:
1747 		return kCursorNormal;
1748 
1749 	case SceneHotspot::kActionInventory:
1750 		if (!getState()->sceneBackup2 && (getEvent(kEventKronosBringFirebird) || getProgress().isEggOpen))
1751 			return kCursorNormal;
1752 		else
1753 			return kCursorBackward;
1754 
1755 	case SceneHotspot::kActionKnockOnDoor:
1756 		debugC(2, kLastExpressDebugScenes, "================================= DOOR %03d =================================", object);
1757 		if (object >= kObjectMax)
1758 			return kCursorNormal;
1759 		else
1760 			return (CursorStyle)getObjects()->get(object).windowCursor;
1761 
1762 	case SceneHotspot::kAction12:
1763 		debugC(2, kLastExpressDebugScenes, "================================= OBJECT %03d =================================", object);
1764 		if (object >= kObjectMax)
1765 			return kCursorNormal;
1766 
1767 		if (getObjects()->get(object).entity)
1768 			return (CursorStyle)getObjects()->get(object).windowCursor;
1769 		else
1770 			return kCursorNormal;
1771 
1772 	case SceneHotspot::kActionPickItem:
1773 		debugC(2, kLastExpressDebugScenes, "================================= ITEM %03d =================================", object);
1774 		if (object >= kObjectCompartmentA)
1775 			return kCursorNormal;
1776 
1777 		if ((!getInventory()->getSelectedItem() || getInventory()->getSelectedEntry()->floating)
1778 		 && (object != kObject21 || getProgress().eventCorpseMovedFromFloor))
1779 			return kCursorHand;
1780 		else
1781 			return kCursorNormal;
1782 
1783 	case SceneHotspot::kActionDropItem:
1784 		debugC(2, kLastExpressDebugScenes, "================================= ITEM %03d =================================", object);
1785 		if (object >= kObjectCompartmentA)
1786 			return kCursorNormal;
1787 
1788 		if (getInventory()->getSelectedItem() != (InventoryItem)object)
1789 			return kCursorNormal;
1790 
1791 		if (object == kObject20 && hotspot.param2 == 4 && !getProgress().isTrainRunning)
1792 			return kCursorNormal;
1793 
1794 		if (object == kObjectHandleInsideBathroom  && hotspot.param2 == 1 && getProgress().field_5C)
1795 			return kCursorNormal;
1796 
1797 		return (CursorStyle)getInventory()->getSelectedEntry()->cursor;
1798 
1799 	case SceneHotspot::kAction15:
1800 		if (object >= kObjectMax)
1801 			return kCursorNormal;
1802 
1803 		if (getProgress().isEqual(object, hotspot.param2))
1804 			return (CursorStyle)hotspot.param3;
1805 
1806 		return kCursorNormal;
1807 
1808 	case SceneHotspot::kActionEnterCompartment:
1809 		if ((getInventory()->getSelectedItem() != kItemKey || getObjects()->get(kObjectCompartment1).status)
1810 		&& (getObjects()->get(kObjectCompartment1).status != 1 || !getInventory()->hasItem(kItemKey)
1811 		 ||	(getInventory()->getSelectedItem() != kItemFirebird && getInventory()->getSelectedItem() != kItemBriefcase)))
1812 			goto LABEL_KEY;
1813 
1814 		return (CursorStyle)getInventory()->get(kItemKey)->cursor; // TODO is that always the same as kCursorKey ?
1815 
1816 	case SceneHotspot::kActionGetOutsideTrain:
1817 		if (getProgress().jacket != kJacketGreen)
1818 			return kCursorNormal;
1819 
1820 		if ((getEvent(kEventCathLookOutsideWindowDay) || getEvent(kEventCathLookOutsideWindowNight) || getObjects()->get(kObjectCompartment1).model == kObjectModel1)
1821 			&& getProgress().isTrainRunning
1822 			&& (object != kObjectOutsideAnnaCompartment || (getEntities()->isInsideCompartment(kEntityRebecca, kCarRedSleeping, kPosition_4840) && getObjects()->get(kObjectOutsideBetweenCompartments).status == 2))
1823 			&& getInventory()->getSelectedItem() != kItemBriefcase && getInventory()->getSelectedItem() != kItemFirebird)
1824 			return kCursorForward;
1825 
1826 		return (getObjects()->get(kObjectCompartment1).model < kObjectModel2) ? kCursorNormal : kCursorMagnifier;
1827 
1828 	case SceneHotspot::kActionSlip:
1829 		return (getProgress().field_C8 < 1) ? kCursorNormal : kCursorLeft;
1830 
1831 	case SceneHotspot::kActionClimbUpTrain:
1832 		if (getProgress().isTrainRunning
1833 			&& (getProgress().chapter == kChapter2 || getProgress().chapter == kChapter3 || getProgress().chapter == kChapter5)
1834 			&& getInventory()->getSelectedItem() != kItemFirebird
1835 			&& getInventory()->getSelectedItem() != kItemBriefcase)
1836 			return kCursorUp;
1837 
1838 		return kCursorNormal;
1839 
1840 	case SceneHotspot::kActionJumpUpDownTrain:
1841 		if (object != kObjectCompartment1)
1842 			return kCursorNormal;
1843 
1844 		return (getObjects()->get(kObjectCeiling).status < kObjectLocation1) ? kCursorHand : kCursorNormal;
1845 
1846 	case SceneHotspot::kActionUnbound:
1847 		if (hotspot.param2 != 2)
1848 			return kCursorNormal;
1849 
1850 		if (getEvent(kEventCathBurnRope) || !getEvent(kEventCathStruggleWithBonds2))
1851 			return kCursorNormal;
1852 
1853 		return kCursorHand;
1854 
1855 	case SceneHotspot::kActionCatchBeetle:
1856 		if (!getBeetle()->isLoaded())
1857 			return kCursorNormal;
1858 
1859 		if (!getBeetle()->isCatchable())
1860 			return kCursorNormal;
1861 
1862 		if (getInventory()->getSelectedItem() == kItemMatchBox && getInventory()->hasItem(kItemMatch))
1863 			return (CursorStyle)getInventory()->get(kItemMatchBox)->cursor;
1864 
1865 		return kCursorHandPointer;
1866 
1867 	case SceneHotspot::KActionUseWhistle:
1868 		if (object != kObjectCompartment3)
1869 			return kCursorNormal;
1870 
1871 		if (getInventory()->getSelectedItem() == kItemWhistle)
1872 			return kCursorWhistle;
1873 		else
1874 			return kCursorNormal;
1875 
1876 	case SceneHotspot::kActionOpenBed:
1877 		if (getProgress().chapter < kChapter2)
1878 			return kCursorHand;
1879 
1880 		return kCursorNormal;
1881 
1882 	case SceneHotspot::kActionDialog:
1883 		if (getSound()->getDialogName((EntityIndex)object))
1884 			return kCursorHandPointer;
1885 
1886 		return kCursorNormal;
1887 
1888 	case SceneHotspot::kActionBed:
1889 		if (getProgress().field_18 == 2 && !getProgress().field_E4
1890 			&& (getState()->time > kTimeBedTime
1891 			|| (getProgress().eventMetAugust && getProgress().field_CC
1892 			&& (!getProgress().field_24 || getProgress().field_3C))))
1893 			return kCursorSleep;
1894 
1895 		return kCursorNormal;
1896 
1897 LABEL_KEY:
1898 	// Handle compartment action
1899 	case SceneHotspot::kActionCompartment:
1900 	case SceneHotspot::kActionExitCompartment:
1901 		debugC(2, kLastExpressDebugScenes, "================================= DOOR %03d =================================", object);
1902 		if (object >= kObjectMax)
1903 			return kCursorNormal;
1904 
1905 		if (getInventory()->getSelectedItem() != kItemKey
1906 		|| getObjects()->get(object).entity
1907 		|| getObjects()->get(object).status != 1
1908 		|| !getObjects()->get(object).handleCursor
1909 		|| getEntities()->isInsideCompartments(kEntityPlayer)
1910 		|| getEntities()->checkFields2(object))
1911 			return (CursorStyle)getObjects()->get(object).handleCursor;
1912 		else
1913 			return (CursorStyle)getInventory()->get(kItemKey)->cursor;
1914 	}
1915 }
1916 
1917 //////////////////////////////////////////////////////////////////////////
1918 // Animation
1919 //////////////////////////////////////////////////////////////////////////
1920 
1921 // Play an animation and add delta time to global game time
1922 void Action::playAnimation(EventIndex index, bool debugMode) const {
1923 	if (index >= _animationListSize)
1924 		error("[Action::playAnimation] Invalid event index (value=%i, max=%i)", index, _animationListSize);
1925 
1926 	// In debug mode, just show the animation
1927 	if (debugMode) {
1928 		Animation animation;
1929 		if (animation.load(getArchive(Common::String(_animationList[index].filename) + ".nis")))
1930 			animation.play();
1931 		return;
1932 	}
1933 
1934 	getFlags()->flag_3 = true;
1935 
1936 	// Hide cursor
1937 	_engine->getCursor()->show(false);
1938 
1939 	// Show inventory & hourglass
1940 	getInventory()->show();
1941 	getInventory()->showHourGlass();
1942 
1943 	if (!getFlags()->mouseRightClick) {
1944 
1945 		if (getGlobalTimer()) {
1946 			if (getSoundQueue()->isBuffered("TIMER")) {
1947 				getSoundQueue()->fade("TIMER");
1948 				setGlobalTimer(105);
1949 			}
1950 		}
1951 
1952 		bool processSound = false;
1953 		if (index >= kEventCorpseDropFloorOriginal
1954 		 || index == kEventCathWakingUp
1955 		 || index == kEventConcertCough
1956 		 || index == kEventConcertSit
1957 		 || index == kEventConcertLeaveWithBriefcase)
1958 			processSound = true;
1959 
1960 		Animation animation;
1961 		if (animation.load(getArchive(Common::String(_animationList[index].filename) + ".nis") , processSound ? Animation::kFlagDefault : Animation::kFlagProcess))
1962 			animation.play();
1963 
1964 		if (getSoundQueue()->isBuffered("TIMER"))
1965 			getSoundQueue()->stop("TIMER");
1966 	}
1967 
1968 	// Show cursor
1969 	_engine->getCursor()->show(true);
1970 
1971 	getEvent(index) = 1;
1972 
1973 	// Adjust game time
1974 	getState()->timeTicks += _animationList[index].time;
1975 	getState()->time = (TimeValue)(getState()->time + (TimeValue)(_animationList[index].time * getState()->timeDelta));
1976 }
1977 
1978 } // End of namespace LastExpress
1979