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 "common/scummsys.h"
24 #include "common/config-manager.h"
25 #include "graphics/scaler.h"
26 #include "mads/mads.h"
27 #include "mads/game.h"
28 #include "mads/screen.h"
29 #include "mads/msurface.h"
30 #include "mads/menu_views.h"
31 #include "mads/nebular/game_nebular.h"
32 #include "mads/nebular/dialogs_nebular.h"
33 #include "mads/nebular/globals_nebular.h"
34 #include "mads/nebular/nebular_scenes.h"
35
36 namespace MADS {
37
38 namespace Nebular {
39
GameNebular(MADSEngine * vm)40 GameNebular::GameNebular(MADSEngine *vm)
41 : Game(vm) {
42 _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
43 _storyMode = STORYMODE_NAUGHTY;
44 _difficulty = DIFFICULTY_HARD;
45 }
46
checkCopyProtection()47 ProtectionResult GameNebular::checkCopyProtection() {
48 // Only show copy protection dialog if explicitly wanted
49 if (!ConfMan.getBool("copy_protection"))
50 return PROTECTION_SUCCEED;
51
52 CopyProtectionDialog *dlg;
53 bool correctAnswer;
54
55 dlg = new CopyProtectionDialog(_vm, false);
56 dlg->show();
57 correctAnswer = dlg->isCorrectAnswer();
58 delete dlg;
59
60 if (!correctAnswer && !_vm->shouldQuit()) {
61 dlg = new CopyProtectionDialog(_vm, true);
62 dlg->show();
63 correctAnswer = dlg->isCorrectAnswer();
64 delete dlg;
65 }
66
67 return correctAnswer ? PROTECTION_SUCCEED : PROTECTION_FAIL;
68 }
69
startGame()70 void GameNebular::startGame() {
71 // First handle any ending credits from a just finished game session.
72 // Note that, with the exception of the decompression ending, which doesn't
73 // use animations, the remaining animations will automatically launch their
74 // own text view credits when the animation is completed
75 switch (_winStatus) {
76 case 1:
77 // No shields failure ending
78 AnimationView::execute(_vm, "rexend1");
79 break;
80 case 2:
81 // Shields, but no targetting failure ending
82 AnimationView::execute(_vm, "rexend2");
83 break;
84 case 3:
85 // Completed game successfully, so activate quotes item on the main menu
86 ConfMan.setBool("ShowQuotes", true);
87 ConfMan.flushToDisk();
88
89 AnimationView::execute(_vm, "rexend3");
90 break;
91 case 4:
92 // Decompression ending
93 TextView::execute(_vm, "ending4");
94 break;
95 default:
96 break;
97 }
98
99 do {
100 checkShowDialog();
101 _winStatus = 0;
102
103 _sectionNumber = 1;
104 initSection(_sectionNumber);
105 _vm->_events->setCursor(CURSOR_ARROW);
106 _statusFlag = true;
107
108 // Show the main menu
109 _vm->_dialogs->_pendingDialog = DIALOG_MAIN_MENU;
110 _vm->_dialogs->showDialog();
111 } while (!_vm->shouldQuit() && _vm->_dialogs->_pendingDialog != DIALOG_NONE);
112
113 if (_vm->shouldQuit())
114 return;
115
116 _priorSectionNumber = 0;
117 _priorSectionNumber = -1;
118 _scene._priorSceneId = 0;
119 _scene._currentSceneId = -1;
120 _scene._nextSceneId = 101;
121
122 initializeGlobals();
123
124 if (_loadGameSlot >= 0)
125 // User selected to resume a savegame
126 return;
127
128 // Check copy protection
129 ProtectionResult protectionResult = checkCopyProtection();
130
131 switch (protectionResult) {
132 case PROTECTION_FAIL:
133 // Copy protection failed
134 _scene._nextSceneId = 804;
135 _globals[kCopyProtectFailed] = true;
136 return;
137 case PROTECTION_ESCAPE:
138 // User escaped out of copy protection dialog
139 _vm->quitGame();
140 return;
141 default:
142 // Copy protection check succeeded
143 break;
144 }
145 }
146
initializeGlobals()147 void GameNebular::initializeGlobals() {
148 int count, count2;
149 int bad;
150
151 _globals.reset();
152 _globals[kTalkInanimateCount] = 8;
153
154 /* Section #1 variables */
155 _globals[kNeedToStandUp] = true;
156 _globals[kTurkeyExploded] = false;
157 _globals[kMedicineCabinetOpen] = false;
158 _globals[kMedicineCabinetVirgin] = true;
159 _globals[kWatchedViewScreen] = false;
160 _globals[kHoovicAlive] = true;
161 _globals[kWaterInAPuddle] = false;
162
163 _globals[kFishIn105] = true;
164 _globals[kFishIn107] = true;
165 _globals[kFishIn108] = true;
166
167 /* Section #2 variables */
168 _globals[kLadderBroken] = false;
169 _globals[kBone202Status] = 0;
170 _globals[kRhotundaStatus] = RHOTUNDA_HUNGRY;
171 _globals[kMonkeyStatus] = MONKEY_AMBUSH_READY;
172 _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT;
173 _globals[kMeteorologistEverSeen] = false;
174 _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL;
175 _globals[kTeleporterCommand] = TELEPORTER_NONE;
176 _globals[kTeleporterUnderstood] = false;
177 _globals[kTwinklesStatus] = TWINKLES_AT_HOME;
178 _globals[kTwinklesApproached] = 0;
179
180 /* Section #3 variables */
181 _globals[kAfterHavoc] = false;
182 _globals[kKickedIn391Grate] = false;
183
184 /* Section #4 variables */
185 _globals[kBadFirstIngredient] = -1;
186 _objects[OBJ_CHARGE_CASES].setQuality(EXPLOSIVES_INSIDE, 0);
187 _globals[kHasPurchased] = false;
188 _globals[kBeenThruHelgaScene] = false;
189 _globals[kNextIngredient] = 0;
190 _globals[kHasSaidTimer] = false;
191 _globals[kHasSaidBinocs] = false;
192 _globals[kBottleDisplayed] = false;
193 _globals[kHasBeenScanned] = false;
194 _globals[kSomeoneHasExploded] = false;
195
196 // Generate a random ingredient list
197 for (count = 0; count < 4; ++count) {
198 do {
199 _globals[kIngredientList + count] = _vm->getRandomNumber(3);
200 bad = false;
201 for (count2 = 0; count2 < count; ++count2) {
202 if (_globals[kIngredientList + count] == _globals[kIngredientList + count2]) {
203 bad = true;
204 }
205 }
206 } while (bad);
207 }
208
209 // Generate random ingredient quantities
210 for (count = 0; count < 4; ++count) {
211 do {
212 _globals[kIngredientQuantity + count] = _vm->getRandomNumber(3);
213 bad = false;
214 for (count2 = 0; count2 < count; ++count2) {
215 if (_globals[kIngredientQuantity + count] == _globals[kIngredientQuantity + count2]) {
216 bad = true;
217 }
218 }
219 } while (bad);
220 }
221
222
223 /* Section #5 variables */
224 _globals[kHoverCarLocation] = 501;
225 _globals[kHoverCarDestination] = -1;
226 _globals[kCityFlooded] = false;
227 _globals[kBoatRaised] = true;
228 _globals[kLaserHoleIsThere] = false;
229 _globals[kLineStatus] = LINE_NOT_DROPPED;
230
231
232 /* Section #6 variables */
233 _globals[kHasTalkedToHermit] = false;
234 _globals[kHandsetCellStatus] = FIRST_TIME_PHONE_CELLS;
235 _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED;
236 _globals[kWarnedFloodCity] = false;
237 _globals._timebombClock = 0;
238 _globals._timebombTimer = 0;
239
240
241 /* Section #7 variables */
242 _globals[kBottleStatus] = BOTTLE_EMPTY;
243 _globals[kBoatStatus] = BOAT_UNFLOODED;
244
245
246 /* Section #8 variables */
247 _globals[kWindowFixed] = false;
248 _globals[kInSpace] = false;
249 _globals[kReturnFromCut] = false;
250 _globals[kBeamIsUp] = false;
251 _globals[kForceBeamDown] = false;
252 _globals[kCameFromCut] = false;
253 _globals[kDontRepeat] = false;
254 _globals[kHoppyDead] = false;
255 _globals[kHasWatchedAntigrav] = false;
256 _globals[kRemoteSequenceRan] = false;
257 _globals[kRemoteOnGround] = false;
258 _globals[kFromCockpit] = false;
259 _globals[kExitShip] = false;
260 _globals[kBetweenRooms] = false;
261 _globals[kTopButtonPushed] = false;
262 _globals[kShieldModInstalled] = false;
263 _globals[kTargetModInstalled] = false;
264 _globals[kUpBecauseOfRemote] = false;
265
266
267 /* Set up the game's teleporters */
268 _globals[kTeleporterRoom] = 201;
269 _globals[kTeleporterRoom + 1] = 301;
270 _globals[kTeleporterRoom + 2] = 413;
271 _globals[kTeleporterRoom + 3] = 706;
272 _globals[kTeleporterRoom + 4] = 801;
273 _globals[kTeleporterRoom + 5] = 551;
274 _globals[kTeleporterRoom + 6] = 752;
275 _globals[kTeleporterRoom + 7] = 0;
276 _globals[kTeleporterRoom + 8] = 0;
277 _globals[kTeleporterRoom + 9] = 0;
278
279 for (count = 0; count < TELEPORTER_COUNT; ++count) {
280 do {
281 _globals[kTeleporterCode + count] = _vm->getRandomNumber(9999);
282 bad = false;
283 for (count2 = 0; count2 < count; ++count2) {
284 if (_globals[kTeleporterCode + count] == _globals[kTeleporterCode + count2]) {
285 bad = true;
286 }
287 }
288 } while (bad);
289 }
290
291 // Final setup based on selected difficulty level
292 switch (_difficulty) {
293 case DIFFICULTY_HARD:
294 default:
295 _objects.setRoom(OBJ_BLOWGUN, NOWHERE);
296 _objects.setRoom(OBJ_NOTE, NOWHERE);
297
298 _globals[kLeavesStatus] = LEAVES_ON_GROUND;
299 _globals[kDurafailRecharged] = 0;
300 _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL;
301 break;
302
303 case DIFFICULTY_MEDIUM:
304 _objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
305
306 _globals[kLeavesStatus] = LEAVES_ON_GROUND;
307 _globals[kDurafailRecharged] = 1;
308 _globals[kPenlightCellStatus] = FIRST_TIME_CHARGED_DURAFAIL;
309 break;
310
311 case DIFFICULTY_EASY:
312 _objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
313 _objects.setRoom(OBJ_PENLIGHT, NOWHERE);
314
315 _globals[kLeavesStatus] = LEAVES_ON_TRAP;
316 break;
317 }
318
319 _player._facing = FACING_NORTH;
320 _player._turnToFacing = FACING_NORTH;
321
322 Player::preloadSequences("RXM", 1);
323 Player::preloadSequences("ROX", 1);
324 }
325
setSectionHandler()326 void GameNebular::setSectionHandler() {
327 delete _sectionHandler;
328
329 switch (_sectionNumber) {
330 case 1:
331 _sectionHandler = new Section1Handler(_vm);
332 break;
333 case 2:
334 _sectionHandler = new Section2Handler(_vm);
335 break;
336 case 3:
337 _sectionHandler = new Section3Handler(_vm);
338 break;
339 case 4:
340 _sectionHandler = new Section4Handler(_vm);
341 break;
342 case 5:
343 _sectionHandler = new Section5Handler(_vm);
344 break;
345 case 6:
346 _sectionHandler = new Section6Handler(_vm);
347 break;
348 case 7:
349 _sectionHandler = new Section7Handler(_vm);
350 break;
351 case 8:
352 _sectionHandler = new Section8Handler(_vm);
353 break;
354 default:
355 break;
356 }
357 }
358
checkShowDialog()359 void GameNebular::checkShowDialog() {
360 // Loop for showing dialogs, if any need to be shown
361 if (_vm->_dialogs->_pendingDialog && (_player._stepEnabled || _winStatus)
362 && !_globals[kCopyProtectFailed]) {
363 _player.releasePlayerSprites();
364
365 // Make a thumbnail in case it's needed for making a savegame
366 _vm->_game->createThumbnail();
367
368 // Show the dialog
369 _vm->_dialogs->showDialog();
370 _vm->_dialogs->_pendingDialog = DIALOG_NONE;
371 }
372 }
373
showRecipe()374 void GameNebular::showRecipe() {
375 Dialogs &dialogs = *_vm->_dialogs;
376 int count;
377
378 for (count = 0; count < 4; count++) {
379 switch(_globals[kIngredientQuantity + count]) {
380 case 0:
381 dialogs._indexList[count] = NOUN_DROP;
382 break;
383 case 1:
384 dialogs._indexList[count] = NOUN_DOLLOP;
385 break;
386 case 2:
387 dialogs._indexList[count] = NOUN_DASH;
388 break;
389 case 3:
390 dialogs._indexList[count] = NOUN_SPLASH;
391 break;
392 default:
393 break;
394 }
395 }
396
397 for (count = 0; count < 4; count++) {
398 switch(_globals[kIngredientList + count]) {
399 case 0:
400 dialogs._indexList[count + 4] = NOUN_ALCOHOL;
401 break;
402 case 1:
403 dialogs._indexList[count + 4] = NOUN_LECITHIN;
404 break;
405 case 2:
406 dialogs._indexList[count + 4] = NOUN_PETROX;
407 break;
408 case 3:
409 dialogs._indexList[count + 4] = NOUN_FORMALDEHYDE;
410 break;
411 default:
412 break;
413 }
414 }
415
416 _vm->_dialogs->show(401);
417 }
418
doObjectAction()419 void GameNebular::doObjectAction() {
420 Scene &scene = _scene;
421 MADSAction &action = _scene._action;
422 Dialogs &dialogs = *_vm->_dialogs;
423 int id;
424
425 if (action.isAction(VERB_SMELL) && scene._currentSceneId > 103 && scene._currentSceneId < 111) {
426 dialogs.show(440);
427 } else if (action.isAction(VERB_EAT) && scene._currentSceneId > 103 && scene._currentSceneId < 111) {
428 dialogs.show(441);
429 } else if (action.isAction(VERB_SMELL, NOUN_BURGER)) {
430 dialogs.show(442);
431 } else if (action.isAction(VERB_EAT, NOUN_BURGER)) {
432 dialogs.show(443);
433 } else if (action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) {
434 dialogs.show(444);
435 } else if (action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) {
436 dialogs.show(445);
437 } else if (action.isAction(VERB_WEAR, NOUN_REBREATHER)) {
438 dialogs.show(scene._currentSceneId > 103 && scene._currentSceneId < 111 ? 446 : 447);
439 } else if (action.isAction(VERB_SET, NOUN_TIMER_MODULE)) {
440 dialogs.show(448);
441 } else if (action.isAction(VERB_NIBBLE_ON, NOUN_BIG_LEAVES)) {
442 dialogs.show(449);
443 } else if (action.isAction(VERB_LICK, NOUN_POISON_DARTS)) {
444 dialogs.show(450);
445 } else if (action.isAction(VERB_EAT, NOUN_TWINKIFRUIT)) {
446 _objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE);
447 dialogs.show(451);
448 } else if (action.isAction(VERB_GORGE_ON, NOUN_TWINKIFRUIT)) {
449 _objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE);
450 dialogs.show(452);
451 } else if (action.isAction(VERB_GNAW_ON)) {
452 dialogs.show(453);
453 } else if (action.isAction(VERB_MASSAGE, NOUN_AUDIO_TAPE)) {
454 dialogs.show(454);
455 } else if (action.isAction(VERB_MANGLE, NOUN_CREDIT_CHIP)) {
456 dialogs.show(455);
457 } else if (action.isAction(VERB_FONDLE, NOUN_CHARGE_CASES)) {
458 dialogs.show(456);
459 } else if (action.isAction(VERB_RUB, NOUN_BOMB)) {
460 dialogs.show(457);
461 } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) {
462 dialogs.show(458);
463 } else if (action.isAction(VERB_GUZZLE, NOUN_ALIEN_LIQUOR)) {
464 dialogs.show(459);
465 } else if (action.isAction(VERB_SMASH, NOUN_TARGET_MODULE)) {
466 dialogs.show(460);
467 } else if (action.isAction(VERB_JUGGLE)) {
468 dialogs.show(461);
469 } else if (action.isAction(VERB_APPLY, NOUN_POLYCEMENT)) {
470 dialogs.show(462);
471 } else if (action.isAction(VERB_SNIFF, NOUN_POLYCEMENT)) {
472 dialogs.show(465);
473 } else if (action.isAction(VERB_TIE, NOUN_FISHING_LINE)) {
474 dialogs.show(463);
475 } else if (action.isAction(VERB_ATTACH, NOUN_FISHING_LINE)) {
476 dialogs.show(463);
477 } else if (action.isAction(VERB_UNLOCK)) {
478 dialogs.show(464);
479 } else if (action.isAction(VERB_REFLECT)) {
480 dialogs.show(466);
481 } else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) {
482 dialogs.show(467);
483 } else if (action.isAction(VERB_EAT, NOUN_CHICKEN_BOMB)) {
484 dialogs.show(469);
485 } else if (action.isAction(VERB_BREAK, NOUN_VASE)) {
486 dialogs.show(471);
487 } else if (action.isAction(VERB_SHAKE_HANDS, NOUN_GUARDS_ARM2)) {
488 dialogs.show(472);
489 } else if (action.isAction(VERB_READ, NOUN_LOG)) {
490 dialogs.show(473);
491 } else if (action.isAction(VERB_RUB, NOUN_BOMBS)) {
492 dialogs.show(474);
493 } else if (action.isAction(VERB_DRINK, NOUN_FORMALDEHYDE)) {
494 dialogs.show(475);
495 } else if (action.isAction(VERB_DRINK, NOUN_PETROX)) {
496 dialogs.show(476);
497 } else if (action.isAction(VERB_DRINK, NOUN_LECITHIN)) {
498 dialogs.show(477);
499 } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_PLANT_STALK) && _objects.isInInventory(OBJ_POISON_DARTS)
500 && _objects.isInInventory(OBJ_PLANT_STALK)) {
501 _objects.addToInventory(OBJ_BLOWGUN);
502 _objects.setRoom(OBJ_PLANT_STALK, NOWHERE);
503 _globals[kBlowgunStatus] = 0;
504 dialogs.showItem(OBJ_BLOWGUN, 809);
505 } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_BLOWGUN) && _objects.isInInventory(OBJ_POISON_DARTS)
506 && _objects.isInInventory(OBJ_BLOWGUN)) {
507 dialogs.show(433);
508 } else if (action.isAction(VERB_DEFACE) && action.isAction(VERB_FOLD) && action.isAction(VERB_MUTILATE)) {
509 dialogs.show(434);
510 } else if (action.isAction(VERB_SPINDLE)) {
511 dialogs.show(479);
512 } else if ((action.isAction(VERB_READ) || action.isAction(VERB_LOOK_AT) || action.isAction(VERB_LOOK)) &&
513 action.isObject(NOUN_NOTE) && _objects.isInInventory(OBJ_NOTE)) {
514 _objects.setRoom(OBJ_NOTE, NOWHERE);
515 _objects.addToInventory(OBJ_COMBINATION);
516 dialogs.showItem(OBJ_COMBINATION, 851);
517 } else if ((action.isAction(VERB_LOOK) || action.isAction(VERB_READ)) &&
518 ((id = _objects.getIdFromDesc(action._activeAction._objectNameId)) > 0 ||
519 (action._activeAction._indirectObjectId > 0 &&
520 (id = _objects.getIdFromDesc(action._activeAction._indirectObjectId)))) &&
521 _objects.isInInventory(id)) {
522 if (id == OBJ_REPAIR_LIST) {
523 dialogs._indexList[0] = _globals[kTeleporterCode + 7];
524 dialogs._indexList[1] = _globals[kTeleporterCode + 8];
525 dialogs._indexList[2] = _globals[kTeleporterCode + 6];
526 dialogs._indexList[3] = _globals[kTeleporterCode + 9];
527 dialogs._indexList[4] = _globals[kTeleporterCode + 0];
528 dialogs._indexList[5] = _globals[kTeleporterCode + 1];
529 dialogs._indexList[6] = _globals[kTeleporterCode + 4];
530 dialogs._indexList[7] = _globals[kTeleporterCode + 5];
531 dialogs._indexList[8] = _globals[kTeleporterCode + 2];
532
533 dialogs.showItem(id, 402);
534 } else {
535 int messageId = 800 + id;
536 if ((id == OBJ_CHARGE_CASES) && _objects[OBJ_CHARGE_CASES].getQuality(3) != 0) {
537 messageId = 860;
538 }
539
540 if (id == OBJ_TAPE_PLAYER && _objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER)
541 messageId = 867;
542
543 if (id == 32 && _objects[OBJ_FISHING_LINE]._roomNumber == 3)
544 messageId = 862;
545
546 if (id == OBJ_BOTTLE && _globals[kBottleStatus] != 0)
547 messageId = 862 + _globals[kBottleStatus];
548
549 if (id == OBJ_PHONE_HANDSET && _globals[kHandsetCellStatus])
550 messageId = 861;
551
552 dialogs.showItem(id, messageId);
553 }
554 } else if (action.isAction(VERB_PUT, NOUN_BURGER, NOUN_DEAD_FISH)) {
555 if (_objects.isInInventory(OBJ_BURGER) || _objects.isInInventory(OBJ_DEAD_FISH)) {
556 _objects.removeFromInventory(OBJ_DEAD_FISH, PLAYER_INVENTORY);
557 _objects.removeFromInventory(OBJ_BURGER, PLAYER_INVENTORY);
558 _objects.addToInventory(OBJ_STUFFED_FISH);
559 dialogs.showItem(OBJ_STUFFED_FISH, 803);
560 }
561 } else if (action.isAction(VERB_PUT, NOUN_AUDIO_TAPE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_AUDIO_TAPE) &&
562 _objects.isInInventory(OBJ_TAPE_PLAYER)) {
563 _objects.setRoom(OBJ_AUDIO_TAPE, OBJ_TAPE_PLAYER);
564 } else if (action.isAction(VERB_ACTIVATE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) {
565 if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) {
566 showRecipe();
567 } else {
568 dialogs.show(406);
569 }
570 } else if (action.isAction(VERB_EJECT, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) {
571 if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) {
572 _objects.addToInventory(OBJ_AUDIO_TAPE);
573 } else {
574 dialogs.show(407);
575 }
576 } else if (action.isAction(VERB_DISASSEMBLE, NOUN_TAPE_PLAYER)) {
577 dialogs.show(408);
578 } else if (action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) {
579 dialogs.show(_globals[kTopButtonPushed] ? 502 : 501);
580 } else if ((action.isAction(VERB_ATTACH, NOUN_DETONATORS, NOUN_CHARGE_CASES) || action.isAction(VERB_PUT, NOUN_DETONATORS, NOUN_CHARGE_CASES)) &&
581 _objects.isInInventory(OBJ_DETONATORS) && _objects.isInInventory(OBJ_CHARGE_CASES)) {
582 if (_objects[OBJ_CHARGE_CASES].getQuality(3)) {
583 _objects.setRoom(OBJ_CHARGE_CASES, NOWHERE);
584 _objects.setRoom(OBJ_DETONATORS, NOWHERE);
585 _objects.addToInventory(OBJ_BOMBS);
586 dialogs.showItem(OBJ_BOMBS, 403);
587 } else {
588 dialogs.show(405);
589 }
590 } else if (action.isAction(VERB_ATTACH, NOUN_DETONATORS)) {
591 dialogs.show(470);
592 } else if ((action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMB)
593 || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMB)) && _objects.isInInventory(OBJ_TIMER_MODULE) && (
594 _objects.isInInventory(OBJ_BOMBS) || _objects.isInInventory(OBJ_BOMB))) {
595 if (_objects.isInInventory(OBJ_BOMBS)) {
596 _objects.setRoom(OBJ_BOMBS, NOWHERE);
597 _objects.addToInventory(OBJ_BOMB);
598 } else {
599 _objects.setRoom(OBJ_BOMB, NOWHERE);
600 }
601
602 _objects.setRoom(OBJ_TIMER_MODULE, NOWHERE);
603 _objects.addToInventory(OBJ_TIMEBOMB);
604 dialogs.showItem(OBJ_TIMEBOMB, 404);
605 } else if (action.isAction(VERB_FONDLE, NOUN_PLANT_STALK)) {
606 dialogs.show(410);
607 } else if (action.isAction(VERB_EMPTY, NOUN_BOTTLE)) {
608 _globals[kBottleStatus] = 0;
609 dialogs.show(432);
610 } else if (action.isAction(VERB_DISASSEMBLE, NOUN_FISHING_ROD)) {
611 if (_objects[OBJ_FISHING_LINE]._roomNumber == 3) {
612 _objects.addToInventory(OBJ_FISHING_LINE);
613 dialogs.showItem(OBJ_FISHING_LINE, 409);
614 } else {
615 dialogs.show(428);
616 }
617 } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PENLIGHT)) {
618 switch (_globals[kPenlightCellStatus]) {
619 case 1:
620 case 2:
621 _objects.addToInventory(OBJ_DURAFAIL_CELLS);
622 dialogs.showItem(OBJ_DURAFAIL_CELLS, 412);
623 break;
624 case 3:
625 _objects.addToInventory(OBJ_PHONE_CELLS);
626 dialogs.showItem(OBJ_DURAFAIL_CELLS, 413);
627 break;
628 case 5:
629 _objects.addToInventory(OBJ_DURAFAIL_CELLS);
630 dialogs.showItem(OBJ_DURAFAIL_CELLS, 411);
631 break;
632 case 6:
633 _objects.addToInventory(OBJ_DURAFAIL_CELLS);
634 dialogs.showItem(OBJ_DURAFAIL_CELLS, 429);
635 break;
636 default:
637 dialogs.show(478);
638 break;
639 }
640 } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PHONE_HANDSET)) {
641 switch (_globals[kHandsetCellStatus]) {
642 case 1:
643 _objects.addToInventory(OBJ_DURAFAIL_CELLS);
644 dialogs.showItem(OBJ_DURAFAIL_CELLS,
645 _difficulty != DIFFICULTY_HARD || _globals[kDurafailRecharged] ? 415 : 414);
646 _globals[kDurafailRecharged] = true;
647 break;
648 case 2:
649 _objects.addToInventory(OBJ_DURAFAIL_CELLS);
650 if (_difficulty == DIFFICULTY_HARD) {
651 dialogs.showItem(OBJ_DURAFAIL_CELLS, 416);
652 }
653 _globals[kHandsetCellStatus] = 0;
654 break;
655 case 3:
656 _objects.addToInventory(OBJ_PHONE_CELLS);
657 dialogs.showItem(OBJ_PHONE_CELLS, 418);
658 break;
659 case 4:
660 _objects.addToInventory(OBJ_PHONE_CELLS);
661 dialogs.showItem(OBJ_PHONE_CELLS, 417);
662 _globals[kHandsetCellStatus] = 0;
663 break;
664 default:
665 dialogs.show(478);
666 break;
667 }
668 } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PENLIGHT)) {
669 if (_globals[kPenlightCellStatus] == 0) {
670 _globals[kPenlightCellStatus] = 3;
671 _objects.setRoom(OBJ_PHONE_CELLS, NOWHERE);
672 dialogs.show(419);
673 } else {
674 dialogs.show(420);
675 }
676 } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PHONE_HANDSET)) {
677 if (_globals[kHandsetCellStatus] == 0) {
678 _globals[kHandsetCellStatus] = 3;
679 _objects.setRoom(OBJ_PHONE_CELLS, NOWHERE);
680 dialogs.show(421);
681 } else {
682 dialogs.show(422);
683 }
684 } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PENLIGHT)) {
685 if (_globals[kPenlightCellStatus]) {
686 dialogs.show(424);
687 } else {
688 _objects.setRoom(OBJ_DURAFAIL_CELLS, NOWHERE);
689 _globals[kPenlightCellStatus] = _difficulty != DIFFICULTY_HARD || _globals[kDurafailRecharged] ? 1 : 2;
690 dialogs.show(423);
691 }
692 } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PHONE_HANDSET)) {
693 if (_globals[kHandsetCellStatus]) {
694 dialogs.show(426);
695 } else {
696 _objects.setRoom(OBJ_DURAFAIL_CELLS, NOWHERE);
697 _globals[kHandsetCellStatus] = _difficulty != DIFFICULTY_HARD || _globals[kHandsetCellStatus] ? 1 : 2;
698 dialogs.show(425);
699 }
700 } else if (action.isAction(VERB_PUT, NOUN_BOMB, NOUN_CHICKEN) || action.isAction(VERB_PUT, NOUN_BOMBS, NOUN_CHICKEN)) {
701 _objects.setRoom(OBJ_CHICKEN, NOWHERE);
702 if (_objects.isInInventory(OBJ_BOMBS)) {
703 _objects.setRoom(OBJ_BOMBS, NOWHERE);
704 _objects.addToInventory(OBJ_BOMB);
705 } else {
706 _objects.setRoom(OBJ_BOMB, NOWHERE);
707 }
708
709 _objects.addToInventory(OBJ_CHICKEN_BOMB);
710 dialogs.showItem(OBJ_CHICKEN_BOMB, 430);
711 } else {
712 return;
713 }
714
715 action._inProgress = false;
716 }
717
unhandledAction()718 void GameNebular::unhandledAction() {
719 int randVal = _vm->getRandomNumber(1, 1000);
720 MADSAction &action = _scene._action;
721
722 if (action.isAction(VERB_THROW, NOUN_BOMB) || action.isAction(VERB_THROW, NOUN_BOMBS)
723 || action.isAction(VERB_THROW, NOUN_TIMEBOMB) || action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB))
724 _vm->_dialogs->show(42);
725 else if (action.isAction(VERB_DISASSEMBLE))
726 _vm->_dialogs->show(435);
727 else if ((action.isAction(VERB_EAT, NOUN_DEAD_FISH) || action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId)))
728 _vm->_dialogs->show(12);
729 else if ((action.isAction(VERB_SMELL, NOUN_DEAD_FISH) || action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId)))
730 _vm->_dialogs->show(13);
731 else if (action.isAction(VERB_EAT, NOUN_CHICKEN) && _vm->_game->_objects.isInInventory(OBJ_CHICKEN))
732 _vm->_dialogs->show(912);
733 else if ((action.isAction(VERB_SHOOT) || action.isAction(VERB_HOSE_DOWN)) && action.isObject(NOUN_BLOWGUN)) {
734 if ((_scene._currentSceneId >= 104) && (_scene._currentSceneId <= 111))
735 _vm->_dialogs->show(38);
736 else if (action.isObject(NOUN_PIRANHA))
737 _vm->_dialogs->show(41);
738 else if (action.isObject(NOUN_CHICKEN) || action.isObject(NOUN_VULTURE) || action.isObject(NOUN_SPIDER)
739 || action.isObject(NOUN_YELLOW_BIRD) || action.isObject(NOUN_SWOOPING_CREATURE) || action.isObject(NOUN_CAPTIVE_CREATURE)) {
740 _vm->_dialogs->show(40);
741 } else
742 _vm->_dialogs->show(39);
743 } else if (action.isAction(VERB_TALKTO)) {
744 _globals[kTalkInanimateCount] = (_globals[kTalkInanimateCount] + 1) % 16;
745 if (!_globals[kTalkInanimateCount]) {
746 _vm->_dialogs->show(2);
747 } else {
748 Common::String tmpMsg = "\"Greetings, ";
749 tmpMsg += _vm->_game->_scene.getVocab(action._activeAction._objectNameId);
750 tmpMsg += "!\"";
751 _scene._kernelMessages.reset();
752 _scene._kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, tmpMsg);
753 }
754 } else if (action.isAction(VERB_GIVE, NOUN_DOOR, NOUN_CEILING) || action.isAction(VERB_CLOSE, NOUN_CHAIR))
755 _vm->_dialogs->show(3);
756 else if (action.isAction(VERB_THROW)) {
757 int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
758 if (objId < 0)
759 _vm->_dialogs->show(4);
760 else if (_vm->_game->_objects[objId]._roomNumber != 2)
761 _vm->_dialogs->show(5);
762 else
763 _vm->_dialogs->show(6);
764 } else if (action.isAction(VERB_LOOK)) {
765 if (action.isObject(NOUN_BINOCULARS) && (action._activeAction._indirectObjectId > 0))
766 _vm->_dialogs->show(10);
767 else if (randVal < 600)
768 _vm->_dialogs->show(7);
769 else
770 _vm->_dialogs->show(21);
771 } else if (action.isAction(VERB_TAKE)) {
772 int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
773 if (_vm->_game->_objects.isInInventory(objId))
774 _vm->_dialogs->show(16);
775 else if (randVal <= 333)
776 _vm->_dialogs->show(8);
777 else if (randVal <= 666)
778 _vm->_dialogs->show(22);
779 else
780 _vm->_dialogs->show(23);
781 } else if (action.isAction(VERB_CLOSE)) {
782 if (randVal <= 333)
783 _vm->_dialogs->show(9);
784 else
785 _vm->_dialogs->show(33);
786 } else if (action.isAction(VERB_OPEN)) {
787 if (randVal <= 500)
788 _vm->_dialogs->show(30);
789 else if (randVal <= 750)
790 _vm->_dialogs->show(31);
791 else
792 _vm->_dialogs->show(32);
793 } else if (action.isAction(VERB_PULL))
794 _vm->_dialogs->show(18);
795 else if (action.isAction(VERB_PUSH)) {
796 if (randVal < 750)
797 _vm->_dialogs->show(19);
798 else
799 _vm->_dialogs->show(20);
800 } else if (action.isAction(VERB_PUT)) {
801 int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
802 if (_vm->_game->_objects.isInInventory(objId))
803 _vm->_dialogs->show(25);
804 else
805 _vm->_dialogs->show(24);
806 } else if (action.isAction(VERB_GIVE)) {
807 int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId);
808 if (!_vm->_game->_objects.isInInventory(objId))
809 _vm->_dialogs->show(26);
810 else if (randVal <= 500)
811 _vm->_dialogs->show(28);
812 else
813 _vm->_dialogs->show(29);
814 } else if (!action.isAction(VERB_WALKTO) && !action.isAction(VERB_WALK_ACROSS) && !action.isAction(VERB_WALK_TOWARDS) && !action.isAction(VERB_WALK_DOWN)
815 && !action.isAction(VERB_SWIM_TO) && !action.isAction(VERB_SWIM_ACROSS) && !action.isAction(VERB_SWIM_INTO) && !action.isAction(VERB_SWIM_THROUGH)
816 && !action.isAction(VERB_SWIM_UNDER)) {
817 if (randVal <= 100)
818 _vm->_dialogs->show(36);
819 else if (randVal <= 200)
820 _vm->_dialogs->show(1);
821 else if (randVal <= 475)
822 _vm->_dialogs->show(34);
823 else if (randVal <= 750)
824 _vm->_dialogs->show(35);
825 else
826 _vm->_dialogs->show(37);
827 }
828 }
829
step()830 void GameNebular::step() {
831 if (_player._visible && _player._stepEnabled && !_player._moving &&
832 (_player._facing == _player._turnToFacing)) {
833 if (_scene._frameStartTime >= (uint32)_globals[kWalkerTiming]) {
834 if (_player._stopWalkers.empty()) {
835 int randomVal = _vm->getRandomNumber(29999);
836 if (_globals[kSexOfRex] == REX_MALE) {
837 switch (_player._facing) {
838 case FACING_SOUTHWEST:
839 case FACING_SOUTHEAST:
840 case FACING_NORTHWEST:
841 case FACING_NORTHEAST:
842 if (randomVal < 200) {
843 _player.addWalker(-1, 0);
844 _player.addWalker(1, 0);
845 }
846 break;
847
848 case FACING_WEST:
849 case FACING_EAST:
850 if (randomVal < 500) {
851 for (int count = 0; count < 10; ++count) {
852 _player.addWalker(1, 0);
853 }
854 }
855 break;
856
857 case FACING_SOUTH:
858 if (randomVal < 500) {
859 for (int count = 0; count < 10; ++count) {
860 _player.addWalker((randomVal < 250) ? 1 : 2, 0);
861 }
862 } else if (randomVal < 750) {
863 for (int count = 0; count < 5; ++count) {
864 _player.addWalker(1, 0);
865 }
866
867 _player.addWalker(0, 0);
868 _player.addWalker(0, 0);
869
870 for (int count = 0; count < 5; ++count) {
871 _player.addWalker(2, 0);
872 }
873 }
874 break;
875
876 default:
877 break;
878 }
879 }
880 }
881
882 _globals[kWalkerTiming] += 6;
883 }
884 }
885
886 // Below is countdown to set the timebomb off in room 604
887 if (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) {
888 int diff = _scene._frameStartTime - _globals[kTimebombClock];
889 if ((diff >= 0) && (diff <= 60))
890 _globals[kTimebombTimer] += diff;
891 else
892 ++_globals[kTimebombTimer];
893
894 _globals[kTimebombClock] = (int)_scene._frameStartTime;
895 }
896 }
897
synchronize(Common::Serializer & s,bool phase1)898 void GameNebular::synchronize(Common::Serializer &s, bool phase1) {
899 Game::synchronize(s, phase1);
900
901 if (phase1) {
902 _globals.synchronize(s);
903 s.syncAsByte(_storyMode);
904 s.syncAsByte(_difficulty);
905 }
906 }
907
908 } // End of namespace Nebular
909
910 } // End of namespace MADS
911