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 "ngi/ngi.h"
24
25 #include "ngi/objectnames.h"
26 #include "ngi/constants.h"
27 #include "ngi/utils.h"
28 #include "ngi/gfx.h"
29 #include "ngi/messages.h"
30 #include "ngi/motion.h"
31 #include "ngi/scenes.h"
32 #include "ngi/statics.h"
33 #include "ngi/scene.h"
34 #include "ngi/interaction.h"
35 #include "ngi/gameloader.h"
36 #include "ngi/behavior.h"
37
38 #include "audio/mixer.h"
39
40 namespace NGI {
41
42 static const int scene04_speakerPhases[] = {
43 0, 1, 2, 3, -1, -1,
44 0, 2, 3, -1, -1, -1,
45 0, 2, -1, -1, -1, -1
46 };
47
48 void sceneHandler04_putKozyawkaBack(StaticANIObject *ani);
49
scene04_speakerCallback(int * phase)50 void scene04_speakerCallback(int *phase) {
51 if (g_vars->scene04_soundPlaying) {
52 if (g_vars->scene04_speakerPhase >= 0) {
53 *phase = scene04_speakerPhases[g_vars->scene04_speakerPhase + 6 * g_vars->scene04_speakerVariant];
54
55 g_vars->scene04_speakerPhase++;
56
57 if (scene04_speakerPhases[g_vars->scene04_speakerPhase + 6 * g_vars->scene04_speakerVariant] < 0) {
58 g_vars->scene04_speakerPhase = 0;
59 g_vars->scene04_speakerVariant = g_nmi->_rnd.getRandomNumber(2);
60 }
61 } else {
62 ++g_vars->scene04_speakerPhase;
63 }
64 }
65 }
66
scene04_springCallback(int * phase)67 void scene04_springCallback(int *phase) {
68 // do nothing
69 }
70
scene04_initScene(Scene * sc)71 void scene04_initScene(Scene *sc) {
72 debugC(1, kDebugSceneLogic, "scene04_initScene()");
73
74 #if 0
75 Inventory2 *inv = getGameLoaderInventory();
76 inv->addItem(ANI_INV_COIN, 1);
77 inv->rebuildItemRects();
78 #endif
79
80 g_vars->scene04_dudeOnLadder = false;
81 g_vars->scene04_bottle = sc->getPictureObjectById(PIC_SC4_BOTTLE, 0);
82 g_vars->scene04_hand = sc->getStaticANIObject1ById(ANI_HAND, -1);
83 g_vars->scene04_plank = sc->getStaticANIObject1ById(ANI_PLANK, -1);
84 g_vars->scene04_clock = sc->getStaticANIObject1ById(ANI_CLOCK, -1);
85 g_vars->scene04_spring = sc->getStaticANIObject1ById(ANI_SPRING, -1);
86 g_vars->scene04_mamasha = sc->getStaticANIObject1ById(ANI_MAMASHA_4, -1);
87 g_vars->scene04_boot = sc->getStaticANIObject1ById(ANI_SC4_BOOT, -1);
88 g_vars->scene04_ladder = 0;
89
90 StaticANIObject *koz = sc->getStaticANIObject1ById(ANI_KOZAWKA, -1);
91
92 if (koz) {
93 Movement *kozmov = koz->getMovementById(MV_KZW_JUMP);
94 if (kozmov) {
95 uint kozsize = kozmov->_currMovement ? kozmov->_currMovement->_dynamicPhases.size() : kozmov->_dynamicPhases.size();
96
97 for (uint i = 0; i < kozsize; i++) {
98 kozmov->setDynamicPhaseIndex(i);
99
100 if (kozmov->_framePosOffsets.size()) {
101 g_vars->scene04_jumpingKozyawki[i] = kozmov->_framePosOffsets[kozmov->_currDynamicPhaseIndex];
102 } else {
103 kozmov->_somePoint.x = 0;
104 kozmov->_somePoint.y = 0;
105 g_vars->scene04_jumpingKozyawki[i] = kozmov->_somePoint;
106 }
107 }
108 }
109
110 kozmov = koz->getMovementById(MV_KZW_JUMPROTATE);
111 if (kozmov) {
112 uint kozsize = kozmov->_currMovement ? kozmov->_currMovement->_dynamicPhases.size() : kozmov->_dynamicPhases.size();
113
114 for (uint i = 0; i < kozsize; i++) {
115 kozmov->setDynamicPhaseIndex(i);
116
117 if (kozmov->_framePosOffsets.size()) {
118 g_vars->scene04_jumpRotateKozyawki[i] = kozmov->_framePosOffsets[kozmov->_currDynamicPhaseIndex];
119 } else {
120 kozmov->_somePoint.x = 0;
121 kozmov->_somePoint.y = 0;
122 g_vars->scene04_jumpRotateKozyawki[i] = kozmov->_somePoint;
123 }
124 }
125 }
126 }
127
128 Interaction *plank = getGameLoaderInteractionController()->getInteractionByObjectIds(ANI_PLANK, 0, 0);
129 if (plank)
130 plank->_flags |= 8;
131
132 if (g_nmi->getObjectState(sO_Jar_4) == g_nmi->getObjectEnumState(sO_Jar_4, sO_UpsideDown)) {
133 debugC(2, kDebugSceneLogic, "scene04: Jar is upside down");
134
135 g_vars->scene04_bottleObjList.clear();
136 g_vars->scene04_kozyawkiObjList.clear();
137
138 sc->getPictureObjectById(PIC_SC4_BOTTLE, 0)->_flags &= 0xfffb;
139 sc->getPictureObjectById(PIC_SC4_MASK, 0)->_flags &= 0xfffb;
140 sc->getStaticANIObject1ById(ANI_SPRING, 0)->_flags &= 0xfffb;
141
142 g_vars->scene04_clockCanGo = false;
143 g_vars->scene04_objectIsTaken = false;
144 } else {
145 debugC(2, kDebugSceneLogic, "scene04: Jar is NOT upside down");
146
147 StaticANIObject *spring = sc->getStaticANIObject1ById(ANI_SPRING, -1);
148
149 if (spring)
150 spring->_callback2 = scene04_springCallback;
151
152 g_vars->scene04_bottleObjList.clear();
153 g_vars->scene04_bottleObjList.push_back(sc->getPictureObjectById(PIC_SC4_BOTTLE, 0));
154 g_vars->scene04_bottleObjList.push_back(sc->getPictureObjectById(PIC_SC4_MASK, 0));
155
156 g_vars->scene04_kozyawkiObjList.clear();
157
158 if (koz) {
159 debugC(2, kDebugSceneLogic, "scene04: We're in koz");
160
161 koz->loadMovementsPixelData();
162
163 koz->_statics = koz->getStaticsById(ST_KZW_EMPTY);
164 koz->setOXY(0, 0);
165 koz->hide();
166
167 g_vars->scene04_kozyawkiObjList.push_back(koz);
168
169 for (int i = 0; i < 6; i++) {
170 StaticANIObject *koz1 = new StaticANIObject(koz);
171
172 sc->addStaticANIObject(koz1, 1);
173 koz1->_statics = koz->getStaticsById(ST_KZW_EMPTY);
174 koz1->setOXY(0, 0);
175 koz1->hide();
176 g_vars->scene04_kozyawkiObjList.push_back(koz1);
177 }
178 }
179 sc->getPictureObjectById(PIC_SC4_BOTTLE2, 0)->_flags &= 0xfffb;
180
181 g_vars->scene04_clockCanGo = true;
182 g_vars->scene04_objectIsTaken = true;
183
184 debugC(2, kDebugSceneLogic, "scene04: kozObjList size: %d", g_vars->scene04_kozyawkiObjList.size());
185 }
186
187 g_vars->scene04_bottleIsTaken = false;
188 g_vars->scene04_soundPlaying = false;
189 g_vars->scene04_kozyawkaOnLadder = false;
190 g_vars->scene04_walkingKozyawka = 0;
191 g_vars->scene04_bottleWeight = 2;
192 g_vars->scene04_dynamicPhaseIndex = 0;
193
194 g_vars->scene04_kozyawkiAni.clear();
195
196 g_nmi->setObjectState(sO_LowerPipe, g_nmi->getObjectEnumState(sO_LowerPipe, sO_IsClosed));
197
198 g_vars->scene04_var07 = false;
199 g_vars->scene04_ladderClickable = false;
200 g_vars->scene04_coinPut = false;
201 g_vars->scene04_handIsDown = false;
202 g_vars->scene04_dudeInBottle = false;
203 g_vars->scene04_kozHeadRaised = false;
204 g_vars->scene04_bottleIsDropped = false;
205 g_vars->scene04_bigBallIn = true;
206 g_vars->scene04_bigBallCounter = 0;
207 g_vars->scene04_bigBallFromLeft = true;
208
209 if (g_nmi->getObjectState(sO_BigMumsy) != g_nmi->getObjectEnumState(sO_BigMumsy, sO_IsGone))
210 g_vars->scene04_mamasha->hide();
211
212 g_vars->scene04_speaker = sc->getStaticANIObject1ById(ANI_SPEAKER_4, -1);
213 g_vars->scene04_speaker->_callback2 = scene04_speakerCallback;
214 g_vars->scene04_speaker->startAnim(MV_SPK4_PLAY, 0, -1);
215
216 g_vars->scene04_speakerVariant = 0;
217 g_vars->scene04_speakerPhase = 0;
218
219 g_vars->scene04_musicStage = 0;
220
221 g_nmi->initArcadeKeys("SC_4");
222 }
223
sceneHandler04_friesAreWalking()224 bool sceneHandler04_friesAreWalking() {
225 if (g_vars->scene04_dudeOnLadder && g_nmi->_aniMan->isIdle() && !(g_nmi->_aniMan->_flags & 0x100)) {
226 int col = g_vars->scene04_ladder->collisionDetection(g_nmi->_aniMan);
227 if (col >= 3 && col <= 6 ) {
228 Movement *koz;
229
230 if (!g_vars->scene04_walkingKozyawka
231 || (koz = g_vars->scene04_walkingKozyawka->_movement) == 0
232 || koz->_id != MV_KZW_WALKPLANK
233 || koz->_currDynamicPhaseIndex < 10
234 || koz->_currDynamicPhaseIndex > 41)
235 return true;
236 }
237 }
238
239 return false;
240 }
241
scene04_updateCursor()242 int scene04_updateCursor() {
243 g_nmi->updateCursorCommon();
244
245 if (g_nmi->_objectIdAtCursor == PIC_SC4_LRTRUBA) {
246 if (!g_vars->scene04_objectIsTaken) {
247 g_nmi->_cursorId = PIC_CSR_DEFAULT;
248
249 return g_nmi->_cursorId;
250 }
251 } else if (g_nmi->_objectIdAtCursor == ANI_PLANK || g_nmi->_objectIdAtCursor == PIC_SC4_PLANK) {
252 if (g_nmi->_objectIdAtCursor == ANI_PLANK && g_nmi->_cursorId != PIC_CSR_ITN)
253 return g_nmi->_cursorId;
254
255 if (g_nmi->_objectIdAtCursor == ANI_PLANK || (g_nmi->_objectIdAtCursor == PIC_SC4_PLANK && g_nmi->_cursorId == PIC_CSR_DEFAULT)) {
256 if (sceneHandler04_friesAreWalking()) {
257 g_nmi->_cursorId = PIC_CSR_ARCADE1;
258 return g_nmi->_cursorId;
259 }
260 if (g_vars->scene04_soundPlaying) {
261 g_nmi->_cursorId = PIC_CSR_DEFAULT;
262 return g_nmi->_cursorId;
263 }
264 }
265 }
266
267 if (g_nmi->_cursorId == PIC_CSR_ITN && g_nmi->_objectIdAtCursor == PIC_SC4_DOWNTRUBA)
268 g_nmi->_cursorId = PIC_CSR_GOD;
269
270 return g_nmi->_cursorId;
271 }
272
sceneHandler04_checkBigBallClick()273 void sceneHandler04_checkBigBallClick() {
274 StaticANIObject *ball = g_nmi->_currentScene->getStaticANIObject1ById(ANI_BIGBALL, -1);
275
276 if (ball)
277 for (uint i = 0; i < ball->_movements.size(); i++)
278 ball->_movements[i]->_counterMax = 73;
279
280 g_vars->scene04_bigBallIn = true;
281 }
282
sceneHandler04_clickBottle()283 void sceneHandler04_clickBottle() {
284 if (!g_vars->scene04_bottleIsTaken)
285 g_vars->scene04_springOffset += 5;
286 }
287
sceneHandler04_clickButton()288 void sceneHandler04_clickButton() {
289 StaticANIObject *but = g_nmi->_currentScene->getStaticANIObject1ById(ANI_BUTTON, -1);
290
291 if (but) {
292 if (!g_vars->scene04_clock->_movement ||
293 (g_vars->scene04_clock->_movement->_id == MV_CLK_GO && g_vars->scene04_clock->_movement->_currDynamicPhaseIndex > 3 &&
294 g_vars->scene04_clock->_movement->_currDynamicPhaseIndex < 105)) {
295 if (!g_vars->scene04_hand->_movement && !g_vars->scene04_bottleIsTaken) {
296 but->startAnim(MV_BTN_CLICK, 0, -1);
297 g_vars->scene04_hand->startAnim(MV_HND_POINT, 0, -1);
298 }
299 }
300 }
301 }
302
sceneHandler04_downLadder(int x,int y)303 void sceneHandler04_downLadder(int x, int y) {
304 g_vars->scene04_ladder->startMove(g_nmi->_aniMan, x + g_vars->scene04_ladder->_ladder_field_20, y + g_vars->scene04_ladder->_ladder_field_24, 0, 0);
305 }
306
sceneHandler04_walkClimbLadder(ExCommand * ex)307 void sceneHandler04_walkClimbLadder(ExCommand *ex) {
308 MessageQueue *mq = new MessageQueue(g_nmi->_globalMessageQueueList->compact());
309
310 ExCommand *ex1 = new ExCommand(ANI_MAN, 1, MV_MAN_TOLADDER, 0, 0, 0, 1, 0, 0, 0);
311
312 ex1->_param = g_nmi->_aniMan->_odelay;
313 ex1->_excFlags |= 2;
314
315 mq->addExCommandToEnd(ex1);
316
317 ExCommand *ex2 = new ExCommand(ANI_MAN, 1, MV_MAN_STOPLADDER, 0, 0, 0, 1, 0, 0, 0);
318
319 ex2->_param = g_nmi->_aniMan->_odelay;
320 ex2->_excFlags |= 2;
321
322 mq->addExCommandToEnd(ex2);
323
324 ExCommand *ex3;
325
326 if (ex) {
327 ex3 = ex->createClone();
328 } else {
329 ex3 = new ExCommand(0, 17, MSG_SC4_CLICKLADDER, 0, 0, 0, 1, 0, 0, 0);
330 ex3->_excFlags |= 3;
331 }
332
333 mq->addExCommandToEnd(ex3);
334
335 mq->setFlags(mq->getFlags() | 1);
336
337 mq->chain(0);
338
339 g_vars->scene04_dudeOnLadder = 1;
340
341 g_vars->scene04_ladder = new MctlLadder;
342 g_vars->scene04_ladder->_ladderX = 1089;
343 g_vars->scene04_ladder->_ladderY = 406;
344 g_vars->scene04_ladder->_ladder_field_14 = 12;
345 g_vars->scene04_ladder->_width = 0;
346 g_vars->scene04_ladder->_height = -40;
347 g_vars->scene04_ladder->_ladder_field_20 = 0;
348 g_vars->scene04_ladder->_ladder_field_24 = -60;
349
350 g_vars->scene04_ladder->attachObject(g_nmi->_aniMan);
351
352 if (g_vars->scene04_soundPlaying) {
353 g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStart = MV_MAN_STARTLADDER2;
354 g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpGo = MV_MAN_GOLADDER2;
355 g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStop = MV_MAN_STOPLADDER2;
356 g_vars->scene04_ladder->_ladmovements.front()->staticIds[2] = ST_MAN_GOLADDER2;
357 } else {
358 g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStart = MV_MAN_STARTLADDER;
359 g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpGo = MV_MAN_GOLADDER;
360 g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStop = MV_MAN_STOPLADDER;
361 g_vars->scene04_ladder->_ladmovements.front()->staticIds[2] = ST_MAN_GOLADDER;
362 }
363
364 g_nmi->_aniMan->_priority = 12;
365
366 getSc2MctlCompoundBySceneId(g_nmi->_currentScene->_sceneId)->deactivate();
367 getGameLoaderInteractionController()->disableFlag24();
368 }
369
sceneHandler04_clickLadder()370 void sceneHandler04_clickLadder() {
371 g_vars->scene04_dudePosX = g_nmi->_aniMan->_ox;
372 g_vars->scene04_dudePosY = g_nmi->_aniMan->_oy;
373
374 if (g_vars->scene04_dudeOnLadder) {
375 if (!g_nmi->_aniMan->isIdle() || (g_nmi->_aniMan->_flags & 0x100)) {
376 g_vars->scene04_ladderClickable = true;
377 } else {
378 int h3 = 3 * g_vars->scene04_ladder->_height;
379 int half = abs(g_vars->scene04_ladder->_height) / 2;
380 int start = g_vars->scene04_ladder->_ladderY - g_vars->scene04_ladder->_ladder_field_24;
381 int min = 2 * h3 + start + half + 1;
382 int max = h3 + start - half - 1;
383
384 if (g_vars->scene04_sceneClickY > max)
385 g_vars->scene04_sceneClickY = max;
386
387 if (g_vars->scene04_sceneClickY < min)
388 g_vars->scene04_sceneClickY = min;
389
390 sceneHandler04_downLadder(g_vars->scene04_sceneClickX, g_vars->scene04_sceneClickY);
391
392 g_vars->scene04_ladderClickable = false;
393 }
394 } else {
395 if (g_nmi->_aniMan->isIdle() && !(g_nmi->_aniMan->_flags & 0x100)) {
396 if (abs(1095 - g_vars->scene04_dudePosX) > 1 || abs(434 - g_vars->scene04_dudePosY) > 1) {
397 MessageQueue *mq = getSc2MctlCompoundBySceneId(g_nmi->_currentScene->_sceneId)->startMove(g_nmi->_aniMan, 1095, 434, 1, ST_MAN_UP);
398 if (mq) {
399 ExCommand *ex = new ExCommand(0, 17, MSG_SC4_CLICKLADDER, 0, 0, 0, 1, 0, 0, 0);
400
401 ex->_excFlags = 3;
402 mq->addExCommandToEnd(ex);
403
404 postExCommand(g_nmi->_aniMan->_id, 2, 1095, 434, 0, -1);
405 }
406 } else {
407 sceneHandler04_walkClimbLadder(0);
408 }
409 }
410 }
411 }
412
sceneHandler04_jumpOnLadder()413 void sceneHandler04_jumpOnLadder() {
414 if (g_nmi->_aniMan->_movement && g_nmi->_aniMan->_movement->_id != MV_MAN_LOOKLADDER)
415 return;
416
417 if (g_nmi->_aniMan->_statics->_staticsId != ST_MAN_STANDLADDER && g_nmi->_aniMan->_statics->_staticsId != ST_MAN_LADDERDOWN)
418 return;
419
420 g_nmi->_aniMan->changeStatics2(ST_MAN_LADDERDOWN);
421
422 g_nmi->_aniMan->_flags |= 0x100;
423
424 AniHandler aniHandler;
425 MakeQueueStruct mkQueue;
426
427 aniHandler.attachObject(ANI_MAN);
428
429 mkQueue.ani = g_nmi->_aniMan;
430 mkQueue.staticsId2 = ST_MAN_ONPLANK;
431 mkQueue.x1 = 938;
432 mkQueue.y1 = 442;
433 mkQueue.field_1C = 10;
434 mkQueue.field_10 = 1;
435 mkQueue.flags = 78;
436 mkQueue.movementId = MV_MAN_JUMPONPLANK;
437
438 MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue);
439
440 if (mq) {
441 mq->_flags |= 1;
442
443 if (!mq->chain(g_nmi->_aniMan))
444 delete mq;
445
446 g_nmi->_aniMan->_priority = 10;
447 }
448
449 g_vars->scene04_ladderOffset = g_vars->scene04_ladder->collisionDetection(g_nmi->_aniMan);
450 }
451
sceneHandler04_clickPlank()452 void sceneHandler04_clickPlank() {
453 if (sceneHandler04_friesAreWalking())
454 sceneHandler04_jumpOnLadder();
455 else if (g_vars->scene04_dudeOnLadder)
456 g_nmi->playSound(SND_4_033, 0);
457 else if (!g_vars->scene04_soundPlaying)
458 chainQueue(QU_PNK_CLICK, 0);
459 }
460
sceneHandler04_dropBottle()461 void sceneHandler04_dropBottle() {
462 g_vars->scene04_bottleIsDropped = true;
463 g_vars->scene04_bottleY = 10;
464 g_vars->scene04_bottleWeight = 0;
465
466 while (g_vars->scene04_kozyawkiAni.size()) {
467 StaticANIObject *koz = g_vars->scene04_kozyawkiAni.front();
468 g_vars->scene04_kozyawkiAni.pop_front();
469
470 for (Common::List<GameObject *>::iterator it = g_vars->scene04_bottleObjList.begin(); it != g_vars->scene04_bottleObjList.end(); ++it)
471 if (*it == koz) {
472 g_vars->scene04_bottleObjList.erase(it);
473 break;
474 }
475
476 koz->queueMessageQueue(0);
477 koz->hide();
478
479 g_vars->scene04_kozyawkiObjList.push_back(koz);
480 }
481
482 g_vars->scene04_hand->changeStatics2(ST_HND_EMPTY);
483
484 g_vars->scene04_hand->setOXY(429, 21);
485 g_vars->scene04_hand->_priority = 15;
486 }
487
sceneHandler04_gotoLadder(ExCommand * ex)488 void sceneHandler04_gotoLadder(ExCommand *ex) {
489 AniHandler aniHandler;
490 MakeQueueStruct mkQueue;
491
492 aniHandler.attachObject(ANI_MAN);
493
494 mkQueue.ani = g_nmi->_aniMan;
495 mkQueue.staticsId2 = ST_MAN_UP;
496 mkQueue.x1 = 1095;
497 mkQueue.y1 = 434;
498 mkQueue.field_1C = 12;
499 mkQueue.field_10 = 1;
500 mkQueue.flags = 78;
501 mkQueue.movementId = MV_MAN_PLANKTOLADDER;
502
503 MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue);
504
505 if (mq) {
506 mq->deleteExCommandByIndex(mq->getCount() - 1, 1);
507
508 ExCommand *ex1 = new ExCommand(ANI_MAN, 1, MV_MAN_TOLADDER, 0, 0, 0, 1, 0, 0, 0);
509 ex1->_excFlags = 2;
510 ex1->_field_24 = 1;
511 ex1->_param = -1;
512 mq->addExCommandToEnd(ex1);
513
514 ExCommand *ex2 = new ExCommand(ANI_MAN, 1, MV_MAN_STOPLADDER, 0, 0, 0, 1, 0, 0, 0);
515 ex2->_excFlags = 2;
516 ex2->_field_24 = 1;
517 ex2->_param = -1;
518 mq->addExCommandToEnd(ex2);
519
520 ExCommand *ex3 = new ExCommand(g_nmi->_aniMan->_id, 34, 256, 0, 0, 0, 1, 0, 0, 0);
521 ex3->_z = 256;
522 ex3->_messageNum = 0;
523 ex3->_excFlags |= 3;
524 mq->addExCommandToEnd(ex3);
525
526 if (ex) {
527 ExCommand *ex4 = ex->createClone();
528
529 mq->addExCommandToEnd(ex4);
530 }
531
532 mq->setFlags(mq->getFlags() | 1);
533
534 if (mq->chain(g_nmi->_aniMan)) {
535 g_nmi->_aniMan->_priority = 12;
536 g_nmi->_aniMan->_flags |= 0x100;
537 } else {
538 delete mq;
539 }
540 }
541
542 g_vars->scene04_kozyawkaOnLadder = false;
543 }
544
sceneHandler04_lowerPlank()545 void sceneHandler04_lowerPlank() {
546 g_vars->scene04_plank->startAnim(MV_PNK_WEIGHTRIGHT, 0, -1);
547 }
548
sceneHandler04_manFromBottle()549 void sceneHandler04_manFromBottle() {
550 for (Common::List<GameObject *>::iterator it = g_vars->scene04_bottleObjList.begin(); it != g_vars->scene04_bottleObjList.end(); ++it)
551 if (*it == g_nmi->_aniMan) {
552 g_vars->scene04_bottleObjList.erase(it);
553 g_vars->scene04_bottleWeight -= 9;
554 break;
555 }
556
557 if (g_vars->scene04_ladder)
558 delete g_vars->scene04_ladder;
559
560 g_vars->scene04_ladder = 0;
561
562 getSc2MctlCompoundBySceneId(g_nmi->_currentScene->_sceneId)->activate();
563 getGameLoaderInteractionController()->enableFlag24();
564 }
565
sceneHandler04_manToBottle()566 void sceneHandler04_manToBottle() {
567 g_vars->scene04_bottleObjList.push_back(g_nmi->_aniMan);
568 g_vars->scene04_springOffset = 5;
569 g_vars->scene04_bottleWeight += 9;
570 g_nmi->_aniMan2 = g_nmi->_aniMan;
571 g_vars->scene04_dudeInBottle = 1;
572 }
573
sceneHandler04_raisePlank()574 void sceneHandler04_raisePlank() {
575 g_vars->scene04_plank->startAnim(MV_PNK_WEIGHTLEFT, 0, -1);
576 }
577
sceneHandler04_kozFly3(StaticANIObject * ani,double phase)578 MessageQueue *sceneHandler04_kozFly3(StaticANIObject *ani, double phase) {
579 AniHandler aniHandler;
580 MakeQueueStruct mkQueue;
581
582 debugC(2, kDebugSceneLogic, "scene04: kozFly3 (OK)");
583
584 aniHandler.attachObject(ANI_KOZAWKA);
585
586 mkQueue.ani = ani;
587 mkQueue.staticsId2 = ST_KZW_SIT;
588 mkQueue.x1 = (int)(723.0 - phase * 185.0);
589 mkQueue.y1 = 486;
590 mkQueue.field_1C = 10;
591 mkQueue.field_10 = 1;
592 mkQueue.flags = 78;
593 mkQueue.movementId = MV_KZW_JUMP;
594
595 MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue);
596
597 if (mq) {
598 ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0);
599 ex->_excFlags |= 2;
600 ex->_param = ani->_odelay;
601 mq->addExCommandToEnd(ex);
602
603 ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_TURN, 0, 0, 0, 1, 0, 0, 0);
604 ex->_excFlags |= 2;
605 ex->_param = ani->_odelay;
606 mq->addExCommandToEnd(ex);
607
608 for (int i = 0; i < 5; i++) {
609 ex = new ExCommand(ANI_KOZAWKA, 1, rMV_KZW_GOR, 0, 0, 0, 1, 0, 0, 0);
610 ex->_excFlags |= 2;
611 ex->_param = ani->_odelay;
612 mq->addExCommandToEnd(ex);
613 }
614
615 ex = new ExCommand(ANI_KOZAWKA, 6, 0, 0, 0, 0, 1, 0, 0, 0);
616 ex->_excFlags |= 3;
617 ex->_param = ani->_odelay;
618 mq->addExCommandToEnd(ex);
619
620 ex = new ExCommand(ANI_KOZAWKA, 17, MSG_KOZAWRESTART, 0, 0, 0, 1, 0, 0, 0);
621 ex->_excFlags |= 3;
622 ex->_param = ani->_odelay;
623 mq->addExCommandToEnd(ex);
624 }
625
626 return mq;
627 }
628
sceneHandler04_kozFly5(StaticANIObject * ani,double phase)629 MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) {
630 AniHandler aniHandler;
631 MakeQueueStruct mkQueue;
632
633 debugC(2, kDebugSceneLogic, "scene04: kozFly5 (OK)");
634
635 aniHandler.attachObject(ANI_KOZAWKA);
636
637 mkQueue.ani = ani;
638 mkQueue.staticsId2 = ST_KZW_JUMPOUT;
639 mkQueue.x1 = 525;
640 mkQueue.y1 = (int)(344.0 - (double)(320 - g_vars->scene04_bottle->_oy) * phase);
641 mkQueue.field_1C = 10;
642 mkQueue.field_10 = 1;
643 mkQueue.flags = 78;
644 mkQueue.movementId = MV_KZW_JUMPHIT;
645
646 MessageQueue *mq1 = aniHandler.makeRunQueue(&mkQueue);
647
648 mkQueue.reset();
649 mkQueue.ani = ani;
650 mkQueue.staticsId1 = ST_KZW_JUMPOUT;
651 mkQueue.staticsId2 = ST_KZW_SIT;
652 mkQueue.x2 = 525;
653 mkQueue.y2 = (int)(344.0 - (double)(320 - g_vars->scene04_bottle->_oy) * phase);
654 mkQueue.y1 = 486;
655 mkQueue.field_1C = 10;
656 mkQueue.field_10 = 1;
657 mkQueue.flags = 117;
658 mkQueue.movementId = MV_KZW_JUMPOUT;
659
660 MessageQueue *mq2 = aniHandler.makeRunQueue(&mkQueue);
661
662 if (mq1 && mq2) {
663 mq1->addExCommandToEnd(mq2->getExCommandByIndex(0)->createClone());
664
665 delete mq2;
666 mq2 = 0;
667
668 ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0);
669 ex->_excFlags |= 2;
670 ex->_param = ani->_odelay;
671 mq1->addExCommandToEnd(ex);
672
673 ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_TURN, 0, 0, 0, 1, 0, 0, 0);
674 ex->_excFlags |= 2;
675 ex->_param = ani->_odelay;
676 mq1->addExCommandToEnd(ex);
677
678 for (int i = 0; i < 5; i++) {
679 ex = new ExCommand(ANI_KOZAWKA, 1, rMV_KZW_GOR, 0, 0, 0, 1, 0, 0, 0);
680 ex->_excFlags |= 2;
681 ex->_param = ani->_odelay;
682 mq1->addExCommandToEnd(ex);
683 }
684
685 ex = new ExCommand(ANI_KOZAWKA, 6, 0, 0, 0, 0, 1, 0, 0, 0);
686 ex->_excFlags |= 3;
687 ex->_param = ani->_odelay;
688 mq1->addExCommandToEnd(ex);
689
690 ex = new ExCommand(ANI_KOZAWKA, 17, MSG_KOZAWRESTART, 0, 0, 0, 1, 0, 0, 0);
691 ex->_excFlags |= 3;
692 ex->_param = ani->_odelay;
693 mq1->addExCommandToEnd(ex);
694 }
695
696 if (mq2)
697 delete mq2;
698
699 return mq1;
700 }
701
sceneHandler04_kozFly6(StaticANIObject * ani)702 MessageQueue *sceneHandler04_kozFly6(StaticANIObject *ani) {
703 AniHandler aniHandler;
704 MakeQueueStruct mkQueue;
705
706 debugC(2, kDebugSceneLogic, "scene04: kozFly6 (OK)");
707
708 aniHandler.attachObject(ANI_KOZAWKA);
709
710 mkQueue.ani = ani;
711 mkQueue.staticsId2 = ST_KZW_SIT;
712 mkQueue.x1 = 397 - 4 * g_nmi->_rnd.getRandomNumber(1);
713 mkQueue.field_1C = ani->_priority;
714 mkQueue.y1 = g_vars->scene04_bottle->_oy - 4 * g_nmi->_rnd.getRandomNumber(1) + 109;
715 mkQueue.field_10 = 1;
716 mkQueue.flags = 78;
717 mkQueue.movementId = MV_KZW_JUMPROTATE;
718
719 MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue);
720
721 if (mq) {
722 mq->deleteExCommandByIndex(mq->getCount() - 1, 1);
723
724 ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0);
725 ex->_excFlags |= 2;
726 ex->_param = ani->_odelay;
727 mq->addExCommandToEnd(ex);
728
729 ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_GOR, 0, 0, 0, 1, 0, 0, 0);
730 ex->_excFlags |= 2;
731 ex->_param = ani->_odelay;
732 mq->addExCommandToEnd(ex);
733
734 ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_RAISEHEAD, 0, 0, 0, 1, 0, 0, 0);
735 ex->_excFlags |= 2;
736 ex->_param = ani->_odelay;
737 mq->addExCommandToEnd(ex);
738
739 g_vars->scene04_kozHeadRaised = true;
740 }
741
742 return mq;
743 }
744
sceneHandler04_kozMove(Movement * mov,int from,int to,Common::Point * points,double phase)745 void sceneHandler04_kozMove(Movement *mov, int from, int to, Common::Point *points, double phase) {
746 for (int i = from; i < to; i++) {
747 mov->setDynamicPhaseIndex(i);
748
749 Common::Point *p;
750 if (mov->_framePosOffsets.size()) {
751 p = &mov->_framePosOffsets[mov->_currDynamicPhaseIndex];
752 } else {
753 p = &mov->_somePoint;
754 p->x = 0;
755 p->y = 0;
756 }
757
758 p->y = (int)((double)points[i].y * phase);
759 }
760 }
761
sceneHandler04_kozFly7(StaticANIObject * ani,double phase)762 MessageQueue *sceneHandler04_kozFly7(StaticANIObject *ani, double phase) {
763 AniHandler aniHandler;
764 MakeQueueStruct mkQueue;
765
766 debugC(2, kDebugSceneLogic, "scene04: kozFly7");
767
768 aniHandler.attachObject(ANI_KOZAWKA);
769
770 mkQueue.ani = ani;
771 mkQueue.staticsId2 = 560;
772 mkQueue.x1 = (int)(250.0 - phase * 100.0);
773 mkQueue.y1 = 455;
774 mkQueue.field_1C = 10;
775 mkQueue.field_10 = 1;
776 mkQueue.flags = 78;
777 mkQueue.movementId = MV_KZW_JUMPROTATE;
778
779 MessageQueue *mq = aniHandler.makeRunQueue(&mkQueue);
780
781 if (mq) {
782 sceneHandler04_kozMove(ani->getMovementById(MV_KZW_JUMPROTATE), 1, 9, g_vars->scene04_jumpRotateKozyawki, phase * 0.5 + 1.5);
783
784 ani->_priority = 10;
785
786 ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0);
787 ex->_excFlags |= 2;
788 ex->_param = ani->_odelay;
789 mq->addExCommandToEnd(ex);
790
791 ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_TURN, 0, 0, 0, 1, 0, 0, 0);
792 ex->_excFlags |= 2;
793 ex->_param = ani->_odelay;
794 mq->addExCommandToEnd(ex);
795
796 for (int i = 0; i < 2; i++) {
797 ex = new ExCommand(ANI_KOZAWKA, 1, rMV_KZW_GOR, 0, 0, 0, 1, 0, 0, 0);
798 ex->_excFlags |= 2;
799 ex->_param = ani->_odelay;
800 mq->addExCommandToEnd(ex);
801 }
802
803 ex = new ExCommand(ANI_KOZAWKA, 6, 0, 0, 0, 0, 1, 0, 0, 0);
804 ex->_excFlags |= 3;
805 ex->_param = ani->_odelay;
806 mq->addExCommandToEnd(ex);
807
808 ex = new ExCommand(ANI_KOZAWKA, 17, MSG_KOZAWRESTART, 0, 0, 0, 1, 0, 0, 0);
809 ex->_excFlags |= 3;
810 ex->_param = ani->_odelay;
811 mq->addExCommandToEnd(ex);
812 }
813
814 return mq;
815 }
816
817 static const int kozTrajectory3[] = {
818 3, 2, 0,
819 3, 2, 0,
820 3, 2, 0
821 };
822
823 static const int kozTrajectory4[] = {
824 5, 3, 1,
825 5, 4, 1,
826 5, 3, 1
827 };
828
829 static const int kozTrajectory5[] = {
830 6, 5, 4,
831 6, 5, 4,
832 6, 5, 4
833 };
834
835 static const int kozTrajectory6[] = {
836 7, 6, 5,
837 7, 6, 5,
838 7, 6, 5
839 };
840
sceneHandler04_shootKozyawka()841 void sceneHandler04_shootKozyawka() {
842 g_vars->scene04_plank->changeStatics2(ST_PNK_WEIGHTRIGHT);
843
844 if (!g_vars->scene04_walkingKozyawka)
845 return;
846
847 if (g_vars->scene04_walkingKozyawka->_movement) {
848 if (g_vars->scene04_walkingKozyawka->_movement->_id == MV_KZW_WALKPLANK) {
849 int dphase = g_vars->scene04_walkingKozyawka->_movement->_currDynamicPhaseIndex;
850
851 if (dphase < 41) {
852 int col = 3 * dphase / 15;
853 if (col > 2)
854 col = 2;
855
856 int row = g_vars->scene04_kozyawkiAni.size();
857 if (row > 2)
858 row = 2;
859
860 int idx = 3 * row + col;
861 int phase;
862
863 if (g_vars->scene04_ladderOffset == 3) {
864 phase = kozTrajectory3[idx];
865 } else if (g_vars->scene04_ladderOffset == 4) {
866 phase = kozTrajectory4[idx];
867 } else {
868 if (g_vars->scene04_ladderOffset == 5)
869 phase = kozTrajectory5[idx];
870 else
871 phase = kozTrajectory6[idx];
872 }
873
874 g_vars->scene04_walkingKozyawka->queueMessageQueue(0);
875 g_vars->scene04_walkingKozyawka->_movement = 0;
876 g_vars->scene04_walkingKozyawka->_statics = g_vars->scene04_walkingKozyawka->getStaticsById(ST_KZW_RIGHT);
877
878 MessageQueue *mq;
879
880 if (phase > 2) {
881 if (phase > 5) {
882 if (phase == 6)
883 mq = sceneHandler04_kozFly6(g_vars->scene04_walkingKozyawka);
884 else
885 mq = sceneHandler04_kozFly7(g_vars->scene04_walkingKozyawka, (double)(phase - 6) * 0.3333333333333333);
886 } else {
887 mq = sceneHandler04_kozFly5(g_vars->scene04_walkingKozyawka, (double)(phase - 2) * 0.3333333333333333);
888 }
889 } else {
890 mq = sceneHandler04_kozFly3(g_vars->scene04_walkingKozyawka, (double)phase * 0.5);
891 }
892
893 if (mq) {
894 g_vars->scene04_lastKozyawka = g_vars->scene04_walkingKozyawka;
895
896 if (!mq->chain(g_vars->scene04_walkingKozyawka) )
897 delete mq;
898 }
899 }
900 }
901 }
902
903 if (g_vars->scene04_ladderOffset > 3)
904 g_nmi->_aniMan->changeStatics1(ST_MAN_LOOKPLANK);
905
906 g_vars->scene04_kozyawkaOnLadder = true;
907 }
908
sceneHandler04_showCoin()909 void sceneHandler04_showCoin() {
910 StaticANIObject *ani = g_nmi->_currentScene->getStaticANIObject1ById(ANI_SC4_COIN, -1);
911
912 if (ani) {
913 ani->show1(MV_BDG_OPEN, MV_MAN_GOU, MV_SC4_COIN_default, 0);
914
915 ani->_priority = 40;
916 }
917 }
918
sceneHandler04_stopSound()919 void sceneHandler04_stopSound() {
920 g_vars->scene04_soundPlaying = false;
921
922 g_nmi->stopSoundStream2();
923 }
924
sceneHandler04_animOutOfBottle(ExCommand * ex)925 void sceneHandler04_animOutOfBottle(ExCommand *ex) {
926 g_nmi->_aniMan->changeStatics2(ST_MAN_SIT);
927
928 MessageQueue *mq = new MessageQueue(g_nmi->_currentScene->getMessageQueueById(QU_SC4_MANFROMBOTTLE), 0, 0);
929
930 if (ex) {
931 ExCommand *newex = ex->createClone();
932
933 mq->addExCommandToEnd(newex);
934 }
935
936 mq->_flags |= 1;
937 mq->chain(0);
938
939 g_vars->scene04_dudeInBottle = false;
940 g_nmi->_behaviorManager->setFlagByStaticAniObject(g_nmi->_aniMan, 1);
941 }
942
sceneHandler04_walkKozyawka()943 void sceneHandler04_walkKozyawka() {
944 debugC(1, kDebugSceneLogic, "scene04: walkKozyawka");
945
946 if (g_vars->scene04_kozyawkiObjList.size()) {
947 debugC(1, kDebugSceneLogic, "scene04: walkKozyawka: getting one");
948
949 g_vars->scene04_walkingKozyawka = g_vars->scene04_kozyawkiObjList.front();
950 g_vars->scene04_kozyawkiObjList.pop_front();
951
952 MessageQueue *mq = new MessageQueue(g_nmi->_currentScene->getMessageQueueById(QU_KOZAW_WALK), 0, 1);
953 mq->setParamInt(-1, g_vars->scene04_walkingKozyawka->_odelay);
954 mq->chain(0);
955 }
956 }
957
sceneHandler04_bottleUpdateObjects(int off)958 void sceneHandler04_bottleUpdateObjects(int off) {
959 for (Common::List<GameObject *>::iterator it = g_vars->scene04_bottleObjList.begin(); it != g_vars->scene04_bottleObjList.end(); ++it) {
960 if ((*it)->_objtype == kObjTypeStaticANIObject) {
961 StaticANIObject *st = static_cast<StaticANIObject *>(*it);
962
963 st->setOXY(st->_ox, off + st->_oy);
964 } else {
965 GameObject *obj = *it;
966
967 obj->setOXY(obj->_ox, off + obj->_oy);
968 }
969 }
970 }
971
sceneHandler04_springWobble()972 void sceneHandler04_springWobble() {
973 int oldDynIndex = g_vars->scene04_dynamicPhaseIndex;
974 int newdelta = g_vars->scene04_springOffset + g_vars->scene04_dynamicPhaseIndex;
975
976 g_vars->scene04_dynamicPhaseIndex += g_vars->scene04_springOffset;
977
978 if (newdelta < 0) {
979 newdelta = 0;
980 g_vars->scene04_dynamicPhaseIndex = 0;
981 g_vars->scene04_springOffset = 0;
982 }
983
984 if (newdelta > 14) {
985 newdelta = 14;
986 g_vars->scene04_dynamicPhaseIndex = 14;
987 g_vars->scene04_springOffset = 0;
988 }
989
990 if (g_vars->scene04_bottleWeight > newdelta)
991 g_vars->scene04_springOffset++;
992
993 if (g_vars->scene04_bottleWeight < newdelta)
994 g_vars->scene04_springOffset--;
995
996 if ((oldDynIndex <= g_vars->scene04_bottleWeight && newdelta > g_vars->scene04_bottleWeight)
997 || (oldDynIndex > g_vars->scene04_bottleWeight && newdelta <= g_vars->scene04_bottleWeight)) {
998 g_vars->scene04_springDelay++;
999
1000 if (g_vars->scene04_springOffset && g_vars->scene04_springDelay > 1) {
1001 g_vars->scene04_springDelay = 0;
1002 g_vars->scene04_springOffset = g_vars->scene04_springOffset - g_vars->scene04_springOffset / abs(g_vars->scene04_springOffset);
1003 }
1004 }
1005
1006 int oldpos = g_vars->scene04_spring->getCurrDimensions().y - oldDynIndex;
1007
1008 if (g_vars->scene04_dynamicPhaseIndex) {
1009 if (!g_vars->scene04_spring->_movement)
1010 g_vars->scene04_spring->startAnim(MV_SPR_LOWER, 0, -1);
1011
1012 g_vars->scene04_spring->_movement->setDynamicPhaseIndex(g_vars->scene04_dynamicPhaseIndex);
1013 } else {
1014 g_vars->scene04_spring->changeStatics2(ST_SPR_UP);
1015 }
1016
1017 if (g_vars->scene04_dynamicPhaseIndex != oldDynIndex) {
1018 sceneHandler04_bottleUpdateObjects(oldpos - (g_vars->scene04_spring->getCurrDimensions().y - g_vars->scene04_dynamicPhaseIndex));
1019 }
1020 }
1021
sceneHandler04_leaveScene()1022 void sceneHandler04_leaveScene() {
1023 g_nmi->_aniMan2 = 0;
1024
1025 MessageQueue *mq = new MessageQueue(g_nmi->_currentScene->getMessageQueueById(QU_SC4_MANTOBOTTLE), 0, 0);
1026 ExCommand *ex = 0;
1027
1028 for (uint i = 0; i < mq->getCount(); i++) {
1029 if (mq->getExCommandByIndex(i)->_messageKind == 27) {
1030 ex = mq->getExCommandByIndex(i);
1031 break;
1032 }
1033 }
1034
1035 if (!ex) {
1036 error("sceneHandler04_leaveScene(): Cannot find exit");
1037 }
1038
1039 ex->_y = g_vars->scene04_bottle->_oy - 304;
1040
1041 mq->chain(0);
1042
1043 g_vars->scene04_var07 = false;
1044 g_vars->scene04_dudeOnLadder = 0;
1045
1046 g_nmi->_behaviorManager->setFlagByStaticAniObject(g_nmi->_aniMan, 0);
1047
1048 g_nmi->updateMapPiece(PIC_MAP_P03, 1);
1049 }
1050
sceneHandler04_liftBottle()1051 void sceneHandler04_liftBottle() {
1052 int newy = g_vars->scene04_bottleY + g_vars->scene04_spring->_oy;
1053
1054 g_vars->scene04_bottleY += 5;
1055
1056 sceneHandler04_bottleUpdateObjects(newy - g_vars->scene04_spring->_oy);
1057
1058 g_vars->scene04_spring->setOXY(g_vars->scene04_spring->_ox, newy);
1059
1060 if (g_vars->scene04_bottle->_oy >= 226) {
1061 sceneHandler04_bottleUpdateObjects(226 - g_vars->scene04_bottle->_oy);
1062
1063 g_vars->scene04_spring->setOXY(g_vars->scene04_spring->_ox, 437);
1064 g_vars->scene04_bottleIsDropped = false;
1065 g_vars->scene04_handIsDown = false;
1066 g_vars->scene04_objectIsTaken = true;
1067 g_vars->scene04_bottleWeight = 2;
1068 g_vars->scene04_springOffset = 10;
1069 g_vars->scene04_bottleIsTaken = false;
1070
1071 g_nmi->setObjectState(sO_LowerPipe, g_nmi->getObjectEnumState(sO_LowerPipe, sO_IsClosed));
1072 }
1073 }
1074
sceneHandler04_startSounds(const char * snd1,const char * snd2,const char * snd3)1075 void sceneHandler04_startSounds(const char *snd1, const char *snd2, const char *snd3) {
1076 g_nmi->playOggSound(snd1, g_nmi->_soundStream2);
1077
1078 g_nmi->_stream2playing = true;
1079
1080 g_vars->scene04_musicStage = 1;
1081 }
1082
updateSound()1083 void updateSound() {
1084 switch (g_vars->scene04_musicStage) {
1085 case 0:
1086 default:
1087 break;
1088 case 1:
1089 if (!g_nmi->_mixer->isSoundHandleActive(g_nmi->_soundStream2)) {
1090 g_nmi->playOggSound("sc4_loop.ogg", g_nmi->_soundStream3);
1091 g_vars->scene04_musicStage = 2;
1092 }
1093 break;
1094 case 2:
1095 if (!g_nmi->_mixer->isSoundHandleActive(g_nmi->_soundStream3)) {
1096 if (g_nmi->_stream2playing) { // Looop it
1097 g_nmi->playOggSound("sc4_loop.ogg", g_nmi->_soundStream3);
1098 } else {
1099 g_nmi->playOggSound("sc4_stop2.ogg", g_nmi->_soundStream4);
1100 g_vars->scene04_musicStage = 3;
1101 }
1102 }
1103 break;
1104 case 3:
1105 if (!g_nmi->_mixer->isSoundHandleActive(g_nmi->_soundStream4)) {
1106 g_vars->scene04_musicStage = 0;
1107 }
1108 break;
1109 }
1110 }
1111
sceneHandler04_goClock()1112 void sceneHandler04_goClock() {
1113 sceneHandler04_walkKozyawka();
1114 chainQueue(QU_SC4_GOCLOCK, 0);
1115 g_vars->scene04_soundPlaying = true;
1116 g_vars->scene04_coinPut = false;
1117
1118 g_nmi->stopAllSoundStreams();
1119
1120 sceneHandler04_startSounds("sc4_start.ogg", "sc4_loop.ogg", "sc4_stop2.ogg");
1121
1122 g_vars->scene04_bigBallCounter = 0;
1123 }
1124
sceneHandler04_bigBallOut()1125 void sceneHandler04_bigBallOut() {
1126 StaticANIObject *ball = g_nmi->_currentScene->getStaticANIObject1ById(ANI_BIGBALL, -1);
1127
1128 if (ball && ball->_flags & 4)
1129 for (uint i = 0; i < ball->_movements.size(); i++)
1130 ball->_movements[i]->_counterMax = 0;
1131
1132 g_vars->scene04_bigBallIn = false;
1133 }
1134
sceneHandler04_leaveLadder(ExCommand * ex)1135 void sceneHandler04_leaveLadder(ExCommand *ex) {
1136 if (!g_nmi->_aniMan->isIdle())
1137 return;
1138
1139 if (!(g_nmi->_aniMan->_flags & 0x100)) {
1140 if (getSc2MctlCompoundBySceneId(g_nmi->_currentScene->_sceneId)->_objtype == kObjTypeMctlCompound) {
1141 MctlCompound *mc = static_cast<MctlCompound *>(getSc2MctlCompoundBySceneId(g_nmi->_currentScene->_sceneId));
1142
1143 if (mc->_motionControllers[0]->_movGraphReactObj->pointInRegion(g_nmi->_sceneRect.left + ex->_x, g_nmi->_sceneRect.top + ex->_y)) {
1144 if (g_vars->scene04_ladder->collisionDetection(g_nmi->_aniMan)) {
1145 MessageQueue *mq = g_vars->scene04_ladder->controllerWalkTo(g_nmi->_aniMan, 0);
1146
1147 if (mq) {
1148 mq->addExCommandToEnd(ex->createClone());
1149
1150 if (mq->chain(g_nmi->_aniMan) )
1151 ex->_messageKind = 0;
1152 else
1153 delete mq;
1154
1155 if (g_vars->scene04_bigBallIn) {
1156 sceneHandler04_bigBallOut();
1157 return;
1158 }
1159 }
1160 } else {
1161 MessageQueue *mq = new MessageQueue(g_nmi->_globalMessageQueueList->compact());
1162 ExCommand *ex1;
1163
1164 if (g_nmi->_aniMan->_statics->_staticsId == ST_MAN_LADDERDOWN) {
1165 ex1 = new ExCommand(ANI_MAN, 1, MV_MAN_LOOKLADDERRV, 0, 0, 0, 1, 0, 0, 0);
1166 ex1->_param = g_nmi->_aniMan->_odelay;
1167 ex1->_excFlags |= 2;
1168 mq->addExCommandToEnd(ex1);
1169 }
1170
1171 ex1 = new ExCommand(ANI_MAN, 1, MV_MAN_STARTLADDERD, 0, 0, 0, 1, 0, 0, 0);
1172 ex1->_param = g_nmi->_aniMan->_odelay;
1173 ex1->_excFlags |= 2;
1174 mq->addExCommandToEnd(ex1);
1175
1176 ex1 = new ExCommand(ANI_MAN, 1, MV_MAN_FROMLADDER, 0, 0, 0, 1, 0, 0, 0);
1177 ex1->_param = g_nmi->_aniMan->_odelay;
1178 ex1->_excFlags |= 2;
1179 mq->addExCommandToEnd(ex1);
1180
1181 ex1 = ex->createClone();
1182 mq->addExCommandToEnd(ex1);
1183
1184 mq->setFlags(mq->getFlags() | 1);
1185
1186 if (mq->chain(g_nmi->_aniMan)) {
1187 if (g_vars->scene04_ladder)
1188 delete g_vars->scene04_ladder;
1189
1190 g_vars->scene04_ladder = 0;
1191 g_vars->scene04_dudeOnLadder = 0;
1192
1193 ex->_messageKind = 0;
1194
1195 mc->activate();
1196 getGameLoaderInteractionController()->enableFlag24();
1197 } else {
1198 delete mq;
1199 }
1200
1201 if (g_vars->scene04_bigBallIn) {
1202 sceneHandler04_bigBallOut();
1203 return;
1204 }
1205 }
1206 }
1207 }
1208 }
1209 }
1210
sceneHandler04_handTake()1211 void sceneHandler04_handTake() {
1212 g_vars->scene04_clock->changeStatics2(ST_CLK_CLOSED);
1213
1214 if (g_vars->scene04_kozyawkiAni.size()) {
1215 if (g_vars->scene04_kozyawkiAni.size() == 1) {
1216 chainQueue(QU_HND_TAKE1, 0);
1217 g_vars->scene04_objectIsTaken = false;
1218 } else {
1219 chainQueue((g_vars->scene04_kozyawkiAni.size() != 2) ? QU_HND_TAKEBOTTLE : QU_HND_TAKE2, 0);
1220 g_vars->scene04_objectIsTaken = false;
1221 }
1222 } else {
1223 chainQueue(QU_HND_TAKE0, 0);
1224 g_vars->scene04_objectIsTaken = false;
1225 }
1226 }
1227
sceneHandler04_putKozyawkaBack(StaticANIObject * ani)1228 void sceneHandler04_putKozyawkaBack(StaticANIObject *ani) {
1229 debugC(2, kDebugSceneLogic, "scene04: putKozyawkaBack");
1230
1231 g_vars->scene04_bottleObjList.push_back(ani);
1232 g_vars->scene04_kozyawkiAni.push_back(ani);
1233
1234 g_vars->scene04_bottleWeight += 2;
1235 g_vars->scene04_walkingKozyawka = 0;
1236 g_vars->scene04_lastKozyawka = 0;
1237
1238 if (g_vars->scene04_kozyawkiAni.size() > 1 )
1239 g_vars->scene04_objectIsTaken = false;
1240
1241 if (g_vars->scene04_kozyawkiAni.size() <= 2 || g_vars->scene04_hand->_movement) {
1242 sceneHandler04_walkKozyawka();
1243 } else {
1244 sceneHandler04_handTake();
1245 sceneHandler04_stopSound();
1246 }
1247 }
1248
sceneHandler04_bigBallWalkIn()1249 void sceneHandler04_bigBallWalkIn() {
1250 StaticANIObject *ball = g_nmi->_currentScene->getStaticANIObject1ById(ANI_BIGBALL, -1);
1251
1252 if (g_vars->scene04_dudeOnLadder
1253 && (!ball || !(ball->_flags & 4))
1254 && g_vars->scene04_ladder->collisionDetection(g_nmi->_aniMan) > 3) {
1255
1256 if (!g_nmi->_rnd.getRandomNumber(49)) {
1257 if (g_vars->scene04_bigBallFromLeft)
1258 chainQueue(QU_BALL_WALKR, 0);
1259 else
1260 chainQueue(QU_BALL_WALKL, 0);
1261
1262 g_vars->scene04_bigBallFromLeft = !g_vars->scene04_bigBallFromLeft;
1263
1264 sceneHandler04_checkBigBallClick();
1265
1266 g_vars->scene04_bigBallCounter = 0;
1267 }
1268 }
1269 }
1270
sceneHandler04_takeBottle()1271 void sceneHandler04_takeBottle() {
1272 g_vars->scene04_bottleIsTaken = true;
1273 g_vars->scene04_hand->_priority = 5;
1274
1275 g_nmi->setObjectState(sO_LowerPipe, g_nmi->getObjectEnumState(sO_LowerPipe, sO_IsOpened));
1276 }
1277
sceneHandler04_takeKozyawka()1278 void sceneHandler04_takeKozyawka() {
1279 if (g_vars->scene04_kozyawkiAni.size() > 0) {
1280 if (g_vars->scene04_kozyawkiAni.size() == 1)
1281 g_vars->scene04_objectIsTaken = true;
1282
1283 StaticANIObject *koz = g_vars->scene04_kozyawkiAni.front();
1284 g_vars->scene04_kozyawkiAni.pop_front();
1285
1286 if (koz) {
1287 koz->queueMessageQueue(0);
1288 koz->hide();
1289
1290 g_vars->scene04_kozyawkiObjList.push_back(koz);
1291
1292 for (Common::List<GameObject *>::iterator it = g_vars->scene04_bottleObjList.begin(); it != g_vars->scene04_bottleObjList.end(); ++it)
1293 if (*it == koz) {
1294 g_vars->scene04_bottleObjList.erase(it);
1295 break;
1296 }
1297
1298 g_vars->scene04_bottleWeight -= 2;
1299 }
1300 }
1301 }
1302
sceneHandler04_testPlank(ExCommand * ex)1303 void sceneHandler04_testPlank(ExCommand *ex) {
1304 MessageQueue *mq = g_nmi->_globalMessageQueueList->getMessageQueueById(ex->_parId);
1305
1306 if (!mq)
1307 return;
1308
1309 if (g_vars->scene04_plank->_movement || !g_vars->scene04_plank->_statics || g_vars->scene04_plank->_statics->_staticsId != ST_PNK_WEIGHTLEFT) {
1310 mq->getExCommandByIndex(0)->_messageNum = MV_KZW_TOHOLERV;
1311 } else {
1312 mq->getExCommandByIndex(0)->_messageNum = MV_KZW_WALKPLANK;
1313 }
1314 }
1315
sceneHandler04_updateBottle()1316 void sceneHandler04_updateBottle() {
1317 int yoff;
1318
1319 if (g_vars->scene04_hand->_movement)
1320 yoff = g_vars->scene04_hand->_movement->_oy;
1321 else
1322 yoff = g_vars->scene04_hand->_oy;
1323
1324 int newy = g_vars->scene04_hand->getSomeXY().y + yoff + 140;
1325
1326 sceneHandler04_bottleUpdateObjects(newy - g_vars->scene04_spring->_oy);
1327
1328 g_vars->scene04_spring->setOXY(g_vars->scene04_spring->_ox, newy);
1329 }
1330
sceneHandler04_winArcade()1331 void sceneHandler04_winArcade() {
1332 if (g_nmi->getObjectState(sO_LowerPipe) == g_nmi->getObjectEnumState(sO_LowerPipe, sO_IsClosed)
1333 && g_vars->scene04_soundPlaying) {
1334 g_vars->scene04_clock->changeStatics2(ST_CLK_CLOSED);
1335 g_vars->scene04_hand->changeStatics2(ST_HND_EMPTY);
1336
1337 chainQueue(QU_HND_TAKEBOTTLE, 1);
1338
1339 if (g_vars->scene04_walkingKozyawka) {
1340 g_vars->scene04_kozyawkiObjList.push_back(g_vars->scene04_walkingKozyawka);
1341
1342 g_vars->scene04_walkingKozyawka->changeStatics2(ST_KZW_EMPTY);
1343 g_vars->scene04_walkingKozyawka->hide();
1344 g_vars->scene04_walkingKozyawka = 0;
1345 }
1346
1347 g_vars->scene04_objectIsTaken = false;
1348 g_vars->scene04_soundPlaying = false;
1349
1350 getSc2MctlCompoundBySceneId(g_nmi->_currentScene->_sceneId)->activate();
1351
1352 getGameLoaderInteractionController()->enableFlag24();
1353
1354 g_nmi->stopSoundStream2();
1355 }
1356 }
1357
sceneHandler04(ExCommand * ex)1358 int sceneHandler04(ExCommand *ex) {
1359 if (ex->_messageKind != 17)
1360 return 0;
1361
1362 switch (ex->_messageNum) {
1363 case MSG_UPDATEBOTTLE:
1364 sceneHandler04_updateBottle();
1365 break;
1366
1367 case MSG_CLICKBOTTLE:
1368 sceneHandler04_clickBottle();
1369 break;
1370
1371 case MSG_SHOOTKOZAW:
1372 sceneHandler04_shootKozyawka();
1373 break;
1374
1375 case MSG_SHAKEBOTTLE:
1376 if (!g_vars->scene04_bottleIsTaken)
1377 ++g_vars->scene04_springOffset;
1378 break;
1379
1380 case MSG_STARTHAND:
1381 g_vars->scene04_handIsDown = true;
1382 g_vars->scene04_coinPut = false;
1383
1384 if (g_vars->scene04_dudeInBottle)
1385 sceneHandler04_animOutOfBottle(0);
1386
1387 sceneHandler04_handTake();
1388 sceneHandler04_stopSound();
1389 break;
1390
1391 case MSG_TAKEKOZAW:
1392 sceneHandler04_takeKozyawka();
1393 break;
1394
1395 case MSG_CLICKBUTTON:
1396 sceneHandler04_clickButton();
1397 break;
1398
1399 case MSG_CLICKPLANK:
1400 sceneHandler04_clickPlank();
1401 break;
1402
1403 case MSG_RAISEPLANK:
1404 sceneHandler04_raisePlank();
1405 break;
1406
1407 case MSG_KOZAWRESTART:
1408 debugC(1, kDebugSceneLogic, "scene04: kozawRestart");
1409
1410 if (g_vars->scene04_walkingKozyawka) {
1411 g_vars->scene04_kozyawkiObjList.push_back(g_vars->scene04_walkingKozyawka);
1412 g_vars->scene04_walkingKozyawka->hide();
1413 g_vars->scene04_walkingKozyawka = 0;
1414 }
1415
1416 if (g_vars->scene04_soundPlaying)
1417 sceneHandler04_walkKozyawka();
1418
1419 break;
1420
1421 case MSG_LOWERPLANK:
1422 sceneHandler04_lowerPlank();
1423 break;
1424
1425 case MSG_TESTPLANK:
1426 sceneHandler04_testPlank(ex);
1427 break;
1428
1429 case 33:
1430 {
1431 g_vars->scene04_dudePosX = g_nmi->_aniMan->_ox;
1432 g_vars->scene04_dudePosY = g_nmi->_aniMan->_oy;
1433
1434 int res = 0;
1435
1436 if (g_nmi->_aniMan2) {
1437 if (g_nmi->_aniMan->_ox < g_nmi->_sceneRect.left + 200) {
1438 g_nmi->_currentScene->_x = g_nmi->_aniMan->_ox - g_nmi->_sceneRect.left - 300;
1439 g_nmi->_aniMan->_ox = g_vars->scene04_dudePosX;
1440 }
1441 if (g_nmi->_aniMan->_ox > g_nmi->_sceneRect.right - 200) {
1442 g_nmi->_currentScene->_x = g_nmi->_aniMan->_ox - g_nmi->_sceneRect.right + 300;
1443 }
1444
1445 res = 1;
1446 }
1447
1448 g_nmi->sceneAutoScrolling();
1449
1450 if (g_nmi->_aniMan2) {
1451 if (g_vars->scene04_soundPlaying) {
1452 if (g_nmi->_aniMan->_movement) {
1453 if (g_nmi->_aniMan->_movement->_id == MV_MAN_TOLADDER) {
1454 g_nmi->_aniMan2 = 0;
1455
1456 if (g_nmi->_sceneRect.left > 380)
1457 g_nmi->_currentScene->_x = 380 - g_nmi->_sceneRect.left;
1458 }
1459 }
1460 }
1461 } else {
1462 if (g_nmi->_aniMan->_movement && g_nmi->_aniMan->_movement->_id == MV_MAN_GOD)
1463 g_nmi->_aniMan2 = g_nmi->_aniMan;
1464 }
1465
1466 sceneHandler04_springWobble();
1467
1468 if (g_vars->scene04_var07 && !g_vars->scene04_handIsDown)
1469 sceneHandler04_leaveScene();
1470
1471 if (g_vars->scene04_bottleIsDropped)
1472 sceneHandler04_liftBottle();
1473
1474 if (g_vars->scene04_ladderClickable)
1475 sceneHandler04_clickLadder();
1476
1477 if (g_vars->scene04_dudeInBottle && g_vars->scene04_hand->_movement)
1478 sceneHandler04_animOutOfBottle(0);
1479
1480 if (g_vars->scene04_coinPut && g_vars->scene04_clockCanGo && !g_vars->scene04_handIsDown && !g_vars->scene04_soundPlaying)
1481 sceneHandler04_goClock();
1482
1483 if (g_vars->scene04_dudeOnLadder) {
1484 if (!g_vars->scene04_soundPlaying) {
1485 g_nmi->startSceneTrack();
1486
1487 g_nmi->_behaviorManager->updateBehaviors();
1488 return res;
1489 }
1490
1491 g_vars->scene04_bigBallCounter++;
1492
1493 if (g_vars->scene04_bigBallCounter > 600)
1494 sceneHandler04_bigBallWalkIn();
1495 }
1496
1497 if (g_vars->scene04_soundPlaying) {
1498 g_nmi->_behaviorManager->updateBehaviors();
1499
1500 return res;
1501 }
1502
1503 g_nmi->startSceneTrack();
1504
1505 g_nmi->_behaviorManager->updateBehaviors();
1506
1507 return res;
1508 }
1509 break;
1510
1511 case 29:
1512 {
1513 int picid = g_nmi->_currentScene->getPictureObjectIdAtPos(ex->_sceneClickX, ex->_sceneClickY);
1514
1515 if (g_vars->scene04_dudeInBottle) {
1516 sceneHandler04_animOutOfBottle(ex);
1517
1518 break;
1519 }
1520
1521 if (picid == PIC_SC4_LADDER) {
1522 if (!g_vars->scene04_kozyawkaOnLadder) {
1523 g_vars->scene04_sceneClickX = ex->_sceneClickX;
1524 g_vars->scene04_sceneClickY = ex->_sceneClickY;
1525
1526 sceneHandler04_clickLadder();
1527
1528 ex->_messageKind = 0;
1529
1530 break;
1531 }
1532
1533 sceneHandler04_gotoLadder(0);
1534
1535 break;
1536 }
1537
1538 StaticANIObject *ani = g_nmi->_currentScene->getStaticANIObjectAtPos(ex->_sceneClickX, ex->_sceneClickY);
1539
1540 if ((ani && ani->_id == ANI_PLANK) || picid == PIC_SC4_PLANK) {
1541 sceneHandler04_clickPlank();
1542
1543 ex->_messageKind = 0;
1544 } else if (g_vars->scene04_dudeOnLadder) {
1545 sceneHandler04_leaveLadder(ex);
1546 } else if (!ani || !canInteractAny(g_nmi->_aniMan, ani, ex->_param)) {
1547 PictureObject *pic = g_nmi->_currentScene->getPictureObjectById(picid, 0);
1548
1549 if (!pic || !canInteractAny(g_nmi->_aniMan, pic,ex->_param)) {
1550 if ((g_nmi->_sceneRect.right - ex->_sceneClickX < 47 && g_nmi->_sceneRect.right < g_nmi->_sceneWidth - 1)
1551 || (ex->_sceneClickX - g_nmi->_sceneRect.left < 47 && g_nmi->_sceneRect.left > 0))
1552 g_nmi->processArcade(ex);
1553 }
1554 }
1555 }
1556 break;
1557
1558 case MSG_SC4_HIDEBOOT:
1559 g_vars->scene04_boot->_flags &= 0xfffb;
1560 break;
1561
1562 case MSG_CMN_WINARCADE:
1563 sceneHandler04_winArcade();
1564 break;
1565
1566 case MSG_SC4_HANDOVER:
1567 g_vars->scene04_handIsDown = false;
1568 g_vars->scene04_objectIsTaken = true;
1569 break;
1570
1571 case MSG_SC4_DROPBOTTLE:
1572 sceneHandler04_dropBottle();
1573 break;
1574
1575 case MSG_SC4_COINOUT:
1576 g_vars->scene04_clock->changeStatics2(ST_CLK_CLOSED);
1577 g_vars->scene04_coinPut = false;
1578 sceneHandler04_stopSound();
1579
1580 if (g_vars->scene04_kozyawkiAni.size() && !g_vars->scene04_bottleIsTaken) {
1581 g_vars->scene04_handIsDown = true;
1582
1583 if (g_vars->scene04_dudeInBottle)
1584 sceneHandler04_animOutOfBottle(0);
1585
1586 sceneHandler04_handTake();
1587 }
1588 break;
1589
1590 case MSG_SC4_KOZAWFALL:
1591 {
1592 ExCommand *exnew;
1593
1594 if (g_vars->scene04_kozHeadRaised) {
1595 sceneHandler04_putKozyawkaBack(g_vars->scene04_lastKozyawka);
1596
1597 g_vars->scene04_kozHeadRaised = 0;
1598
1599 exnew = new ExCommand(0, 35, SND_4_010, 0, 0, 0, 1, 0, 0, 0);
1600 } else {
1601 exnew = new ExCommand(0, 35, SND_4_012, 0, 0, 0, 1, 0, 0, 0);
1602 }
1603
1604 exnew->_z = 5;
1605 exnew->_excFlags |= 2;
1606 exnew->postMessage();
1607 }
1608 break;
1609
1610 case MSG_SC4_MANFROMBOTTLE:
1611 sceneHandler04_manFromBottle();
1612 break;
1613
1614 case MSG_SC4_CLICKLADDER:
1615 sceneHandler04_clickLadder();
1616 break;
1617
1618 case MSG_SC4_MANTOBOTTLE:
1619 sceneHandler04_manToBottle();
1620 break;
1621
1622 case MSG_SHOWCOIN:
1623 sceneHandler04_showCoin();
1624 break;
1625
1626 case MSG_TAKEBOTTLE:
1627 sceneHandler04_takeBottle();
1628 break;
1629
1630 case MSG_GOTOLADDER:
1631 sceneHandler04_gotoLadder(0);
1632 break;
1633
1634 case MSG_SC4_COINPUT:
1635 g_vars->scene04_coinPut = true;
1636 break;
1637
1638 default:
1639 break;
1640 }
1641
1642 updateSound();
1643
1644 return 0;
1645 }
1646
1647 } // End of namespace NGI
1648