aboutsummaryrefslogtreecommitdiff
path: root/engines/startrek
diff options
context:
space:
mode:
authorMatthew Stewart2018-05-24 22:08:56 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commit45ae72b763268d87a5a6613231b7a11a2fbd8168 (patch)
treefd5f55b9ca830dff6544c68d60e7836c3f02fcdc /engines/startrek
parentca3a9dcc8764909e163a860e4a472404620480e2 (diff)
downloadscummvm-rg350-45ae72b763268d87a5a6613231b7a11a2fbd8168.tar.gz
scummvm-rg350-45ae72b763268d87a5a6613231b7a11a2fbd8168.tar.bz2
scummvm-rg350-45ae72b763268d87a5a6613231b7a11a2fbd8168.zip
STARTREK: DEMON1 done (klingon attack)
Diffstat (limited to 'engines/startrek')
-rw-r--r--engines/startrek/action.h1
-rw-r--r--engines/startrek/awaymission.cpp36
-rw-r--r--engines/startrek/awaymission.h54
-rw-r--r--engines/startrek/menu.cpp33
-rw-r--r--engines/startrek/module.mk3
-rw-r--r--engines/startrek/room.cpp13
-rw-r--r--engines/startrek/room.h70
-rw-r--r--engines/startrek/rooms/demon0.cpp37
-rw-r--r--engines/startrek/rooms/demon1.cpp827
-rw-r--r--engines/startrek/rooms/function_map.h85
-rw-r--r--engines/startrek/sound.cpp4
-rw-r--r--engines/startrek/startrek.cpp57
-rw-r--r--engines/startrek/startrek.h3
13 files changed, 1163 insertions, 60 deletions
diff --git a/engines/startrek/action.h b/engines/startrek/action.h
index 7be09eb671..232dc22b35 100644
--- a/engines/startrek/action.h
+++ b/engines/startrek/action.h
@@ -35,6 +35,7 @@ enum Acton {
ACTION_TOUCHED_WARP = 6,
ACTION_TOUCHED_HOTSPOT = 7, // Doors? (Or just hotspots activated by Kirk moving there?)
+ ACTION_TIMER_EXPIRED = 8,
ACTION_FINISHED_ANIMATION = 10,
ACTION_FINISHED_WALKING = 12,
ACTION_OPTIONS = 13 // Not really an action, but selectable from action menu
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp
index 5bd134df8f..0265f4ed60 100644
--- a/engines/startrek/awaymission.cpp
+++ b/engines/startrek/awaymission.cpp
@@ -108,7 +108,7 @@ void StarTrekEngine::loadRoom(const Common::String &missionName, int roomIndex)
void StarTrekEngine::initAwayCrewPositions(int warpEntryIndex) {
_sound->stopAllVocSounds();
- memset(_awayMission.field25, 0xff, 4);
+ memset(_awayMission.crewDirectionsAfterWalk, 0xff, 4);
switch (warpEntryIndex) {
case 0: // 0-3: Read warp positions from RDF file
@@ -160,13 +160,13 @@ void StarTrekEngine::handleAwayMissionEvents() {
switch (event.type) {
case TREKEVENT_TICK:
updateActorAnimations();
- // sub_236bb();
+ updateCrewmanGetupTimers();
updateMouseBitmap();
// doSomethingWithBanData1();
_gfx->drawAllSprites();
// doSomethingWithBanData2();
_sound->checkLoopMusic();
- // sub_22de0();
+ updateAwayMissionTimers();
_frameIndex++;
_roomFrameCounter++;
addAction(Action(ACTION_TICK, _roomFrameCounter & 0xff, (_roomFrameCounter >> 8) & 0xff, 0));
@@ -180,7 +180,7 @@ void StarTrekEngine::handleAwayMissionEvents() {
switch (_awayMission.activeAction) {
case ACTION_WALK: {
- if (_awayMission.field1c != 0)
+ if (_awayMission.disableWalking)
break;
_kirkActor->sprite.drawMode = 1; // Hide these objects for function call below?
_spockActor->sprite.drawMode = 1;
@@ -208,7 +208,7 @@ void StarTrekEngine::handleAwayMissionEvents() {
}
case ACTION_USE: {
- if (_awayMission.activeObject == OBJECT_REDSHIRT && (_awayMission.redshirtDead || (_awayMission.field24 & 8))) {
+ if (_awayMission.activeObject == OBJECT_REDSHIRT && (_awayMission.redshirtDead || (_awayMission.crewDownBitset & (1 << OBJECT_REDSHIRT)))) {
hideInventoryIcons();
_awayMission.activeAction = ACTION_WALK;
break;
@@ -277,7 +277,7 @@ checkAddAction:
addAction(Action(_awayMission.activeAction, _awayMission.activeObject, _awayMission.passiveObject, 0));
checkShowInventory:
- if (!(_awayMission.field24 & 1))
+ if (!(_awayMission.crewDownBitset & (1 << OBJECT_KIRK)))
showInventoryIcons(true);
}
break;
@@ -304,7 +304,7 @@ checkShowInventory:
if (clickedObject != -2)
addAction(Action(_awayMission.activeAction, _awayMission.activeObject, 0, 0));
- if (_awayMission.activeAction == ACTION_LOOK && !(_awayMission.field24 & (1 << OBJECT_KIRK)))
+ if (_awayMission.activeAction == ACTION_LOOK && !(_awayMission.crewDownBitset & (1 << OBJECT_KIRK)))
showInventoryIcons(false);
}
break;
@@ -317,7 +317,7 @@ checkShowInventory:
break;
case TREKEVENT_RBUTTONDOWN: // TODO: also triggered by key press?
- if (_awayMission.field1d)
+ if (_awayMission.transitioningIntoRoom)
break;
hideInventoryIcons();
playSoundEffectIndex(0x07);
@@ -330,7 +330,7 @@ checkShowInventory:
_awayMission.activeObject = clickedObject;
}
if (_awayMission.activeAction == ACTION_USE
- && _awayMission.activeObject == OBJECT_ICOMM && (_awayMission.field24 & (1 << OBJECT_KIRK)) == 0) {
+ && _awayMission.activeObject == OBJECT_ICOMM && (_awayMission.crewDownBitset & (1 << OBJECT_KIRK)) == 0) {
if (!walkActiveObjectToHotspot()) {
addAction(Action(_awayMission.activeAction, _awayMission.activeObject, 0, 0));
_sound->playVoc("communic");
@@ -339,7 +339,7 @@ checkShowInventory:
}
else if (_awayMission.activeAction == ACTION_LOOK)
showInventoryIcons(false);
- else if (_awayMission.activeAction == ACTION_USE && (_awayMission.field24 & 1) == 0)
+ else if (_awayMission.activeAction == ACTION_USE && (_awayMission.crewDownBitset & 1) == 0)
showInventoryIcons(true);
break;
@@ -519,7 +519,7 @@ void StarTrekEngine::checkTouchedLoadingZone(int16 x, int16 y) {
}
_activeDoorWarpHotspot = -1;
- if (_awayMission.field24 == 0 && _warpHotspotsActive) {
+ if (_awayMission.crewDownBitset == 0 && _warpHotspotsActive) {
offset = _room->getFirstWarpPolygonOffset();
while (offset != _room->getWarpPolygonEndOffset()) {
@@ -540,6 +540,20 @@ void StarTrekEngine::checkTouchedLoadingZone(int16 x, int16 y) {
}
/**
+ * Updates any nonzero away mission timers, and invokes ACTION_TIMER_EXPIRED when any one
+ * reached 0.
+ */
+void StarTrekEngine::updateAwayMissionTimers() {
+ for (int i = 0; i < 8; i++) {
+ if (_awayMission.timers[i] == 0)
+ continue;
+ _awayMission.timers[i]--;
+ if (_awayMission.timers[i] == 0)
+ addAction(ACTION_TIMER_EXPIRED, i, 0, 0);
+ }
+}
+
+/**
* Returns true if the given position in the room is solid (not walkable).
* Reads from a ".map" file which has a bit for each position in the room, which is true
* when that position is solid.
diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h
index 34cdb4ba25..2e5b7d99d5 100644
--- a/engines/startrek/awaymission.h
+++ b/engines/startrek/awaymission.h
@@ -25,33 +25,47 @@
// All variables here get cleared to 0 upon starting an away mission.
struct AwayMission {
- int16 mouseX;
- int16 mouseY;
- byte field1c;
- byte field1d;
- byte transitioningIntoRoom; // Set while beaming in or walking into a room. Disables control?
- bool redshirtDead;
- byte activeAction;
- byte activeObject; // The item that is going to be used on something
- byte passiveObject; // The item that the active item is used on (or the item looked at, etc).
+ // These timers count down automatically when nonzero. When they reach 0,
+ // ACTION_TIMER_EXPIRED is invoked with the corresponding index (0-7).
+ int16 timers[8]; // 0x00-0x0f
+
+ int16 mouseX; // 0x10
+ int16 mouseY; // 0x12
+ int16 crewGetupTimers[4]; // 0x14
+ bool disableWalking; // 0x1c
+ byte transitioningIntoRoom; // 0x1d; Set while beaming in or walking into a room. Disables control?
+ bool redshirtDead; // 0x1e
+ byte activeAction; // 0x1f
+ byte activeObject; // 0x20; The item that is going to be used on something
+ byte passiveObject; // 0x21; The item that the active item is used on (or the item looked at, etc).
// If this is true after calling room-specific RDF code, the game will continue to run
// any "default" code for the event, if any.
- bool rdfStillDoDefaultAction;
+ bool rdfStillDoDefaultAction; // 0x23
+
+ // If a bit in "crewDownBitset" is set, the corresponding timer in "crewGetupTimers"
+ // begins counting down. When it reaches 0, they get up.
+ byte crewDownBitset;
- // Bits 0-3 correspond to the crewmen? A bit is set if they're not selectable with
- // the use action?
- byte field24;
+ int8 crewDirectionsAfterWalk[4]; // Sets an object's direction after they finish walking somewhere?
- int8 field25[4]; // Sets an object's direction after they finish walking somewhere?
+ // Mission-specific variables
+ union {
+ // Demon World
+ struct {
+ bool wasRudeToPrelate; // 0x29
+ bool beatKlingons; // 0x2f
+ bool tookKlingonHand; // 0x31
- // Demon Word: nonzero if a rude response was given to the prelate.
- int16 field29;
+ bool talkedToPrelate; // 0x33
+ bool askedPrelateAboutSightings; // 0x36
+ byte field37; // 0x37
+ bool mccoyMentionedFlora; // 0x38
+ byte enteredFrom; // 0x3a
- byte field33;
- byte field36;
- byte field38;
- byte field3a;
+ bool warpsDisabled; // 0x48
+ } demon;
+ };
int16 missionScore;
};
diff --git a/engines/startrek/menu.cpp b/engines/startrek/menu.cpp
index b0aea1f284..d6929d0d5c 100644
--- a/engines/startrek/menu.cpp
+++ b/engines/startrek/menu.cpp
@@ -848,6 +848,39 @@ void StarTrekEngine::showQuitGamePrompt(int x, int y) {
}
}
+void StarTrekEngine::showGameOverMenu() {
+ const char *options[] = {
+ "Game Over",
+ "#GENE\\GENER006#Load a previously saved game.",
+ "#GENE\\GENER020#Restart the game.",
+ "#GENE\\GENER018#Quit the game.",
+ ""
+ };
+
+ while (true) {
+ _inQuitGameMenu = true;
+ int selected = showText(&StarTrekEngine::readTextFromArray, (uintptr)options, 20, 20, TEXTCOLOR_YELLOW, true, false, true);
+ _inQuitGameMenu = false;
+
+ switch (selected) {
+ case 0: // Load game
+ _gfx->fadeoutScreen();
+ showLoadMenu(); // TODO: this probably manipulates the stack to jump out of this function...
+ break;
+ case 1: // Restart
+ _gfx->fadeoutScreen();
+ // TODO
+ break;
+ case 2: // Quit
+ _gfx->fadeoutScreen();
+ _system->quit();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/**
* This can be called from startup or from the options menu.
* On startup, this tries to load the setting without user input.
diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk
index b011c06c7a..94c2c8c661 100644
--- a/engines/startrek/module.mk
+++ b/engines/startrek/module.mk
@@ -18,7 +18,8 @@ MODULE_OBJS = \
sprite.o \
startrek.o \
text.o \
- rooms/demon0.o
+ rooms/demon0.o \
+ rooms/demon1.o
diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp
index 17d66d8cf7..f6e94f7338 100644
--- a/engines/startrek/room.cpp
+++ b/engines/startrek/room.cpp
@@ -40,11 +40,16 @@ Room::Room(StarTrekEngine *vm, const Common::String &name) : _vm(vm) {
_roomActionList = demon0ActionList;
_numRoomActions = sizeof(demon0ActionList) / sizeof(RoomAction);
}
+ else if (name == "DEMON1") {
+ _roomActionList = demon1ActionList;
+ _numRoomActions = sizeof(demon1ActionList) / sizeof(RoomAction);
+ }
else {
warning("Room \"%s\" unimplemented", name.c_str());
_numRoomActions = 0;
- return;
}
+
+ memset(&_roomVar, 0, sizeof(_roomVar));
}
Room::~Room() {
@@ -182,7 +187,7 @@ void Room::giveItem(int item) {
}
void Room::loadRoomIndex(int roomIndex, int spawnIndex) {
- if (_vm->_awayMission.field24 != 0)
+ if (_vm->_awayMission.crewDownBitset != 0)
return;
_vm->loadRoomIndex(roomIndex, spawnIndex);
@@ -215,6 +220,10 @@ void Room::playMidiMusicTracks(int startTrack, int loopTrack) {
_vm->playMidiMusicTracks(startTrack, loopTrack);
}
+void Room::showGameOverMenu() {
+ _vm->showGameOverMenu();
+}
+
void Room::playVoc(Common::String filename) {
_vm->_sound->playVoc(filename);
}
diff --git a/engines/startrek/room.h b/engines/startrek/room.h
index 220c7333ec..c7392449e5 100644
--- a/engines/startrek/room.h
+++ b/engines/startrek/room.h
@@ -103,6 +103,7 @@ private:
void walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 finishedAnimActionParam);// Cmd 0x08
void playSoundEffectIndex(int soundEffect); // Cmd 0x0f
void playMidiMusicTracks(int startTrack, int loopTrack); // Cmd 0x10
+ void showGameOverMenu(); // Cmd 0x12
void playVoc(Common::String filename); // Cmd 0x15
// Room-specific code
@@ -144,8 +145,75 @@ public:
void demon0UseSTricorderAnywhere();
void demon0UseMTricorderAnywhere();
void demon0UseMTricorderOnPrelate();
-
void demon0BadResponse();
+
+ // DEMON1
+ void demon1Tick1();
+ void demon1WalkToCave();
+ void demon1TouchedTopWarp();
+ void demon1TouchedBottomWarp();
+ void demon1Timer2Expired();
+ void demon1Timer0Expired();
+ void demon1Timer3Expired();
+ void demon1Timer1Expired();
+ void demon1KlingonFinishedAimingWeapon();
+ void demon1KirkShot();
+ void demon1UsePhaserOnAnything();
+ void demon1UsePhaserOnKlingon1();
+ void demon1ShootKlingon1();
+ void demon1KlingonDropsHand();
+ void demon1UsePhaserOnKlingon2();
+ void demon1ShootKlingon2();
+ void demon1UsePhaserOnKlingon3();
+ void demon1ShootKlingon3();
+ void demon1AllKlingonsDead();
+ void demon1Timer5Expired();
+ void demon1UseMTricorderOnKlingon();
+ void demon1UseSTricorderOnTulips();
+ void demon1UseSTricorderOnPods();
+ void demon1UseSTricorderOnCattails();
+ void demon1UseSTricorderOnFerns();
+ void demon1UseSTricorderOnHand();
+ void demon1UseSTricorderOnKlingon1();
+ void demon1UseSTricorderOnKlingon2Or3();
+ void demon1UseMTricorderOnKirk();
+ void demon1UseMTricorderOnSpock();
+ void demon1UseMTricorderOnRedshirt();
+ void demon1UseMTricorderOnCrewman();
+ void demon1GetHand();
+ void demon1ReachedHand();
+ void demon1PickedUpHand();
+ void demon1FinishedGettingHand();
+ void demon1LookAtKlingon();
+ void demon1LookAtCattails();
+ void demon1LookAtTulips();
+ void demon1LookAtPods();
+ void demon1LookAtFerns();
+ void demon1LookAtStream();
+ void demon1LookAtMine();
+ void demon1LookAtMountain();
+ void demon1LookAtHand();
+ void demon1LookAnywhere();
+ void demon1LookAtKirk();
+ void demon1LookAtSpock();
+ void demon1LookAtMcCoy();
+ void demon1LookAtRedshirt();
+ void demon1TalkToKirk();
+ void demon1TalkToSpock();
+ void demon1TalkToMcCoy();
+ void demon1TalkToRedshirt();
+ void demon1TalkToUnconsciousCrewman();
+
+private:
+ // Room-specific variables. This is memset'ed to 0 when the room is initialized.
+ union {
+ struct {
+ int numKlingonsKilled;
+ byte attackIndex;
+ bool kirkShooting;
+ char d6[10];
+ } demon1;
+ } _roomVar;
};
}
diff --git a/engines/startrek/rooms/demon0.cpp b/engines/startrek/rooms/demon0.cpp
index 41a5bbf802..b9c01373be 100644
--- a/engines/startrek/rooms/demon0.cpp
+++ b/engines/startrek/rooms/demon0.cpp
@@ -31,13 +31,13 @@ void Room::demon0Tick1() {
}
void Room::demon0Tick2() {
- if (_vm->_awayMission.field33 == 1)
+ if (_vm->_awayMission.demon.talkedToPrelate)
return;
loadActorAnim(8, "prel", 120, 190, 0);
}
void Room::demon0Tick60() {
- if (_vm->_awayMission.field33 == 1)
+ if (_vm->_awayMission.demon.talkedToPrelate)
return;
loadActorAnim2(8, "prelclap", 120, 190, 0);
}
@@ -59,23 +59,23 @@ void Room::demon0Tick140() {
""
};
- if (_vm->_awayMission.field38 == 1)
+ if (_vm->_awayMission.demon.mccoyMentionedFlora)
return;
showRoomSpecificText(text);
- _vm->_awayMission.field38 = 1;
+ _vm->_awayMission.demon.mccoyMentionedFlora = true;
}
void Room::demon0TouchedWarp0() {
- _vm->_awayMission.field3a = 1;
+ _vm->_awayMission.demon.enteredFrom = 1;
_vm->_awayMission.rdfStillDoDefaultAction = true;
}
void Room::demon0WalkToBottomDoor() {
_vm->_awayMission.transitioningIntoRoom = 1;
_rdfData[0xcd] = 1; // FIXME
- _vm->_awayMission.field25[OBJECT_KIRK] = DIR_E;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_E;
walkCrewman(OBJECT_KIRK, 243, 158, 1);
}
@@ -95,7 +95,7 @@ void Room::demon0ReachedBottomDoor() {
void Room::demon0WalkToTopDoor() {
_vm->_awayMission.transitioningIntoRoom = 1;
_rdfData[0xcc] = 1; // FIXME
- _vm->_awayMission.field25[OBJECT_KIRK] = DIR_E;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_E;
walkCrewman(OBJECT_KIRK, 157, 134, 2);
}
@@ -164,11 +164,11 @@ void Room::demon0TalkToPrelate() {
""
};
- if (_vm->_awayMission.field33 != 0)
+ if (_vm->_awayMission.demon.talkedToPrelate)
return;
_vm->_awayMission.missionScore += 3;
- _vm->_awayMission.field33 = 1;
+ _vm->_awayMission.demon.talkedToPrelate = true;
const char **response = nullptr;
@@ -197,7 +197,7 @@ void Room::demon0TalkToPrelate() {
showRoomSpecificText(thirdResponse);
- if (_vm->_awayMission.field29 != 0)
+ if (_vm->_awayMission.demon.wasRudeToPrelate)
showRoomSpecificText(badConclusion);
else
showRoomSpecificText(goodConclusion);
@@ -213,6 +213,7 @@ void Room::demon0LookAtPrelate() {
}
void Room::demon0UsePhaserOnSnow() {
+ // BUG: doesn't check if redshirt is dead.
const char *text[] = {
"Ensign Everts",
"#DEM0\\DEM0_039#Aw, Captain, please don't melt the snow. I've never seen it before.",
@@ -420,7 +421,7 @@ void Room::demon0TalkToRedshirt() {
}
void Room::demon0TalkToMcCoy() {
- if (_vm->_awayMission.field33 == 1) {
+ if (_vm->_awayMission.demon.talkedToPrelate) {
const char *text1[] = {
"Capt. Kirk",
"#DEM0\\DEM0_011#You look rather cold, Bones.",
@@ -456,7 +457,7 @@ void Room::demon0TalkToMcCoy() {
};
showRoomSpecificText(text1);
- if (_vm->_awayMission.field36 != 1) {
+ if (!_vm->_awayMission.demon.askedPrelateAboutSightings) {
demon0AskPrelateAboutSightings();
}
}
@@ -469,12 +470,12 @@ void Room::demon0TalkToSpock() {
""
};
- if (_vm->_awayMission.field33 == 1) {
+ if (_vm->_awayMission.demon.talkedToPrelate) {
showRoomSpecificText(text1);
}
else {
showRoomSpecificText(text1);
- if (_vm->_awayMission.field36 != 1)
+ if (!_vm->_awayMission.demon.askedPrelateAboutSightings)
demon0AskPrelateAboutSightings();
}
}
@@ -494,7 +495,7 @@ void Room::demon0AskPrelateAboutSightings() {
showRoomSpecificText(text2);
showRoomSpecificText(text3);
- _vm->_awayMission.field36 = 1;
+ _vm->_awayMission.demon.askedPrelateAboutSightings = true;
}
void Room::demon0UseSTricorderAnywhere() {
@@ -526,7 +527,7 @@ void Room::demon0UseMTricorderOnPrelate() {
loadActorAnim2(OBJECT_MCCOY, "mscans", -1, -1, 0);
playSoundEffectIndex(0x04);
- if (_vm->_awayMission.field33 == 1) {
+ if (_vm->_awayMission.demon.talkedToPrelate) {
const char *text[] = {
"Dr. McCoy",
"#DEM0\\DEM0_018#His blood pressure's up a bit, but he believes he's telling the truth.",
@@ -552,11 +553,11 @@ void Room::demon0BadResponse() {
""
};
- if (_vm->_awayMission.field29 != 0)
+ if (_vm->_awayMission.demon.wasRudeToPrelate)
return;
_vm->_awayMission.missionScore -= 3;
- _vm->_awayMission.field29 = 1;
+ _vm->_awayMission.demon.wasRudeToPrelate = true;
showRoomSpecificText(text);
}
diff --git a/engines/startrek/rooms/demon1.cpp b/engines/startrek/rooms/demon1.cpp
new file mode 100644
index 0000000000..7559dd7512
--- /dev/null
+++ b/engines/startrek/rooms/demon1.cpp
@@ -0,0 +1,827 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "startrek/room.h"
+
+namespace StarTrek {
+
+// BUG: under certain circumstances, the klingons just stop firing?
+
+void Room::demon1Tick1() {
+ playVoc("DEM1LOOP");
+
+ if (!_vm->_awayMission.demon.beatKlingons)
+ playMidiMusicTracks(1, -1);
+
+ if (_vm->_awayMission.demon.enteredFrom == 1) { // Entered from south
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_N;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_N;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_N;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_N;
+ }
+ else if (_vm->_awayMission.demon.enteredFrom == 2) { // Entered from north?
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_KIRK] = DIR_S;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_SPOCK] = DIR_S;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_MCCOY] = DIR_S;
+ _vm->_awayMission.crewDirectionsAfterWalk[OBJECT_REDSHIRT] = DIR_S;
+ }
+
+ if (!_vm->_awayMission.demon.beatKlingons) {
+ _vm->_awayMission.disableWalking = true;
+ _vm->_awayMission.timers[2] = 50;
+ }
+ else {
+ loadActorAnim(8, "klg1d2", 0x120, 0x82, 0);
+ if (!_vm->_awayMission.demon.tookKlingonHand)
+ loadActorAnim(13, "klghnd", 0x10b, 0x8e, 0);
+ loadActorAnim(9, "klg2d2", 0xaa, 0x7c, 0);
+ loadActorAnim(10, "klg3d2", 0, 0, 0);
+
+ _rdfData[0xca] = 1; // FIXME
+ _rdfData[0xcb] = 1;
+ _rdfData[0xcc] = 1;
+ _roomVar.demon1.numKlingonsKilled = 3;
+ }
+}
+
+void Room::demon1WalkToCave() {
+ if (_roomVar.demon1.numKlingonsKilled != 3)
+ return;
+ walkCrewman(OBJECT_KIRK, 0xa3, 0x56, 2);
+}
+
+void Room::demon1TouchedTopWarp() {
+ if (_vm->_awayMission.demon.warpsDisabled)
+ return;
+ loadRoomIndex(2, 1);
+}
+
+void Room::demon1TouchedBottomWarp() {
+ if (_vm->_awayMission.demon.warpsDisabled)
+ return;
+ loadRoomIndex(0, 0);
+}
+
+void Room::demon1Timer2Expired() {
+ if (_vm->_awayMission.demon.beatKlingons)
+ return;
+ _vm->_awayMission.demon.field37 = 1;
+ _vm->_awayMission.demon.beatKlingons = true;
+ _vm->_awayMission.demon.warpsDisabled = true;
+ _vm->_awayMission.timers[0] = 5;
+ _vm->_awayMission.timers[3] = 2;
+ _vm->_awayMission.timers[1] = 100;
+ loadActorAnim(8, "klg1u", 0x120, 0x82, 0);
+}
+
+void Room::demon1Timer0Expired() {
+ loadActorAnim(9, "klg2u", 0xaa, 0x7c, 0);
+}
+
+void Room::demon1Timer3Expired() {
+ loadActorAnim(10, "klg3u", 0xdb, 0x6d, 0);
+}
+
+void Room::demon1Timer1Expired() {
+ int shooter;
+ Common::String anim;
+
+ if (_rdfData[0xca] != 1) {
+ anim = "klg1f";
+ shooter = 8;
+
+ switch (_roomVar.demon1.attackIndex) {
+ case 0:
+ strcpy(_roomVar.demon1.d6, "klg1fr");
+ break;
+ case 1:
+ strcpy(_roomVar.demon1.d6, "klg1fm");
+ break;
+ case 2:
+ strcpy(_roomVar.demon1.d6, "klg1fs");
+ break;
+ case 3:
+ strcpy(_roomVar.demon1.d6, "klg1fk");
+ break;
+ default:
+ // TODO
+ return;
+ }
+ }
+ else if (_rdfData[0xcb] != 1) {
+ anim = "klg2f";
+ shooter = 9;
+ switch (_roomVar.demon1.attackIndex) {
+ case 0:
+ strcpy(_roomVar.demon1.d6, "klg2fr");
+ break;
+ case 1:
+ strcpy(_roomVar.demon1.d6, "klg2fm");
+ break;
+ case 2:
+ strcpy(_roomVar.demon1.d6, "klg2fs");
+ break;
+ case 3:
+ strcpy(_roomVar.demon1.d6, "klg2fk");
+ break;
+ default:
+ // TODO
+ return;
+ }
+ }
+ else {
+ anim = "klg3f";
+ shooter = 10;
+ switch (_roomVar.demon1.attackIndex) {
+ case 0:
+ strcpy(_roomVar.demon1.d6, "klg3fr");
+ break;
+ case 1:
+ strcpy(_roomVar.demon1.d6, "klg3fm");
+ break;
+ case 2:
+ strcpy(_roomVar.demon1.d6, "klg3fs");
+ break;
+ case 3:
+ strcpy(_roomVar.demon1.d6, "klg3fk");
+ break;
+ default:
+ // TODO
+ return;
+ }
+ }
+
+ loadActorAnim2(shooter, anim, -1, -1, 2);
+}
+
+void Room::demon1KlingonFinishedAimingWeapon() {
+ loadActorAnim(11, _roomVar.demon1.d6, 0, 0, 0);
+ playSoundEffectIndex(0x06);
+
+ _roomVar.demon1.attackIndex++;
+ int crewman;
+ if (_roomVar.demon1.attackIndex == 1) {
+ loadActorAnim2(OBJECT_REDSHIRT, "rstunn", -1, -1, 0);
+ crewman = OBJECT_REDSHIRT;
+ }
+ else if (_roomVar.demon1.attackIndex == 2) {
+ loadActorAnim2(OBJECT_SPOCK, "sstunn", -1, -1, 0);
+ crewman = OBJECT_SPOCK;
+ }
+ else if (_roomVar.demon1.attackIndex == 3) {
+ loadActorAnim2(OBJECT_MCCOY, "mstune", -1, -1, 0);
+ crewman = OBJECT_MCCOY;
+ }
+ else if (_roomVar.demon1.attackIndex == 4) {
+ loadActorAnim2(OBJECT_KIRK, "kstunn", -1, -1, 1);
+ crewman = OBJECT_KIRK;
+ }
+
+ _vm->_awayMission.crewDirectionsAfterWalk[crewman] = DIR_N;
+ _vm->_awayMission.crewGetupTimers[crewman] = 650;
+ _vm->_awayMission.crewDownBitset |= (1 << crewman);
+
+ _vm->_awayMission.timers[1] = 100;
+}
+
+void Room::demon1KirkShot() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N000#Captain Kirk is fatally shot by a Klingon, game over.",
+ ""
+ };
+
+ showRoomSpecificText(text);
+ showGameOverMenu();
+}
+
+void Room::demon1UsePhaserOnAnything() {
+ const char *text[] = {
+ "Dr. McCoy",
+ "#DEM1\\DEM1_011#The fire fight is over, Jim. I think you can put that away now.",
+ ""
+ };
+
+ if (_roomVar.demon1.numKlingonsKilled == 3)
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UsePhaserOnKlingon1() {
+ if (_rdfData[0xca] != 0)
+ return;
+ _vm->_awayMission.transitioningIntoRoom = 1;
+ _rdfData[0xca] = 1;
+
+ if (_roomVar.demon1.kirkShooting) {
+ demon1ShootKlingon1();
+ }
+ else {
+ loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 3);
+ _roomVar.demon1.kirkShooting = true;
+ }
+}
+
+void Room::demon1ShootKlingon1() {
+ _roomVar.demon1.numKlingonsKilled++;
+ if (_roomVar.demon1.numKlingonsKilled == 3) {
+ _vm->_awayMission.timers[1] = 0;
+ _vm->_awayMission.timers[5] = 180;
+ _vm->_awayMission.timers[6] = 1;
+ _vm->_awayMission.demon.warpsDisabled = false;
+ _vm->_awayMission.disableWalking = false;
+ }
+ loadActorAnim(12, "s0ks1", 0, 0, 0);
+ playSoundEffectIndex(0x06);
+ playVoc("EFX19");
+ loadActorAnim2(8, "klg1d", 0x120, 0x84, 7);
+}
+
+void Room::demon1KlingonDropsHand() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N020#You see a small explosion, and the Klingon's hand falls to the ground with a dull thud.",
+ ""
+ };
+ loadActorAnim(13, "klghnd", 0x10b, 0x8e, 0);
+ _vm->_awayMission.transitioningIntoRoom = 0;
+ _vm->_awayMission.timers[1] = 0;
+ showRoomSpecificText(text);
+
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_REDSHIRT))
+ return;
+
+ const char *rshirtText[] = {
+ "Ensign Everts",
+ "#DEM1\\DEM1_025#I guess they don't make Klingons like they used to, Sir.",
+ ""
+ };
+ showRoomSpecificText(rshirtText);
+
+ if (_roomVar.demon1.numKlingonsKilled == 3)
+ return;
+
+ const char *klingonText[] = {
+ "Klingon",
+ "#DEM1\\DEM1_F23#Federation Scum!",
+ ""
+ };
+ showRoomSpecificText(klingonText);
+
+ _vm->_awayMission.timers[1] = 1;
+}
+
+void Room::demon1UsePhaserOnKlingon2() {
+ if (_rdfData[0xcb] != 0)
+ return;
+ _vm->_awayMission.transitioningIntoRoom = 1;
+ _rdfData[0xcb] = 1;
+
+ if (_roomVar.demon1.kirkShooting) {
+ demon1ShootKlingon2();
+ }
+ else {
+ loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 4);
+ _roomVar.demon1.kirkShooting = true;
+ }
+}
+
+void Room::demon1ShootKlingon2() {
+ _roomVar.demon1.numKlingonsKilled++;
+ if (_roomVar.demon1.numKlingonsKilled == 3) {
+ _vm->_awayMission.timers[1] = 0;
+ _vm->_awayMission.timers[5] = 180;
+ _vm->_awayMission.timers[6] = 1;
+ _vm->_awayMission.demon.warpsDisabled = false;
+ _vm->_awayMission.disableWalking = false;
+ }
+ loadActorAnim(12, "s0ks2", 0, 0, 0);
+ playSoundEffectIndex(0x06);
+ loadActorAnim2(9, "klg2d", 0xaa, 0x7c, 0);
+ _vm->_awayMission.transitioningIntoRoom = 0;
+}
+
+void Room::demon1UsePhaserOnKlingon3() {
+ if (_rdfData[0xcc] != 0)
+ return;
+ _vm->_awayMission.transitioningIntoRoom = 1;
+ _rdfData[0xcc] = 1;
+
+ if (_roomVar.demon1.kirkShooting) {
+ demon1ShootKlingon3();
+ }
+ else {
+ loadActorAnim2(OBJECT_KIRK, "kfiren", -1, -1, 5);
+ _roomVar.demon1.kirkShooting = true;
+ }
+}
+
+void Room::demon1ShootKlingon3() {
+ _roomVar.demon1.numKlingonsKilled++;
+ if (_roomVar.demon1.numKlingonsKilled == 3) {
+ _vm->_awayMission.timers[1] = 0;
+ _vm->_awayMission.timers[5] = 180;
+ _vm->_awayMission.timers[6] = 1;
+ _vm->_awayMission.demon.warpsDisabled = false;
+ _vm->_awayMission.disableWalking = false;
+ }
+ loadActorAnim(12, "s0ks3", 0, 0, 0);
+ playSoundEffectIndex(0x06);
+ loadActorAnim2(10, "klg3d", 0, 0, 0);
+ _vm->_awayMission.transitioningIntoRoom = 0;
+}
+
+// Timer 6 expired
+void Room::demon1AllKlingonsDead() {
+ _vm->_awayMission.crewGetupTimers[OBJECT_KIRK] = 45;
+ _vm->_awayMission.crewGetupTimers[OBJECT_SPOCK] = 45;
+ _vm->_awayMission.crewGetupTimers[OBJECT_MCCOY] = 45;
+ _vm->_awayMission.crewGetupTimers[OBJECT_REDSHIRT] = 45;
+}
+
+void Room::demon1Timer5Expired() {
+ if (_vm->_awayMission.crewDownBitset != 0)
+ return;
+
+ const char *text1[] = {
+ "Lt. Uhura",
+ "#DEM1\\DEM1U077#Captain we registered Phaser fire and an unknown energy beam. Is everyone OK?",
+ ""
+ };
+ const char *text2[] = {
+ "Capt. Kirk",
+ "#DEM1\\DEM1_003#We're fine. Did you register any Disruptor fire?",
+ ""
+ };
+ const char *text3[] = {
+ "Lt. Uhura",
+ "#DEM1\\DEM1U078#No, Captain. Why, are Klingons down there?",
+ ""
+ };
+ const char *text4[] = {
+ "Capt. Kirk",
+ "#DEM1\\DEM1_002#No just an idea, Kirk out.",
+ ""
+ };
+ const char *text5[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_020#Fascinating. I begin to suspect that we have stumbled upon something that the colonists would never have uncovered.",
+ ""
+ };
+ const char *text6[] = {
+ "Capt. Kirk",
+ "#DEM1\\DEM1_004#What is it, Spock?",
+ ""
+ };
+ const char *text7[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_021#I wish to gather further data before making a definite conclusion, Captain.",
+ ""
+ };
+
+ showRoomSpecificText(text1);
+ showRoomSpecificText(text2);
+ showRoomSpecificText(text3);
+ showRoomSpecificText(text4);
+ showRoomSpecificText(text5);
+ showRoomSpecificText(text6);
+ showRoomSpecificText(text7);
+}
+
+
+void Room::demon1UseMTricorderOnKlingon() {
+ const char *text[] = {
+ "Dr. McCoy",
+ "#DEM1\\DEM1_012#This is definitely not a real klingon Jim.",
+ ""
+ };
+ loadActorAnim2(OBJECT_MCCOY, "mscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseSTricorderOnTulips() {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_007#Khytellian tulips are a perennial flower that survive in almost any climate.",
+ ""
+ };
+ loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseSTricorderOnPods() {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_008#The Brandzite pod is similar to terran milkweed except that the silk pods are in bright iridecent colors.",
+ ""
+ };
+ loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseSTricorderOnCattails() {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_005#Doctis Cattails are similar to their terran name sake except that they are known to cause hives if in contact with flesh for any amount of time.",
+ ""
+ };
+ loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseSTricorderOnFerns() {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_006#Gindorian ferns are regarded as an intergalactic weed, Captain.",
+ ""
+ };
+ loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseSTricorderOnHand() {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_017#This is a detached hand with some kind of circuitry in the palm, Captain.",
+ ""
+ };
+ loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseSTricorderOnKlingon1() {
+ // NOTE: it sets up the stack, but doesn't call the function...
+ //loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+
+ if (_roomVar.demon1.numKlingonsKilled == 3 && !_vm->_awayMission.demon.tookKlingonHand && _rdfData[0xcf] != 1) {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_018#This is not a Klingon, Captain, not a real one. It is an organic construct -- an android-like robot. It looks like a Klingon, but the appearance is entirely superficial. There is something different about this particular construct. Come here, Captain, look at the hand.It seems to have been separated from the body. There is a wiring circuit in the middle of the palm.",
+ ""
+ };
+ showRoomSpecificText(text);
+ _rdfData[0xcf] = 1;
+ }
+ else {
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_019#This is not a Klingon, Captain, not a real one. It is an organic construct -- an android-like robot. It looks like a Klingon, but the appearance is entirely superficial.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+}
+
+void Room::demon1UseSTricorderOnKlingon2Or3() {
+ loadActorAnim2(OBJECT_SPOCK, "sscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+
+ const char *text[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_019#This is not a Klingon, Captain, not a real one. It is an organic construct -- an android-like robot. It looks like a Klingon, but the appearance is entirely superficial.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1UseMTricorderOnKirk() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_KIRK))
+ demon1UseMTricorderOnCrewman();
+}
+
+void Room::demon1UseMTricorderOnSpock() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_SPOCK))
+ demon1UseMTricorderOnCrewman();
+}
+
+void Room::demon1UseMTricorderOnRedshirt() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_REDSHIRT))
+ demon1UseMTricorderOnCrewman();
+}
+
+void Room::demon1UseMTricorderOnCrewman() {
+ const char *text[] = {
+ "Dr. McCoy",
+ "#DEM1\\DEM1_009#He's only stunned. He'll be back up in a few seconds.",
+ ""
+ };
+ loadActorAnim2(OBJECT_MCCOY, "mscann", -1, -1, 0);
+ playSoundEffectIndex(0x04);
+ showRoomSpecificText(text);
+}
+
+void Room::demon1GetHand() {
+ if (_roomVar.demon1.numKlingonsKilled != 3)
+ return;
+ walkCrewman(OBJECT_KIRK, 0x104, 0x8e, 1);
+}
+
+void Room::demon1ReachedHand() {
+ loadActorAnim2(OBJECT_KIRK, "s5r1kg", -1, -1, 6);
+}
+
+void Room::demon1PickedUpHand() {
+ loadActorStandAnim(13);
+ _vm->_awayMission.missionScore += 3;
+ loadActorStandAnim(OBJECT_KIRK);
+ _vm->_awayMission.timers[4] = 2;
+}
+
+// Timer 4 expired
+void Room::demon1FinishedGettingHand() {
+ const char *text1[] = {
+ nullptr,
+ "#DEM1\\DEM1N005#You already took the hand from the Klingon.",
+ ""
+ };
+ const char *text2[] = {
+ nullptr,
+ "#DEM1\\DEM1N007#You take the Klingon's detached hand.",
+ ""
+ };
+
+ if (_vm->_awayMission.demon.tookKlingonHand)
+ showRoomSpecificText(text1);
+ else {
+ _vm->_awayMission.demon.tookKlingonHand = true;
+ giveItem(OBJECT_IHAND);
+ showRoomSpecificText(text2);
+ }
+}
+
+void Room::demon1LookAtKlingon() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N004#They look like Klingons.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtCattails() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N018#These are very beautiful Doctis Cattails.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtTulips() {
+ const char *text[] = {
+ nullptr,
+ "M1\\DEM1N010#A large patch of Khytellian Tulips.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtPods() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N019#These Brandzite Pods add a nice touch to the local flora.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtFerns() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N009#A Gindorian Fern.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtStream() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N011#A small stream flows down towards the forest.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtMine() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N021#You see the mine entrance ahead.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtMountain() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N016#Mt. Idyll rises above you.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtHand() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N023#It's the Klingon's detached hand!",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+void Room::demon1LookAnywhere() {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N017#The path is surrounded by some beautiful shrubbery.",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+void Room::demon1LookAtKirk() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_KIRK)) {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N012#Captain Kirk is unconscious.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+ else {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N003#James Kirk, filled with a premonition of more dangers yet to come.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+}
+
+void Room::demon1LookAtSpock() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_SPOCK)) {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N015#Mr. Spock is unconscious.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+ else {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N008#Your Vulcan science officer seems to be lost in thought, but remains alert.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+}
+
+void Room::demon1LookAtMcCoy() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_MCCOY)) {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N013#Dr. McCoy is unconscious.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+ else {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N001#Dr. McCoy, still hoping the cold winds that whip around Mount Idyll will soon die down.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+}
+
+void Room::demon1LookAtRedshirt() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_REDSHIRT)) {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N014#Ensign Everts is unconscious.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+ else {
+ const char *text[] = {
+ nullptr,
+ "#DEM1\\DEM1N002#Ensign Everts seems to be rattled by the attack of the Klingons.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+}
+
+void Room::demon1TalkToKirk() {
+ const char *text[] = {
+ "Capt. Kirk",
+ "#DEM1\\DEM1_001#We were caught flat footed there. I don't want any more surprises to catch us off guard.",
+ ""
+ };
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_KIRK))
+ demon1TalkToUnconsciousCrewman();
+ else if (_roomVar.demon1.numKlingonsKilled == 3)
+ showRoomSpecificText(text);
+}
+
+void Room::demon1TalkToSpock() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_SPOCK))
+ demon1TalkToUnconsciousCrewman();
+ else {
+ const char *text1[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_022#Captain, I detect a recent avalanche, approximately 6.2 kilometers away, that occurred within the last three days. The mountain may be quite dangerous.",
+ ""
+ };
+ const char *text2[] = {
+ "Dr. McCoy",
+ "#DEM1\\DEM1_013#Demons, Klingons, avalanches... What's next, the Wicked Witch of the West?",
+ ""
+ };
+ const char *text3[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_024#That is not logical, doctor.",
+ ""
+ };
+ const char *text4[] = {
+ "Dr. McCoy",
+ "#DEM1\\DEM1_014#It wasn't supposed to be logical, you green blooded Vulcan! Why does everything have to be so damned logical?",
+ ""
+ };
+ showRoomSpecificText(text1);
+ showRoomSpecificText(text2);
+ showRoomSpecificText(text3);
+ showRoomSpecificText(text4);
+ }
+}
+
+void Room::demon1TalkToMcCoy() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_MCCOY))
+ demon1TalkToUnconsciousCrewman();
+ else {
+ const char *text1[] = {
+ "Dr. McCoy",
+ "#DEM1\\DEM1_015#Well, we've seen Klingons. Now all we need is a few Romulans...",
+ ""
+ };
+ const char *text2[] = {
+ "Mr. Spock",
+ "#DEM1\\DEM1_023#Control your thoughts, Doctor. There is a high probability that something here is using our own memories against us.",
+ ""
+ };
+ showRoomSpecificText(text1);
+ showRoomSpecificText(text2);
+ }
+}
+
+void Room::demon1TalkToRedshirt() {
+ if (_vm->_awayMission.crewDownBitset & (1 << OBJECT_REDSHIRT))
+ demon1TalkToUnconsciousCrewman();
+ else {
+ const char *text[] = {
+ "Ensign Everts",
+ "#DEM1\\DEM1_026#I guess this isn't such a great planet after all.",
+ ""
+ };
+ showRoomSpecificText(text);
+ }
+}
+
+// FIXME: this doesn't happen in actual game? (does the event get blocked from higher up?)
+void Room::demon1TalkToUnconsciousCrewman() {
+ const char *text[] = {
+ nullptr,
+ "Zzzzz....",
+ ""
+ };
+ showRoomSpecificText(text);
+}
+
+}
diff --git a/engines/startrek/rooms/function_map.h b/engines/startrek/rooms/function_map.h
index ae7e8eb252..0743b794ff 100644
--- a/engines/startrek/rooms/function_map.h
+++ b/engines/startrek/rooms/function_map.h
@@ -85,6 +85,91 @@ RoomAction demon0ActionList[] = {
{ Action(ACTION_USE, OBJECT_IMTRICOR, 8, 0), &Room::demon0UseMTricorderOnPrelate },
};
+RoomAction demon1ActionList[] = {
+ { Action(ACTION_TICK, 1, 0, 0), &Room::demon1Tick1 },
+
+ { Action(ACTION_WALK, 0x25, 0, 0), &Room::demon1WalkToCave },
+ { Action(ACTION_FINISHED_WALKING, 2, 0, 0), &Room::demon1TouchedTopWarp },
+ { Action(ACTION_TOUCHED_WARP, 0, 0, 0), &Room::demon1TouchedTopWarp },
+ { Action(ACTION_TOUCHED_WARP, 1, 0, 0), &Room::demon1TouchedBottomWarp },
+
+ { Action(ACTION_TIMER_EXPIRED, 2, 0, 0), &Room::demon1Timer2Expired },
+ { Action(ACTION_TIMER_EXPIRED, 0, 0, 0), &Room::demon1Timer0Expired },
+ { Action(ACTION_TIMER_EXPIRED, 3, 0, 0), &Room::demon1Timer3Expired },
+ { Action(ACTION_TIMER_EXPIRED, 1, 0, 0), &Room::demon1Timer1Expired },
+
+ { Action(ACTION_FINISHED_ANIMATION, 2, 0, 0), &Room::demon1KlingonFinishedAimingWeapon },
+ { Action(ACTION_FINISHED_ANIMATION, 1, 0, 0), &Room::demon1KirkShot },
+
+ { Action(ACTION_USE, OBJECT_IPHASERK, -1, 0), &Room::demon1UsePhaserOnAnything },
+ { Action(ACTION_USE, OBJECT_IPHASERS, -1, 0), &Room::demon1UsePhaserOnAnything },
+
+ { Action(ACTION_USE, OBJECT_IPHASERK, 8, 0), &Room::demon1UsePhaserOnKlingon1 },
+ { Action(ACTION_USE, OBJECT_IPHASERS, 8, 0), &Room::demon1UsePhaserOnKlingon1 },
+ { Action(ACTION_FINISHED_ANIMATION, 3, 0, 0), &Room::demon1ShootKlingon1 },
+ { Action(ACTION_FINISHED_ANIMATION, 7, 0, 0), &Room::demon1KlingonDropsHand },
+
+ { Action(ACTION_USE, OBJECT_IPHASERK, 9, 0), &Room::demon1UsePhaserOnKlingon2 },
+ { Action(ACTION_USE, OBJECT_IPHASERS, 9, 0), &Room::demon1UsePhaserOnKlingon2 },
+ { Action(ACTION_FINISHED_ANIMATION, 4, 0, 0), &Room::demon1ShootKlingon2 },
+
+ { Action(ACTION_USE, OBJECT_IPHASERK, 10, 0), &Room::demon1UsePhaserOnKlingon3 },
+ { Action(ACTION_USE, OBJECT_IPHASERS, 10, 0), &Room::demon1UsePhaserOnKlingon3 },
+ { Action(ACTION_FINISHED_ANIMATION, 5, 0, 0), &Room::demon1ShootKlingon3 },
+
+ { Action(ACTION_TIMER_EXPIRED, 6, 0, 0), &Room::demon1AllKlingonsDead },
+ { Action(ACTION_TIMER_EXPIRED, 5, 0, 0), &Room::demon1Timer5Expired },
+
+ { Action(ACTION_USE, OBJECT_IMTRICOR, 13, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 0x21, 0), &Room::demon1UseSTricorderOnTulips },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 0x22, 0), &Room::demon1UseSTricorderOnPods },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 0x20, 0), &Room::demon1UseSTricorderOnCattails },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 0x23, 0), &Room::demon1UseSTricorderOnFerns },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 13, 0), &Room::demon1UseSTricorderOnHand },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 8, 0), &Room::demon1UseSTricorderOnKlingon1 },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 10, 0), &Room::demon1UseSTricorderOnKlingon2Or3 },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 9, 0), &Room::demon1UseSTricorderOnKlingon2Or3 },
+ { Action(ACTION_USE, OBJECT_IMEDKIT, 8, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_IMTRICOR, 8, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_IMEDKIT, 10, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_IMEDKIT, 9, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_IMTRICOR, 10, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_IMTRICOR, 9, 0), &Room::demon1UseMTricorderOnKlingon },
+ { Action(ACTION_USE, OBJECT_ISTRICOR, 8, 0), &Room::demon1UseSTricorderOnKlingon2Or3 }, // This is redundant
+
+ { Action(ACTION_USE, OBJECT_IMTRICOR, OBJECT_KIRK, 0), &Room::demon1UseMTricorderOnKirk },
+ { Action(ACTION_USE, OBJECT_IMTRICOR, OBJECT_SPOCK, 0), &Room::demon1UseMTricorderOnSpock },
+ { Action(ACTION_USE, OBJECT_IMTRICOR, OBJECT_REDSHIRT, 0), &Room::demon1UseMTricorderOnRedshirt },
+
+ { Action(ACTION_GET, 13, 0, 0), &Room::demon1GetHand },
+ { Action(ACTION_FINISHED_WALKING, 1, 0, 0), &Room::demon1ReachedHand },
+ { Action(ACTION_FINISHED_ANIMATION, 6, 0, 0), &Room::demon1PickedUpHand },
+ { Action(ACTION_TIMER_EXPIRED, 4, 0, 0), &Room::demon1FinishedGettingHand },
+
+ { Action(ACTION_LOOK, 8, 0, 0), &Room::demon1LookAtKlingon },
+ { Action(ACTION_LOOK, 9, 0, 0), &Room::demon1LookAtKlingon },
+ { Action(ACTION_LOOK, 10, 0, 0), &Room::demon1LookAtKlingon },
+
+ { Action(ACTION_LOOK, 0x20, 0, 0), &Room::demon1LookAtCattails },
+ { Action(ACTION_LOOK, 0x21, 0, 0), &Room::demon1LookAtTulips },
+ { Action(ACTION_LOOK, 0x22, 0, 0), &Room::demon1LookAtPods },
+ { Action(ACTION_LOOK, 0x23, 0, 0), &Room::demon1LookAtFerns },
+ { Action(ACTION_LOOK, 0x24, 0, 0), &Room::demon1LookAtStream },
+ { Action(ACTION_LOOK, 0x25, 0, 0), &Room::demon1LookAtMine },
+ { Action(ACTION_LOOK, 0x26, 0, 0), &Room::demon1LookAtMountain },
+ { Action(ACTION_LOOK, 13, 0, 0), &Room::demon1LookAtHand },
+ { Action(ACTION_LOOK, -1, 0, 0), &Room::demon1LookAnywhere },
+ { Action(ACTION_LOOK, OBJECT_KIRK, 0, 0), &Room::demon1LookAtKirk },
+ { Action(ACTION_LOOK, OBJECT_SPOCK, 0, 0), &Room::demon1LookAtSpock },
+ { Action(ACTION_LOOK, OBJECT_MCCOY, 0, 0), &Room::demon1LookAtMcCoy },
+ { Action(ACTION_LOOK, OBJECT_REDSHIRT, 0, 0), &Room::demon1LookAtRedshirt },
+
+ { Action(ACTION_TALK, OBJECT_KIRK, 0, 0), &Room::demon1TalkToKirk },
+ { Action(ACTION_TALK, OBJECT_SPOCK, 0, 0), &Room::demon1TalkToSpock },
+ { Action(ACTION_TALK, OBJECT_MCCOY, 0, 0), &Room::demon1TalkToMcCoy },
+ { Action(ACTION_TALK, OBJECT_REDSHIRT, 0, 0), &Room::demon1TalkToRedshirt },
+};
+
}
#endif
diff --git a/engines/startrek/sound.cpp b/engines/startrek/sound.cpp
index 5ae06e29c5..553d011c25 100644
--- a/engines/startrek/sound.cpp
+++ b/engines/startrek/sound.cpp
@@ -318,7 +318,9 @@ void Sound::loadPCMusicFile(const Common::String &baseSoundName) {
delete[] loadedSoundData;
loadedSoundData = new byte[soundStream->size()];
soundStream->read(loadedSoundData, soundStream->size());
- _midiSlots[0].midiParser->loadMusic(loadedSoundData, soundStream->size());
+
+ // FIXME: should music start playing when this is called?
+ //_midiSlots[0].midiParser->loadMusic(loadedSoundData, soundStream->size());
}
void Sound::clearMidiSlot(int slot) {
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index b4777a9240..35a6c9fdc8 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -657,10 +657,10 @@ void StarTrekEngine::initStandAnim(int actorIndex) {
const char *directions = "nsew";
if (actorIndex >= 0 && actorIndex <= 3) {
- int8 dir = _awayMission.field25[actorIndex];
+ int8 dir = _awayMission.crewDirectionsAfterWalk[actorIndex];
if (dir != -1) {
actor->direction = directions[dir];
- _awayMission.field25[actorIndex] = -1;
+ _awayMission.crewDirectionsAfterWalk[actorIndex] = -1;
}
}
// end of sub_239d2
@@ -972,7 +972,7 @@ SharedPtr<Bitmap> StarTrekEngine::loadAnimationFrame(const Common::String &filen
*/
int StarTrekEngine::selectObjectForUseAction() {
while (true) {
- if (!(_awayMission.field24 & (1 << OBJECT_KIRK)))
+ if (!(_awayMission.crewDownBitset & (1 << OBJECT_KIRK)))
showInventoryIcons(false);
TrekEvent event;
@@ -1239,11 +1239,11 @@ bool StarTrekEngine::isObjectUnusable(int object, int action) {
return false;
if (object == OBJECT_REDSHIRT && _awayMission.redshirtDead)
return true;
- if (object >= OBJECT_KIRK && object <= OBJECT_REDSHIRT && (_awayMission.field24 & (1 << object)))
+ if (object >= OBJECT_KIRK && object <= OBJECT_REDSHIRT && (_awayMission.crewDownBitset & (1 << object)))
return true;
- if (object == OBJECT_IMTRICOR && (_awayMission.field24 & (1 << OBJECT_MCCOY)))
+ if (object == OBJECT_IMTRICOR && (_awayMission.crewDownBitset & (1 << OBJECT_MCCOY)))
return true;
- if (object == OBJECT_ISTRICOR && (_awayMission.field24 & (1 << OBJECT_SPOCK)))
+ if (object == OBJECT_ISTRICOR && (_awayMission.crewDownBitset & (1 << OBJECT_SPOCK)))
return true;
return false;
}
@@ -1270,6 +1270,51 @@ void StarTrekEngine::hideInventoryIcons() {
}
}
+/**
+ * When a crewman is collapsed, they get once a timer reaches 0.
+ */
+void StarTrekEngine::updateCrewmanGetupTimers() {
+ if (_awayMission.crewDownBitset == 0)
+ return;
+ for (int i = OBJECT_KIRK; i <= OBJECT_REDSHIRT; i++) {
+ Actor *actor = &_actorList[i];
+
+ if (!(_awayMission.crewDownBitset & (1 << i)))
+ continue;
+
+ _awayMission.crewGetupTimers[i]--;
+ if (_awayMission.crewGetupTimers[i] <= 0) {
+ Common::String anim = getCrewmanAnimFilename(i, "getu");
+ int8 dir = _awayMission.crewDirectionsAfterWalk[i];
+ char d;
+ if (dir == -1) {
+ d = actor->direction;
+ }
+ else {
+ const char *dirs = "nsew";
+ uint16 scale = getActorScaleAtPosition(actor->sprite.pos.y);
+ d = dirs[dir];
+
+ int16 xOffset = 0, yOffset = 0;
+ if (d == 'n') {
+ xOffset = -24;
+ yOffset = -8;
+ }
+ else if (d == 'w') {
+ xOffset = -35;
+ yOffset = -12;
+ }
+ actor->sprite.pos.x += (scale * xOffset) >> 8;
+ actor->sprite.pos.y += (scale * yOffset) >> 8;
+ }
+
+ anim += (char)d;
+ loadActorAnimWithRoomScaling(i, anim, actor->sprite.pos.x, actor->sprite.pos.y);
+ _awayMission.crewDownBitset &= ~(1 << i);
+ }
+ }
+}
+
int StarTrekEngine::showInventoryMenu(int x, int y, bool restoreMouse) {
const int ITEMS_PER_ROW = 5;
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index b408b393b0..f5715d5888 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -198,6 +198,7 @@ public:
bool isPointInPolygon(int16 *data, int16 x, int16 y);
void checkTouchedLoadingZone(int16 x, int16 y);
+ void updateAwayMissionTimers();
bool isPositionSolid(int16 x, int16 y);
void loadRoomIndex(int roomIndex, int spawnIndex);
@@ -241,6 +242,7 @@ public:
void updateMouseBitmap();
bool walkActiveObjectToHotspot();
bool isObjectUnusable(int objectIndex, int action);
+ void updateCrewmanGetupTimers();
void showInventoryIcons(bool showItem);
void hideInventoryIcons();
int showInventoryMenu(int x, int y, bool restoreMouse);
@@ -315,6 +317,7 @@ public:
void showSaveMenu();
void showLoadMenu();
void showQuitGamePrompt(int x, int y);
+ void showGameOverMenu();
void showTextConfigurationMenu(bool fromOptionMenu);
int loadTextDisplayMode();