diff options
author | Matthew Stewart | 2018-05-30 21:06:31 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | fe5658ca175810f7ea6cbcaa078e6fc86faf36f1 (patch) | |
tree | a5e392c93e9acc72453d88d0782a8837b6ecdf81 /engines/startrek | |
parent | 1290b7ea0298dc6a565e2593ecb703710d051830 (diff) | |
download | scummvm-rg350-fe5658ca175810f7ea6cbcaa078e6fc86faf36f1.tar.gz scummvm-rg350-fe5658ca175810f7ea6cbcaa078e6fc86faf36f1.tar.bz2 scummvm-rg350-fe5658ca175810f7ea6cbcaa078e6fc86faf36f1.zip |
STARTREK: Mission 1 finished
Diffstat (limited to 'engines/startrek')
-rw-r--r-- | engines/startrek/awaymission.cpp | 9 | ||||
-rw-r--r-- | engines/startrek/awaymission.h | 8 | ||||
-rw-r--r-- | engines/startrek/menu.cpp | 11 | ||||
-rw-r--r-- | engines/startrek/room.cpp | 41 | ||||
-rw-r--r-- | engines/startrek/room.h | 41 | ||||
-rw-r--r-- | engines/startrek/rooms/demon1.cpp | 6 | ||||
-rw-r--r-- | engines/startrek/rooms/demon4.cpp | 498 | ||||
-rw-r--r-- | engines/startrek/rooms/function_map.h | 40 | ||||
-rw-r--r-- | engines/startrek/sprite.cpp | 7 | ||||
-rw-r--r-- | engines/startrek/sprite.h | 1 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 1 | ||||
-rw-r--r-- | engines/startrek/text.h | 2 |
12 files changed, 638 insertions, 27 deletions
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp index e0232009ff..4a604b9e7e 100644 --- a/engines/startrek/awaymission.cpp +++ b/engines/startrek/awaymission.cpp @@ -38,6 +38,7 @@ void StarTrekEngine::initAwayMission() { _sound->loadMusicFile("ground"); loadRoom(_missionToLoad, _roomIndexToLoad); + _roomIndexToLoad = -1; // Load crew positions for beaming in initAwayCrewPositions(4); @@ -45,6 +46,14 @@ void StarTrekEngine::initAwayMission() { void StarTrekEngine::runAwayMission() { while (true) { + // Original game manipulates the stack when the room changes to return execution + // to this point. Instead of doing that, just check if a variable is set. + if (_roomIndexToLoad != -1 && _spawnIndexToLoad != -1) { + loadRoomIndex(_roomIndexToLoad, _spawnIndexToLoad); + _roomIndexToLoad = -1; + _spawnIndexToLoad = -1; + } + handleAwayMissionEvents(); Common::Point mousePos = _gfx->getMousePos(); diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h index 0ad2946c23..5029c8cad1 100644 --- a/engines/startrek/awaymission.h +++ b/engines/startrek/awaymission.h @@ -55,6 +55,7 @@ struct AwayMission { struct { bool wasRudeToPrelate; // 0x29 bool insultedStephen; // 0x2b + bool field2d; // 0x2d bool beatKlingons; // 0x2f bool tookKlingonHand; // 0x31 @@ -75,17 +76,18 @@ struct AwayMission { byte field41; // 0x41 bool foundMiner; // 0x43 bool field45; // 0x45 - bool field47; // 0x47 + bool gaveSkullToNauian; // 0x47 bool warpsDisabled; // 0x48 bool boulder1Gone; // 0x49 bool boulder2Gone; // 0x4a bool boulder3Gone; // 0x4b bool boulder4Gone; // 0x4c bool doorOpened; // 0x4d - bool field4e; // 0x4e + bool solvedSunPuzzle; // 0x4e byte itemsTakenFromCase; // 0x4f bool gotBerries; // 0x50 bool madeHypoDytoxin; // 0x51 + bool metNauian; // 0x53 bool gavePointsForDytoxin; // 0x54 bool lookedAtComputer; // 0x55 byte field56; // 0x56 @@ -93,7 +95,7 @@ struct AwayMission { } demon; }; - int16 missionScore; + int16 missionScore; // 0x58 }; // Size: 0x129 bytes diff --git a/engines/startrek/menu.cpp b/engines/startrek/menu.cpp index d6929d0d5c..1f67fb288c 100644 --- a/engines/startrek/menu.cpp +++ b/engines/startrek/menu.cpp @@ -653,7 +653,6 @@ int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4 switch(event.type) { case TREKEVENT_TICK: { - case TREKEVENT_MOUSEMOVE: // FIXME: actual game only uses TICK event here Common::Point mousePos = _gfx->getMousePos(); int buttonIndex = getMenuButtonAt(_activeMenu->sprites, _activeMenu->numButtons, mousePos.x, mousePos.y); if (buttonIndex != -1) { @@ -676,11 +675,11 @@ int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4 } // Not added: updating mouse position (scummvm handles that) - // sub_10492(); - // sub_10A91(); + // sub_10492(); // TODO + // updateActorAnimations(); // TODO: uncomment and fix animations under textboxes _gfx->drawAllSprites(); - // sub_10BE7(); - // sub_2A4B1(); + // sub_10BE7(); // TODO + _sound->checkLoopMusic(); if (_finishedPlayingSpeech != 0) { _finishedPlayingSpeech = 0; @@ -688,7 +687,7 @@ int StarTrekEngine::handleMenuEvents(uint32 ticksUntilClickingEnabled, bool arg4 return TEXTBUTTON_SPEECH_DONE; } } - // sub_1E88C(); + _gfx->incPaletteFadeLevel(); _frameIndex++; if (ticksUntilClickingEnabled != 0 && _clockTicks >= tickWhenClickingEnabled) diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp index 7110c4d559..2a8f5e6c6f 100644 --- a/engines/startrek/room.cpp +++ b/engines/startrek/room.cpp @@ -236,17 +236,24 @@ void Room::loadRoomIndex(int roomIndex, int spawnIndex) { if (_vm->_awayMission.crewDownBitset != 0) return; - _vm->loadRoomIndex(roomIndex, spawnIndex); + _vm->_missionToLoad = _vm->_missionName; + _vm->_roomIndexToLoad = roomIndex; + _vm->_spawnIndexToLoad = spawnIndex; - // This room has now been deleted, don't do anything else here. - // FIXME: this could a bit dangerous since this is generally called from room-specific - // code, which isn't guaranteed to do nothing afterward. Original game would - // manipulate the stack to jump directly back to the start of "runAwayMission"... + // WORKAROUND: original game manipulates the stack to return directly to the start of + // "runAwayMission". Instead, we set some variables and the room will be changed + // later. (We wouldn't want to delete the room we're currently in...) } void Room::loseItem(int item) { assert(item >= ITEMS_START && item < ITEMS_END); _vm->_itemList[item - ITEMS_START].have = false; + + if (_vm->_awayMission.activeAction == ACTION_USE && _vm->_awayMission.activeObject == item) { + _vm->_awayMission.activeAction = ACTION_WALK; + _vm->chooseMouseBitmapForAction(ACTION_WALK, false); + _vm->hideInventoryIcons(); + } } void Room::walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 finishedAnimActionParam) { @@ -286,6 +293,30 @@ void Room::playMidiMusicTracks(int startTrack, int loopTrack) { _vm->playMidiMusicTracks(startTrack, loopTrack); } +void Room::endMission(int16 score, int16 arg1, int16 arg2) { + _vm->_awayMission.disableInput = true; + + for (int i = 0; i < (_vm->_awayMission.redshirtDead ? 3 : 4); i++) { + Actor *actor = &_vm->_actorList[i]; + Common::String anim = _vm->getCrewmanAnimFilename(i, "teled"); + _vm->loadActorAnimWithRoomScaling(i, anim, actor->sprite.pos.x, actor->sprite.pos.y); + } + + _vm->_kirkActor->animationString[0] = '\0'; + _vm->_spockActor->animationString[0] = '\0'; + _vm->_mccoyActor->animationString[0] = '\0'; + _vm->_redshirtActor->animationString[0] = '\0'; + + playSoundEffectIndex(8); + + while (_vm->_kirkActor->spriteDrawn) + _vm->handleAwayMissionEvents(); + + _vm->_awayMission.disableInput = false; + + // TODO: game mode switch +} + void Room::showGameOverMenu() { _vm->showGameOverMenu(); } diff --git a/engines/startrek/room.h b/engines/startrek/room.h index 027dbd6ae5..4dd6e05d71 100644 --- a/engines/startrek/room.h +++ b/engines/startrek/room.h @@ -103,6 +103,7 @@ private: int showText(int speaker, int text); // Cmd 0x03 int showText(int text); // Cmd 0x03 void giveItem(int item); // Cmd 0x04 + // Command 0x05: "demon4ShowSunPuzzle" void loadRoomIndex(int roomIndex, int spawnIndex); // Cmd 0x06 void loseItem(int item); // Cmd 0x07 void walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 finishedAnimActionParam);// Cmd 0x08 @@ -111,6 +112,7 @@ private: Common::Point getActorPos(int actorIndex); // Cmd 0x0d void playSoundEffectIndex(int soundEffect); // Cmd 0x0f void playMidiMusicTracks(int startTrack, int loopTrack); // Cmd 0x10 + void endMission(int16 score, int16 arg2, int16 arg3); // Cmd 0x11 void showGameOverMenu(); // Cmd 0x12 void playVoc(Common::String filename); // Cmd 0x15 @@ -310,9 +312,26 @@ public: void demon4FinishedAnimation1(); void demon4FinishedAnimation2(); void demon4FinishedAnimation3(); + void demon4Timer0Expired(); + void demon4Timer1Expired(); + void demon4CrewmanReachedBeamoutPosition(); + void demon4Timer2Expired(); + void demon4Timer3Expired(); + void demon4Timer4Expired(); + void demon4Timer5Expired(); + void demon4Timer6Expired(); + void demon4UsePhaserOnNauian(); + void demon4UseMetalOnSecurityEquipment(); + void demon4KirkReachedSecurityEquipment(); + void demon4KirkFinishedUsingSecurityEquipment(); + void demon4UseMetalOnNauian(); + void demon4KirkReachedNauian(); + void demon4UseSkullOnNauian(); + void demon4KirkReachedNauianWithSkull(); void demon4UsePhaserOnPanel(); void demon4UsePhaserOnPattern(); void demon4UsePhaserOnMccoy(); + void demon4TalkToNauian(); void demon4LookAtPattern(); void demon4LookAtAlien(); void demon4LookAnywhere(); @@ -330,6 +349,22 @@ public: void demon4UseRedshirtOnPanel(); void demon4UseCrewmanOnPanel(); void demon4CrewmanReachedPanel(); + bool demon4ShowSunPuzzle(); + void demon4TalkToKirk(); + void demon4TalkToMccoy(); + void demon4TalkToSpock(); + void demon4TalkToRedshirt(); + void demon4UseSTricorderOnChamber(); + void demon4UseSTricorderOnPattern(); + void demon4UseMTricorderOnPattern(); + void demon4UseSTricorderOnPanel(); + void demon4UseMTricorderOnPanel(); + void demon4UseSTricorderOnAnything(); + void demon4UseMTricorderOnAnything(); + void demon4UseSTricorderOnNauian(); + void demon4UseMTricorderOnNauian(); + void demon4UseSTricorderOnSecurityEquipment(); + void demon4UseMTricorderOnSecurityEquipment(); // DEMON5 void demon5Tick1(); @@ -461,7 +496,11 @@ private: } demon3; struct { - bool cb; // 0xcb + bool triedToShootNauian; // 0xca + bool nauianEmerged; // 0xcb + bool disabledSecurity; // 0xcc + bool cd; // 0xcd + byte crewReadyToBeamOut; // 0xce int16 crewmanUsingPanel; // 0xcf } demon4; diff --git a/engines/startrek/rooms/demon1.cpp b/engines/startrek/rooms/demon1.cpp index 325f13c843..a5c42d33d0 100644 --- a/engines/startrek/rooms/demon1.cpp +++ b/engines/startrek/rooms/demon1.cpp @@ -381,8 +381,10 @@ void Room::demon1UseSTricorderOnHand() { } void Room::demon1UseSTricorderOnKlingon1() { - // NOTE: it sets up the stack, but doesn't call the function... - //loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0); + // BUGFIX: Original game sets up the stack for this function call, but doesn't + // actually call the function... + loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0); + playSoundEffectIndex(0x04); if (_roomVar.demon1.numKlingonsKilled == 3 && !_vm->_awayMission.demon.tookKlingonHand && _rdfData[0xcf] != 1) { diff --git a/engines/startrek/rooms/demon4.cpp b/engines/startrek/rooms/demon4.cpp index 52286327ea..8f2e310c9e 100644 --- a/engines/startrek/rooms/demon4.cpp +++ b/engines/startrek/rooms/demon4.cpp @@ -24,18 +24,21 @@ namespace StarTrek { +// TODO: this room should have animations on computer terminals, but this isn't where +// they're implemented. Could be related to ".BAN" files which rooms can load? + void Room::demon4Tick1() { playVoc("DEM4LOOP"); if (!_vm->_awayMission.demon.healedMiner) _vm->_awayMission.demon.minerDead = true; - if (_vm->_awayMission.demon.field4e) { + if (_vm->_awayMission.demon.solvedSunPuzzle) { loadActorAnim(10, "bxrise2", 0x122, 0x91, 0); loadActorAnim(8, "stpout2", 0x107, 0x92, 0); - _roomVar.demon4.cb = true; + _roomVar.demon4.nauianEmerged = true; - if ((_vm->_awayMission.demon.itemsTakenFromCase & 0x10) && !_vm->_awayMission.demon.field47) + if ((_vm->_awayMission.demon.itemsTakenFromCase & 0x10) && !_vm->_awayMission.demon.gaveSkullToNauian) _vm->_awayMission.timers[6] = 20; } @@ -45,14 +48,164 @@ void Room::demon4Tick1() { } } +// Alien emerged void Room::demon4FinishedAnimation1() { - // TODO + loadActorAnim(8, "stpout", 0x107, 0x92, 5); + _roomVar.demon4.nauianEmerged = true; + if (_vm->_awayMission.demon.itemsTakenFromCase & 0x10) + _vm->_awayMission.timers[6] = 45; } void Room::demon4FinishedAnimation2() { + if (!_roomVar.demon4.cd) { + _roomVar.demon4.cd = true; + showText(TX_DEM4N011); + } + + showGameOverMenu(); + + // WORKAROUND: original game has the below line; however, it's never executed anyway + // since the game over menu manipulates the stack. Here, the menu could delete this + // room object, so it should be the last statement... + //_vm->_awayMission.disableInput = false; } void Room::demon4FinishedAnimation3() { + showText(TX_SPEAKER_NAUIAN, TX_DEM4_034); + showText(TX_SPEAKER_KIRK, TX_DEM4_010); + showText(TX_SPEAKER_NAUIAN, TX_DEM4_035); + showText(TX_SPEAKER_SPOCK, TX_DEM4_030); + + _vm->_awayMission.disableInput = true; + _vm->_awayMission.missionScore += 5; + _vm->_awayMission.timers[1] = 20; +} + +// Just solved sun puzzle +void Room::demon4Timer0Expired() { + loadActorAnim(10, "bxrise", 0x122, 0x91, 1); + _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_E; + loadActorStandAnim(OBJECT_KIRK); + playVoc("SE2POWER"); +} + +// Mission end +void Room::demon4Timer1Expired() { + showText(TX_SPEAKER_KIRK, TX_DEM4_011); + + walkCrewman(OBJECT_KIRK, 0xbe, 0xa5, 4); + walkCrewman(OBJECT_SPOCK, 0xb4, 0x9b, 4); + walkCrewman(OBJECT_MCCOY, 0xc8, 0x9b, 4); + + if (!_vm->_awayMission.redshirtDead) + walkCrewman(OBJECT_REDSHIRT, 0xc1, 0x91, 4); + else + _roomVar.demon4.crewReadyToBeamOut++; +} + +void Room::demon4CrewmanReachedBeamoutPosition() { + _roomVar.demon4.crewReadyToBeamOut++; + if (_roomVar.demon4.crewReadyToBeamOut != 4) + return; + + if (!_vm->_awayMission.demon.insultedStephen) + _vm->_awayMission.missionScore += 3; + if (!_vm->_awayMission.redshirtDead) + _vm->_awayMission.missionScore += 2; + + endMission(_vm->_awayMission.missionScore, 0x24, 0); +} + +void Room::demon4Timer2Expired() { + loadActorAnim2(OBJECT_SPOCK, "skille", -1, -1, 0); +} + +void Room::demon4Timer3Expired() { + loadActorAnim2(OBJECT_REDSHIRT, "rkille", -1, -1, 0); +} + +void Room::demon4Timer4Expired() { + loadActorAnim2(OBJECT_MCCOY, "mkille", -1, -1, 0); +} + +void Room::demon4Timer5Expired() { + loadActorAnim2(OBJECT_KIRK, "kkille", -1, -1, 2); +} + +void Room::demon4Timer6Expired() { + showText(TX_SPEAKER_MCCOY, TX_DEM4_017); +} + +void Room::demon4UsePhaserOnNauian() { + if (!_roomVar.demon4.triedToShootNauian) { // Lenient the first time + showText(TX_SPEAKER_NAUIAN, TX_DEM4_033); + _roomVar.demon4.triedToShootNauian = true; + } + else { // Murdery the second time + showText(TX_SPEAKER_NAUIAN, TX_DEM4_032); + loadActorAnim2(10, "bxfire", 0, 0, 2); + playVoc("V0SPOCKT"); + _vm->_awayMission.disableInput = true; + _vm->_awayMission.timers[2] = 7; + _vm->_awayMission.timers[3] = 8; + _vm->_awayMission.timers[4] = 7; + _vm->_awayMission.timers[5] = 8; + } +} + +void Room::demon4UseMetalOnSecurityEquipment() { + _vm->_awayMission.disableInput = true; + walkCrewman(OBJECT_KIRK, 0xf5, 0x90, 5); +} + +void Room::demon4KirkReachedSecurityEquipment() { + loadActorAnim2(OBJECT_KIRK, "kusemn", -1, -1, 4); +} + +void Room::demon4KirkFinishedUsingSecurityEquipment() { + _vm->_awayMission.disableInput = false; + showText(TX_DEM4N014); +} + +void Room::demon4UseMetalOnNauian() { + walkCrewman(OBJECT_KIRK, 0xe9, 0x90, 1); + _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_E; +} + +void Room::demon4KirkReachedNauian() { + loadActorAnim2(8, "usekey", 0x107, 0x8e, 3); + loseItem(OBJECT_IMETAL); + _vm->_awayMission.missionScore += 2; + _vm->_awayMission.demon.itemsTakenFromCase &= ~1; +} + +void Room::demon4UseSkullOnNauian() { + walkCrewman(OBJECT_KIRK, 0xe9, 0x90, 2); +} + +void Room::demon4KirkReachedNauianWithSkull() { + showText(TX_SPEAKER_NAUIAN, TX_DEM4_036); + + const int choices[] = { TX_SPEAKER_KIRK, TX_DEM4_006, TX_DEM4_003, TX_DEM4_005, TX_BLANK }; + int choice = showText(choices); + + switch (choice) { + case 0: + _vm->_awayMission.missionScore++; + loadActorAnim2(8, "takesk", 0x107, 0x8e, 0); + loseItem(OBJECT_ISKULL); + _vm->_awayMission.demon.itemsTakenFromCase &= ~16; // BUG: skull reappears in case? Can abuse for infinite ponits? + _vm->_awayMission.demon.gaveSkullToNauian = true; + break; + + case 1: + case 2: + break; + + default: + showText(TX_DIALOG_ERROR); + break; + } } void Room::demon4UsePhaserOnPanel() { @@ -67,9 +220,77 @@ void Room::demon4UsePhaserOnMccoy() { showText(TX_SPEAKER_MCCOY, TX_DEM4_018); } +void Room::demon4TalkToNauian() { + _vm->_awayMission.disableInput = false; + + if (!_vm->_awayMission.demon.metNauian) { + _vm->_awayMission.demon.metNauian = true; + showText(TX_SPEAKER_NAUIAN, TX_DEM4_044); + + const int choices[] = { TX_SPEAKER_KIRK, TX_DEM4_002, TX_DEM4_004, TX_DEM4_009, TX_BLANK }; + int choice = showText(choices); + + switch (choice) { + case 0: + _vm->_awayMission.demon.field2d = true; + showText(TX_SPEAKER_NAUIAN, TX_DEM4_042); + break; + + case 1: + break; + + case 2: + showText(TX_SPEAKER_NAUIAN, TX_DEM4_039); + break; + + default: + showText(TX_DIALOG_ERROR); + break; + } + + showText(TX_SPEAKER_NAUIAN, TX_DEM4_043); + + const int choices2[] = { TX_SPEAKER_KIRK, TX_DEM4_008, TX_DEM4_007, TX_BLANK }; + choice = showText(choices2); + + switch (choice) { + case 0: + _vm->_awayMission.demon.field2d = true; + showText(TX_SPEAKER_NAUIAN, TX_DEM4_041); + break; + case 1: + break; + default: + showText(TX_DIALOG_ERROR); + break; + } + + showText(TX_SPEAKER_NAUIAN, TX_DEM4_040); + + if (_roomVar.demon4.disabledSecurity) { // Impossible condition? + showText(TX_SPEAKER_NAUIAN, TX_DEM4_037); + + // BUGFIX: Originally all of these used no audio, despite the files existing + // (being used elsewhere). + showText(TX_SPEAKER_KIRK, TX_DEM4_010); + showText(TX_SPEAKER_NAUIAN, TX_DEM4_035); + showText(TX_SPEAKER_SPOCK, TX_DEM4_030); + + _vm->_awayMission.disableInput = true; + _vm->_awayMission.missionScore += 5; + _vm->_awayMission.timers[1] = 20; + } + else { + showText(TX_SPEAKER_NAUIAN, TX_DEM4_038); + } + } + else { + showText(TX_SPEAKER_NAUIAN, TX_DEM4_031); + } +} + void Room::demon4LookAtPattern() { showText(TX_DEM4N002); - } void Room::demon4LookAtAlien() { @@ -133,7 +354,7 @@ void Room::demon4UseRedshirtOnPanel() { } void Room::demon4UseCrewmanOnPanel() { - if (_vm->_awayMission.demon.field4e) + if (_vm->_awayMission.demon.solvedSunPuzzle) return; walkCrewman(_roomVar.demon4.crewmanUsingPanel, 0xda, 0x83, 3); _vm->_awayMission.crewDirectionsAfterWalk[_roomVar.demon4.crewmanUsingPanel] = DIR_N; @@ -141,7 +362,270 @@ void Room::demon4UseCrewmanOnPanel() { } void Room::demon4CrewmanReachedPanel() { - // TODO: puzzle implementation + if (demon4ShowSunPuzzle()) { + _vm->_awayMission.demon.solvedSunPuzzle = true; + loadActorAnim(9, "ctrl", 0, 0, 0); + _vm->_awayMission.missionScore += 3; + _vm->_awayMission.timers[0] = 10; + } + else + showText(TX_DEM4N013); + + walkCrewman(_roomVar.demon4.crewmanUsingPanel, 0xae, 0x93, 0); + _vm->_awayMission.disableInput = false; +} + +bool Room::demon4ShowSunPuzzle() { + bool solved = false; + + int sliderY = 17; + int sliderR = -17; + int sliderB = 17; + + _vm->_gfx->fadeoutScreen(); + _vm->_sound->stopAllVocSounds(); + + _vm->_gfx->pushSprites(); + _vm->_gfx->setBackgroundImage(_vm->_gfx->loadBitmap("machineb")); + _vm->_gfx->copyBackgroundScreen(); + _vm->_gfx->clearPri(); + + Sprite sprites[21]; + + for (int i = 0; i < 21; i++) { + _vm->_gfx->addSprite(&sprites[i]); + } + + sprites[0].setBitmap(_vm->_gfx->loadBitmap("levery")); + sprites[1].setBitmap(_vm->_gfx->loadBitmap("leverr")); + sprites[2].setBitmap(_vm->_gfx->loadBitmap("leverb")); + + SharedPtr<Bitmap> lightyBitmap = _vm->_gfx->loadBitmap("lighty"); + SharedPtr<Bitmap> lightrBitmap = _vm->_gfx->loadBitmap("lightr"); + SharedPtr<Bitmap> lightbBitmap = _vm->_gfx->loadBitmap("lightb"); + + for (int i = 3; i < 9; i++) + sprites[i].bitmap = lightyBitmap; + for (int i = 9; i < 15; i++) + sprites[i].bitmap = lightrBitmap; + for (int i = 15; i < 21; i++) + sprites[i].bitmap = lightbBitmap; + + Sprite doneButtonSprite; + _vm->_gfx->addSprite(&doneButtonSprite); + doneButtonSprite.setXYAndPriority(0x104, 0x64, 2); + doneButtonSprite.setBitmap(_vm->_gfx->loadBitmap("donebutt")); + // BUGFIX: use draw mode 2 so the entire button is clickable (not just non-transparent + // pixels) + doneButtonSprite.drawMode = 2; + + _vm->_gfx->fadeinScreen(); + + bool continueLoop = true; + bool sliderChanged = true; + + while (continueLoop) { + if (sliderChanged) { + sprites[0].setXYAndPriority(0xa0, sliderY + 0x75, 14); + sprites[1].setXYAndPriority(0xa8, sliderR + 0x75, 14); + sprites[2].setXYAndPriority(0xb0, sliderB + 0x75, 14); + + int var56 = 0x82; + int var58 = 0x83; + int var5a = 3; + int numSprites = abs(sliderY) / 3; + for (int i = 0; i < 6; i++) { + sprites[i + var5a].setXYAndPriority(var58, var56, 14); + } + var56 -= 6; + for (int i = 0; i < numSprites; i++) { + sprites[i + var5a].setXYAndPriority(var58, var56, 14); + var56 -= 6; + } + + var56 = 0x82; + var58 = 0x8b; + var5a = 9; + numSprites = abs(sliderR) / 3; + for (int i = 0; i < 6; i++) { + sprites[i + var5a].setXYAndPriority(var58, var56, 14); + } + var56 -= 6; + for (int i = 0; i < numSprites; i++) { + sprites[i + var5a].setXYAndPriority(var58, var56, 14); + var56 -= 6; + } + + var56 = 0x82; + var58 = 0x93; + var5a = 15; + numSprites = abs(sliderB) / 3; + for (int i = 0; i < 6; i++) { + sprites[i + var5a].setXYAndPriority(var58, var56, 14); + } + var56 -= 6; + for (int i = 0; i < numSprites; i++) { + sprites[i + var5a].setXYAndPriority(var58, var56, 14); + var56 -= 6; + } + + sliderChanged = false; + } + + TrekEvent event; + if (!_vm->popNextEvent(&event)) + continue; + + switch (event.type) { + case TREKEVENT_LBUTTONDOWN: { +lclick: + Common::Point mousePos = _vm->_gfx->getMousePos(); + if (_vm->_gfx->getSpriteAt(mousePos) == &doneButtonSprite) + goto done; + else { + if (mousePos.y >= 0x64 && mousePos.y <= 0x86) { + if (mousePos.x >= 0xa0 && mousePos.x <= 0xa6) + sliderY = mousePos.y - 0x75; + else if (mousePos.x >= 0xa8 && mousePos.x <= 0xae) + sliderR = mousePos.y - 0x75; + else if (mousePos.x >= 0xb0 && mousePos.x <= 0xb6) + sliderB = mousePos.y - 0x75; + sliderChanged = true; + } + } + break; + } + + case TREKEVENT_RBUTTONDOWN: +done: + if (abs(sliderY) <= 2 && abs(sliderR) <= 2 && abs(sliderB) <= 2) + solved = true; + else + solved = false; + continueLoop = false; + break; + + case TREKEVENT_KEYDOWN: + switch (event.kbd.keycode) { + case Common::KEYCODE_ESCAPE: + case Common::KEYCODE_F2: + goto done; + + case Common::KEYCODE_RETURN: + case Common::KEYCODE_KP_ENTER: + case Common::KEYCODE_F1: + goto lclick; + + default: + break; + } + break; + + default: + break; + } + + _vm->_gfx->drawAllSprites(); + } + + _vm->_gfx->fadeoutScreen(); + _vm->_gfx->popSprites(); + _vm->_gfx->loadPri(_vm->_screenName); + _vm->_gfx->setBackgroundImage(_vm->_gfx->loadBitmap(_vm->_screenName)); + _vm->_gfx->copyBackgroundScreen(); + _vm->_gfx->forceDrawAllSprites(); + + return solved; +} + +void Room::demon4TalkToKirk() { + showText(TX_SPEAKER_KIRK, TX_DEM4_001); +} + +void Room::demon4TalkToMccoy() { + if (_roomVar.demon4.nauianEmerged) + showText(TX_SPEAKER_MCCOY, TX_DEM4_019); + else + showText(TX_SPEAKER_MCCOY, TX_DEM4_015); +} + +void Room::demon4TalkToSpock() { + if (_roomVar.demon4.nauianEmerged) + showText(TX_SPEAKER_SPOCK, TX_DEM4_022); + else + showText(TX_SPEAKER_SPOCK, TX_DEM4_024); +} + +void Room::demon4TalkToRedshirt() { + if (_roomVar.demon4.nauianEmerged) + showText(TX_SPEAKER_EVERTS, TX_DEM4_047); + else + showText(TX_SPEAKER_EVERTS, TX_DEM4_046); +} + +void Room::demon4UseSTricorderOnChamber() { + loadActorAnim2(OBJECT_SPOCK, "sscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_012); +} + +void Room::demon4UseSTricorderOnPattern() { + loadActorAnim2(OBJECT_SPOCK, "sscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_014); + showText(TX_SPEAKER_SPOCK, TX_DEM4_025); +} + +void Room::demon4UseMTricorderOnPattern() { + showText(TX_SPEAKER_MCCOY, TX_DEM4_021); +} + +void Room::demon4UseSTricorderOnPanel() { + loadActorAnim2(OBJECT_SPOCK, "sscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_027); +} + +void Room::demon4UseMTricorderOnPanel() { + loadActorAnim2(OBJECT_MCCOY, "mscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_MCCOY, TX_DEM4_027); // BUG: Uses spock's voice (though speaker says "Mccoy") +} + +void Room::demon4UseSTricorderOnAnything() { + loadActorAnim2(OBJECT_SPOCK, "sscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_023); +} + +void Room::demon4UseMTricorderOnAnything() { + loadActorAnim2(OBJECT_MCCOY, "mscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_MCCOY, TX_DEM4_020); +} + +void Room::demon4UseSTricorderOnNauian() { + loadActorAnim2(OBJECT_SPOCK, "sscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_029); +} + +void Room::demon4UseMTricorderOnNauian() { + loadActorAnim2(OBJECT_MCCOY, "mscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_029); // BUG: Uses spock's voice (speaker says "Spock" too) +} + +void Room::demon4UseSTricorderOnSecurityEquipment() { + loadActorAnim2(OBJECT_SPOCK, "sscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_026); +} + +void Room::demon4UseMTricorderOnSecurityEquipment() { + loadActorAnim2(OBJECT_MCCOY, "mscane", -1, -1, 0); + playSoundEffectIndex(4); + showText(TX_SPEAKER_SPOCK, TX_DEM4_026); // BUG: Uses spock's voice (speaker says "Spock" too) } } diff --git a/engines/startrek/rooms/function_map.h b/engines/startrek/rooms/function_map.h index fc5f73a28b..db647df41e 100644 --- a/engines/startrek/rooms/function_map.h +++ b/engines/startrek/rooms/function_map.h @@ -314,14 +314,31 @@ RoomAction demon4ActionList[] = { { Action(ACTION_FINISHED_ANIMATION, 1, 0, 0), &Room::demon4FinishedAnimation1 }, { Action(ACTION_FINISHED_ANIMATION, 2, 0, 0), &Room::demon4FinishedAnimation2 }, { Action(ACTION_FINISHED_ANIMATION, 3, 0, 0), &Room::demon4FinishedAnimation3 }, - - // TODO: everything + { Action(ACTION_TIMER_EXPIRED, 0, 0, 0), &Room::demon4Timer0Expired }, + { Action(ACTION_TIMER_EXPIRED, 1, 0, 0), &Room::demon4Timer1Expired }, + { Action(ACTION_FINISHED_WALKING, 4, 0, 0), &Room::demon4CrewmanReachedBeamoutPosition }, + { Action(ACTION_TIMER_EXPIRED, 2, 0, 0), &Room::demon4Timer2Expired }, + { Action(ACTION_TIMER_EXPIRED, 3, 0, 0), &Room::demon4Timer3Expired }, + { Action(ACTION_TIMER_EXPIRED, 4, 0, 0), &Room::demon4Timer4Expired }, + { Action(ACTION_TIMER_EXPIRED, 5, 0, 0), &Room::demon4Timer5Expired }, + { Action(ACTION_TIMER_EXPIRED, 6, 0, 0), &Room::demon4Timer6Expired }, + + { Action(ACTION_USE, OBJECT_IPHASERK, 8, 0), &Room::demon4UsePhaserOnNauian }, + { Action(ACTION_USE, OBJECT_IPHASERS, 8, 0), &Room::demon4UsePhaserOnNauian }, + { Action(ACTION_USE, OBJECT_IMETAL, 0x22, 0), &Room::demon4UseMetalOnSecurityEquipment }, + { Action(ACTION_FINISHED_WALKING, 5, 0, 0), &Room::demon4KirkReachedSecurityEquipment }, + { Action(ACTION_FINISHED_ANIMATION, 4, 0, 0), &Room::demon4KirkFinishedUsingSecurityEquipment }, + { Action(ACTION_USE, OBJECT_IMETAL, 8, 0), &Room::demon4UseMetalOnNauian }, + { Action(ACTION_FINISHED_WALKING, 1, 0, 0), &Room::demon4KirkReachedNauian }, + { Action(ACTION_USE, OBJECT_ISKULL, 8, 0), &Room::demon4UseSkullOnNauian }, + { Action(ACTION_FINISHED_WALKING, 2, 0, 0), &Room::demon4KirkReachedNauianWithSkull }, { Action(ACTION_USE, OBJECT_IPHASERS, 0x21, 0), &Room::demon4UsePhaserOnPanel }, { Action(ACTION_USE, OBJECT_IPHASERS, 0x20, 0), &Room::demon4UsePhaserOnPattern }, { Action(ACTION_USE, OBJECT_IPHASERS, OBJECT_MCCOY, 0), &Room::demon4UsePhaserOnMccoy }, - // TODO + { Action(ACTION_FINISHED_ANIMATION, 5, 0, 0), &Room::demon4TalkToNauian }, + { Action(ACTION_TALK, 8, 0, 0), &Room::demon4TalkToNauian }, { Action(ACTION_LOOK, 0x20, 0, 0), &Room::demon4LookAtPattern }, { Action(ACTION_LOOK, 8, 0, 0), &Room::demon4LookAtAlien }, @@ -342,6 +359,23 @@ RoomAction demon4ActionList[] = { { Action(ACTION_USE, OBJECT_MCCOY, 0x21, 0), &Room::demon4UseMccoyOnPanel }, { Action(ACTION_USE, OBJECT_REDSHIRT, 0x21, 0), &Room::demon4UseRedshirtOnPanel }, { Action(ACTION_FINISHED_WALKING, 3, 0, 0), &Room::demon4CrewmanReachedPanel }, + { Action(ACTION_TALK, OBJECT_KIRK, 0, 0), &Room::demon4TalkToKirk }, + { Action(ACTION_TALK, OBJECT_MCCOY, 0, 0), &Room::demon4TalkToMccoy }, + { Action(ACTION_TALK, OBJECT_SPOCK, 0, 0), &Room::demon4TalkToSpock }, + { Action(ACTION_TALK, OBJECT_REDSHIRT, 0, 0), &Room::demon4TalkToRedshirt }, + { Action(ACTION_USE, OBJECT_ISTRICOR, 10, 0), &Room::demon4UseSTricorderOnChamber }, + { Action(ACTION_USE, OBJECT_ISTRICOR, 0x20, 0), &Room::demon4UseSTricorderOnPattern }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 0x20, 0), &Room::demon4UseMTricorderOnPattern }, + { Action(ACTION_USE, OBJECT_ISTRICOR, 0x21, 0), &Room::demon4UseSTricorderOnPanel }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 0x21, 0), &Room::demon4UseMTricorderOnPanel }, + { Action(ACTION_USE, OBJECT_ISTRICOR, 0x23, 0), &Room::demon4UseSTricorderOnAnything }, + { Action(ACTION_USE, OBJECT_ISTRICOR, -1, 0), &Room::demon4UseSTricorderOnAnything }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 0x23, 0), &Room::demon4UseMTricorderOnAnything }, + { Action(ACTION_USE, OBJECT_IMTRICOR, -1, 0), &Room::demon4UseMTricorderOnAnything }, + { Action(ACTION_USE, OBJECT_ISTRICOR, 8, 0), &Room::demon4UseSTricorderOnNauian }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 8, 0), &Room::demon4UseMTricorderOnNauian }, + { Action(ACTION_USE, OBJECT_ISTRICOR, 0x22, 0), &Room::demon4UseSTricorderOnSecurityEquipment }, + { Action(ACTION_USE, OBJECT_IMTRICOR, 0x22, 0), &Room::demon4UseMTricorderOnSecurityEquipment }, }; RoomAction demon5ActionList[] = { diff --git a/engines/startrek/sprite.cpp b/engines/startrek/sprite.cpp index 580447501c..f6ba48de9d 100644 --- a/engines/startrek/sprite.cpp +++ b/engines/startrek/sprite.cpp @@ -48,6 +48,13 @@ void Sprite::setBitmap(SharedPtr<Bitmap> b) { bitmapChanged = true; } +void Sprite::setXYAndPriority(int16 x, int16 y, int16 priority) { + pos.x = x; + pos.y = y; + drawPriority = priority; + bitmapChanged = true; +} + void Sprite::dontDrawNextFrame() { field16 = true; bitmapChanged = true; diff --git a/engines/startrek/sprite.h b/engines/startrek/sprite.h index ce53372906..e182f927d8 100644 --- a/engines/startrek/sprite.h +++ b/engines/startrek/sprite.h @@ -61,6 +61,7 @@ struct Sprite { Sprite(); void setBitmap(SharedPtr<Bitmap> b); + void setXYAndPriority(int16 x, int16 y, int16 priority); void dontDrawNextFrame(); Common::Rect getRect(); diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h index e37f4427c6..52d23c5677 100644 --- a/engines/startrek/startrek.h +++ b/engines/startrek/startrek.h @@ -360,6 +360,7 @@ public: Common::String _missionToLoad; int _roomIndexToLoad; + int _spawnIndexToLoad; Common::String _missionName; int _roomIndex; diff --git a/engines/startrek/text.h b/engines/startrek/text.h index 95b49a1cd2..7a8a80f3d9 100644 --- a/engines/startrek/text.h +++ b/engines/startrek/text.h @@ -44,6 +44,7 @@ enum GameStringIDs { TX_SPEAKER_CHUB, TX_SPEAKER_ROBERTS, TX_SPEAKER_GRISNASH, + TX_SPEAKER_NAUIAN, TX_DEM0_001, TX_DEM0_002, @@ -482,6 +483,7 @@ const char * const g_gameStrings[] = { "Brother Chub", "Brother Roberts", "Brother Grisnash", + "Nauian", "#DEM0\\DEM0_001#Doctor, you need to investigate the possibility of disease, mental or physical, among these people, before we go chasing up the mountains. Prelate Angiven, may we see those who have encountered the demons?", "#DEM0\\DEM0_002#Aside from seeing demons, has any hard data been collected? Any evidence I could see?", |