aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-06-21 23:33:02 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commit08ead492d8ff338a469ca92881919d8ff22e12b3 (patch)
tree7b51f34ef76ca28cc12d3daa7c663ffb53bca773
parent16042faa655f53553ec26ef908e5528871e046ce (diff)
downloadscummvm-rg350-08ead492d8ff338a469ca92881919d8ff22e12b3.tar.gz
scummvm-rg350-08ead492d8ff338a469ca92881919d8ff22e12b3.tar.bz2
scummvm-rg350-08ead492d8ff338a469ca92881919d8ff22e12b3.zip
STARTREK: LOVE3 finished.
Added "callback" variants of the "walkCrewman" and "loadActorAnim" functions to simplify chains of calls in room-specific code.
-rw-r--r--engines/startrek/action.h12
-rw-r--r--engines/startrek/awaymission.cpp10
-rw-r--r--engines/startrek/awaymission.h9
-rw-r--r--engines/startrek/object.h11
-rw-r--r--engines/startrek/room.cpp41
-rw-r--r--engines/startrek/room.h37
-rw-r--r--engines/startrek/rooms/function_map.h36
-rw-r--r--engines/startrek/rooms/love1.cpp4
-rw-r--r--engines/startrek/rooms/love3.cpp266
-rw-r--r--engines/startrek/startrek.cpp20
-rw-r--r--engines/startrek/startrek.h4
11 files changed, 431 insertions, 19 deletions
diff --git a/engines/startrek/action.h b/engines/startrek/action.h
index a501b7860a..4270eb97ea 100644
--- a/engines/startrek/action.h
+++ b/engines/startrek/action.h
@@ -27,6 +27,8 @@
namespace StarTrek {
+class Room;
+
enum Acton {
ACTION_TICK = 0,
@@ -41,7 +43,9 @@ enum Acton {
ACTION_TIMER_EXPIRED = 8,
ACTION_FINISHED_ANIMATION = 10,
ACTION_FINISHED_WALKING = 12,
- ACTION_OPTIONS = 13 // Not really an action, but selectable from action menu
+ ACTION_OPTIONS = 13, // Not really an action, but selectable from action menu
+
+ ACTION_CALLBACK = 255 // Custom action in ScummVM; calls a function in the Room class
};
struct Action : Common::Serializable {
@@ -50,6 +54,8 @@ struct Action : Common::Serializable {
byte b2;
byte b3;
+ void (Room::*roomFuncPtr)();
+
Action() {}
Action(int _type, int _b1, int _b2, int _b3)
: type((byte)_type),
@@ -57,6 +63,10 @@ struct Action : Common::Serializable {
b2((byte)_b2),
b3((byte)_b3) {}
+ Action(int _type, void (Room::*funcPtr)())
+ : type((byte)_type),
+ roomFuncPtr(funcPtr) {}
+
// ACTION_USE, ACTION_GET, ACTION_LOOK, ACTION_TALK
byte activeObject() { return b1; }
diff --git a/engines/startrek/awaymission.cpp b/engines/startrek/awaymission.cpp
index 1526e6a182..48c474ee85 100644
--- a/engines/startrek/awaymission.cpp
+++ b/engines/startrek/awaymission.cpp
@@ -61,8 +61,8 @@ void StarTrekEngine::runAwayMission() {
_awayMission.mouseY = mousePos.y;
assert(_actionQueue.size() <= 16);
- if (!_actionQueue.empty()) {
- // sub_200e7();
+ while (!_actionQueue.empty()) {
+ // sub_200e7(); // TODO
// sub_20118();
handleAwayMissionAction();
}
@@ -571,6 +571,12 @@ void StarTrekEngine::handleAwayMissionAction() {
initAwayCrewPositions(warpIndex ^ 1);
}
break;
+
+ case ACTION_CALLBACK:
+ // Custom action for ScummVM; calls a function in the Room class. Useful for
+ // simplifying chains of calls.
+ (_room.get()->*(action.roomFuncPtr))();
+ break;
}
}
diff --git a/engines/startrek/awaymission.h b/engines/startrek/awaymission.h
index c827d7a1cb..f1a7e77a65 100644
--- a/engines/startrek/awaymission.h
+++ b/engines/startrek/awaymission.h
@@ -142,7 +142,7 @@ struct AwayMission {
struct {
bool alreadyStartedMission; // 0x29
bool knowAboutVirus; // 0x2a
- bool putLaughingGasInVent; // 0x2b
+ bool romulansUnconsciousFromLaughingGas; // 0x2b
bool field2c; // 0x2c
bool field2d; // 0x2d
bool chamberHasCure; // 0x2e
@@ -159,14 +159,17 @@ struct AwayMission {
bool gasTankUnscrewed; // 0x39
bool wrenchTaken; // 0x3a
bool tookN2TankFromServicePanel; // 0x3b
+ bool field3c; // 0x3c
bool grateRemoved; // 0x3d
- bool field3e; // 0x3e
+ bool insulationOnGround; // 0x3e
bool field3f; // 0x3f
- bool field41; // 0x41
+ bool romulansUnconsciousFromVirus; // 0x41
bool spockAccessedConsole; // 0x49
bool mccoyAccessedConsole; // 0x4a
bool gotPolyberylcarbonate; // 0x4b
bool gotTLDH; // 0x4c (Got romulan laughing gas)
+ bool gotPointsForOpeningGrate; // 0x4d
+ bool gotPointsForGassingRomulans; // 0x4e
bool gotCure; // 0x4f
int16 missionScore; // 0x52
} love;
diff --git a/engines/startrek/object.h b/engines/startrek/object.h
index 18e2145175..6736ca5d7d 100644
--- a/engines/startrek/object.h
+++ b/engines/startrek/object.h
@@ -33,6 +33,7 @@ namespace StarTrek {
class StarTrekEngine;
class FileStream;
+class Room;
// Objects 0-31 are "actors" that are drawn to the screen, are animated, etc.
@@ -87,8 +88,17 @@ struct Actor {
Common::Point pos;
uint16 field60;
uint16 field62;
+
+ // When an object finished walking somewhere or finishes an animation, if
+ // "triggerActionWhenAnimFinished" is true, it will create an action of type
+ // "ACTION_FINISHED_WALKING" or "ACTION_FINISHED_ANIMATION", with the integer value
+ // "finishedAnimActionParam".
+ // To make things simpler, it can also use a callback to a function in the Room class,
+ // if "finishedAnimCallback" is non-null.
bool triggerActionWhenAnimFinished;
uint16 finishedAnimActionParam;
+ void (Room::*finishedAnimCallback)();
+
char animationString2[8];
uint16 field70;
uint16 field72;
@@ -140,6 +150,7 @@ public:
field62(),
triggerActionWhenAnimFinished(),
finishedAnimActionParam(),
+ finishedAnimCallback(),
//animationString2[8](),
field70(),
field72(),
diff --git a/engines/startrek/room.cpp b/engines/startrek/room.cpp
index 05645073fb..62949bedf0 100644
--- a/engines/startrek/room.cpp
+++ b/engines/startrek/room.cpp
@@ -190,6 +190,29 @@ void Room::loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y,
if (finishedAnimActionParam != 0) {
actor->triggerActionWhenAnimFinished = true;
actor->finishedAnimActionParam = finishedAnimActionParam;
+ actor->finishedAnimCallback = nullptr;
+ }
+}
+
+// Same as above, but accepts a callback for when the animation finished (instead of an
+// integer for an action)
+void Room::loadActorAnimC(int actorIndex, Common::String anim, int16 x, int16 y, void (Room::*funcPtr)()) {
+ Actor *actor = &_vm->_actorList[actorIndex];
+
+ if (x == -1 || y == -1) {
+ x = actor->sprite.pos.x;
+ y = actor->sprite.pos.y;
+ }
+
+ if (actorIndex >= 0 && actorIndex < SCALED_ACTORS_END)
+ _vm->loadActorAnimWithRoomScaling(actorIndex, anim, x, y);
+ else
+ _vm->loadActorAnim(actorIndex, anim, x, y, 256);
+
+ if (funcPtr != nullptr) {
+ actor->triggerActionWhenAnimFinished = true;
+ actor->finishedAnimActionParam = 0;
+ actor->finishedAnimCallback = funcPtr;
}
}
@@ -307,6 +330,24 @@ void Room::walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 finished
if (success && finishedAnimActionParam != 0) {
actor->triggerActionWhenAnimFinished = true;
actor->finishedAnimActionParam = finishedAnimActionParam;
+ actor->finishedAnimCallback = nullptr;
+ }
+}
+
+// Same as above, but with a function callback instead of an integer value to generate an
+// action
+void Room::walkCrewmanC(int actorIndex, int16 destX, int16 destY, void (Room::*funcPtr)()) {
+ if (!(actorIndex >= OBJECT_KIRK && actorIndex <= OBJECT_REDSHIRT))
+ error("Tried to walk a non PC");
+
+ Actor *actor = &_vm->_actorList[actorIndex];
+ Common::String anim = _vm->getCrewmanAnimFilename(actorIndex, "walk");
+ bool success = _vm->actorWalkToPosition(actorIndex, anim, actor->pos.x, actor->pos.y, destX, destY);
+
+ if (success && funcPtr != nullptr) {
+ actor->triggerActionWhenAnimFinished = true;
+ actor->finishedAnimActionParam = 0;
+ actor->finishedAnimCallback = funcPtr;
}
}
diff --git a/engines/startrek/room.h b/engines/startrek/room.h
index 3ab458a84a..59b37e6f0d 100644
--- a/engines/startrek/room.h
+++ b/engines/startrek/room.h
@@ -98,6 +98,7 @@ private:
// Interface for room-specific code
void loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66); // Cmd 0x00
+ void loadActorAnimC(int actorIndex, Common::String anim, int16 x, int16 y, void (Room::*funcPtr)());// Cmd 0x00
void loadActorStandAnim(int actorIndex); // Cmd 0x01
void loadActorAnim2(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66);// Cmd 0x02
int showRoomSpecificText(const char **textAddr); // (Deprecated, use function below) // Cmd 0x03
@@ -109,6 +110,7 @@ private:
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
+ void walkCrewmanC(int actorIndex, int16 destX, int16 destY, void (Room::*funcPtr)()); // Cmd 0x08
void loadMapFile(const Common::String &name); // Cmd 0x09
void showBitmapFor5Ticks(const Common::String &bmpName, int priority); // Cmd 0x0a
// Command 0x0c: "demon6ShowCase"
@@ -974,6 +976,41 @@ public:
void love3UseWrenchOnN2Gas();
void love3ReachedGasTankToPutDown();
void love3PutN2TankBack();
+ void love3UseWrenchOnEngineeringPanel();
+ void love3ReachedEngineeringPanel();
+ void love3OpenedEngineeringPanel();
+ void love3UseWrenchOnMonitor();
+ void love3UseWaterOnMonitor();
+ void love3ReachedMonitorToUseWater();
+ void love3PouredWaterOnMonitor();
+ void love3UseCrewmanOnEngineeringPanelOrGrate();
+ void love3UseWrenchOnGrate();
+ void love3ReachedGateWithWrench();
+ void love3OpenedOrClosedGrate();
+ void love3UseCrewmanOnShaft();
+ void love3UseWaterOnShaft();
+ void love3ReachedShaftUsingWater();
+ void love3PouredWaterDownShaft();
+ void love3UseNitrousOxideOnShaft();
+ void love3ReachedShaftUsingNitrousOxide();
+ void love3PouredNitrousOxideDownShaft();
+ void love3UseAmmoniaOnShaft();
+ void love3ReachedShaftUsingAmmonia();
+ void love3PouredAmmoniaDownShaft();
+ void love3UseRomulanLaughingGasOnShaft();
+ void love3ReachedShaftUsingRomulanLaughingGas();
+ void love3PouredRomulanLaughingGasDownShaft();
+ void love3GetWrench();
+ void love3ReachedWrenchToGet();
+ void love3PickedUpWrench();
+ void love3GetGasTank();
+ void love3ReachedGasTankToGet();
+ void love3UseAntigravOnGasTank();
+ void love3ReachedGasTankUsingAntigrav();
+ void love3PickedUpGasTank();
+ void love3GetInsulation();
+ void love3ReachedInsulationToGet();
+ void love3PickedUpInsulation();
// LOVE4
void love4Tick1();
diff --git a/engines/startrek/rooms/function_map.h b/engines/startrek/rooms/function_map.h
index dab82aaac5..8c8df3794f 100644
--- a/engines/startrek/rooms/function_map.h
+++ b/engines/startrek/rooms/function_map.h
@@ -1090,17 +1090,53 @@ RoomAction love3ActionList[] = {
{ Action(ACTION_USE, OBJECT_KIRK, 8, 0), &Room::love3UseKirkOnServicePanel },
{ Action(ACTION_USE, OBJECT_SPOCK, 8, 0), &Room::love3UseSpockOnServicePanel },
{ Action(ACTION_USE, OBJECT_MCCOY, 8, 0), &Room::love3UseMccoyOnServicePanel },
+
{ Action(ACTION_USE, OBJECT_REDSHIRT, 8, 0), &Room::love3UseRedshirtOnServicePanel },
{ Action(ACTION_FINISHED_WALKING, 1, 0, 0), &Room::love3CrewmanReachedServicePanel },
{ Action(ACTION_FINISHED_ANIMATION, 1, 0, 0), &Room::love3OpenedOrClosedServicePanel },
+
{ Action(ACTION_USE, OBJECT_IWRENCH, 12, 0), &Room::love3UseWrenchOnGasTank },
{ Action(ACTION_FINISHED_WALKING, 2, 0, 0), &Room::love3ReachedGasTankToUnscrew },
{ Action(ACTION_FINISHED_ANIMATION, 2, 0, 0), &Room::love3ScrewedOrUnscrewedGasTank },
+
{ Action(ACTION_USE, OBJECT_IWRENCH, OBJECT_IO2GAS, 0), &Room::love3UseWrenchOnO2OrH2Gas },
{ Action(ACTION_USE, OBJECT_IWRENCH, OBJECT_IH2GAS, 0), &Room::love3UseWrenchOnO2OrH2Gas },
+
{ Action(ACTION_USE, OBJECT_IWRENCH, OBJECT_IN2GAS, 0), &Room::love3UseWrenchOnN2Gas },
{ Action(ACTION_FINISHED_WALKING, 15, 0, 0), &Room::love3ReachedGasTankToPutDown },
{ Action(ACTION_FINISHED_ANIMATION, 3, 0, 0), &Room::love3PutN2TankBack },
+
+ { Action(ACTION_USE, OBJECT_IWRENCH, 0x20, 0), &Room::love3UseWrenchOnEngineeringPanel },
+ { Action(ACTION_FINISHED_WALKING, 3, 0, 0), &Room::love3ReachedEngineeringPanel },
+ { Action(ACTION_FINISHED_ANIMATION, 4, 0, 0), &Room::love3OpenedEngineeringPanel },
+
+ { Action(ACTION_USE, OBJECT_IWRENCH, 0x21, 0), &Room::love3UseWrenchOnMonitor },
+
+ { Action(ACTION_USE, OBJECT_IH2O, 0x21, 0), &Room::love3UseWaterOnMonitor },
+
+ { Action(ACTION_USE, OBJECT_KIRK, 0x20, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_SPOCK, 0x20, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_MCCOY, 0x20, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_REDSHIRT, 0x20, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_KIRK, 11, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_SPOCK, 11, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_MCCOY, 11, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+ { Action(ACTION_USE, OBJECT_REDSHIRT, 11, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
+
+ { Action(ACTION_USE, OBJECT_IWRENCH, 11, 0), &Room::love3UseWrenchOnGrate },
+ { Action(ACTION_USE, OBJECT_KIRK, 0x22, 0), &Room::love3UseCrewmanOnShaft },
+ { Action(ACTION_USE, OBJECT_SPOCK, 0x22, 0), &Room::love3UseCrewmanOnShaft },
+ { Action(ACTION_USE, OBJECT_MCCOY, 0x22, 0), &Room::love3UseCrewmanOnShaft },
+ { Action(ACTION_USE, OBJECT_REDSHIRT, 0x22, 0), &Room::love3UseCrewmanOnShaft },
+ { Action(ACTION_USE, OBJECT_IH2O, 0x22, 0), &Room::love3UseWaterOnShaft },
+ { Action(ACTION_USE, OBJECT_IN2O, 0x22, 0), &Room::love3UseNitrousOxideOnShaft },
+ { Action(ACTION_USE, OBJECT_INH3, 0x22, 0), &Room::love3UseAmmoniaOnShaft },
+ { Action(ACTION_USE, OBJECT_IRLG, 0x22, 0), &Room::love3UseRomulanLaughingGasOnShaft },
+ { Action(ACTION_GET, 10, 0, 0), &Room::love3GetWrench },
+ { Action(ACTION_GET, 12, 0, 0), &Room::love3GetGasTank },
+ { Action(ACTION_USE, OBJECT_IANTIGRA, 12, 0), &Room::love3UseAntigravOnGasTank },
+ { Action(ACTION_GET, 9, 0, 0), &Room::love3GetInsulation },
+ // TODO: common code
};
RoomAction love4ActionList[] = {
diff --git a/engines/startrek/rooms/love1.cpp b/engines/startrek/rooms/love1.cpp
index d2ffe2143c..9f4617b8c1 100644
--- a/engines/startrek/rooms/love1.cpp
+++ b/engines/startrek/rooms/love1.cpp
@@ -624,7 +624,7 @@ void Room::love1CrewmanReachedLadder() {
TX_SPEAKER_FERRIS
};
- if (_vm->_awayMission.love.putLaughingGasInVent || _vm->_awayMission.love.field41) // Romulans unconscious
+ if (_vm->_awayMission.love.romulansUnconsciousFromLaughingGas || _vm->_awayMission.love.romulansUnconsciousFromVirus) // Romulans unconscious
loadRoomIndex(4, 3);
else { // Romulans still conscious, they shoot you
loadActorAnim(OBJECT_PHASERSHOT, "s3r2s2", 0xf3, 0x89, 0);
@@ -650,7 +650,7 @@ void Room::love1CrewmanDiedFromPhaser() {
// Romulans fire a "warning shot" when you go to the right part of the room.
void Room::love1TouchedHotspot0() {
- if (_vm->_awayMission.love.putLaughingGasInVent || _vm->_awayMission.love.field41)
+ if (_vm->_awayMission.love.romulansUnconsciousFromLaughingGas || _vm->_awayMission.love.romulansUnconsciousFromVirus)
return;
loadActorAnim(OBJECT_PHASERSHOT, "s3r2s1", 0xf3, 0x89, 0);
playSoundEffectIndex(SND_PHASSHOT);
diff --git a/engines/startrek/rooms/love3.cpp b/engines/startrek/rooms/love3.cpp
index 149c53c824..4e73ed8245 100644
--- a/engines/startrek/rooms/love3.cpp
+++ b/engines/startrek/rooms/love3.cpp
@@ -28,7 +28,7 @@
#define OBJECT_GRATE 11
#define OBJECT_GAS_TANK 12
-#define HOTSPOT_INSULATION 0x20
+#define HOTSPOT_ENGINEERING_PANEL 0x20
#define HOTSPOT_MONITOR 0x21
#define HOTSPOT_SHAFT 0x22
#define HOTSPOT_TURBINES 0x23
@@ -46,7 +46,7 @@ void Room::love3Tick1() {
else
loadActorAnim(OBJECT_GRATE, "s3r4g1", 0x116, 0x8f, 0);
- if (_vm->_awayMission.love.field3e)
+ if (_vm->_awayMission.love.insulationOnGround)
loadActorAnim(OBJECT_INSULATION, "s3r4p2", 0, 0, 0);
if (!_vm->_awayMission.love.tookN2TankFromServicePanel)
@@ -122,7 +122,7 @@ void Room::love3LookAtShaft() {
}
void Room::love3LookAtPanel() {
- if (_vm->_awayMission.love.field3e)
+ if (_vm->_awayMission.love.insulationOnGround)
showText(TX_LOV3N017);
else
showText(TX_LOV3NA22);
@@ -147,7 +147,7 @@ void Room::love3TalkToKirk() {
void Room::love3TalkToSpock() {
if (_vm->_awayMission.love.field3f)
showText(TX_SPEAKER_SPOCK, TX_LOV3_003);
- if (_vm->_awayMission.love.putLaughingGasInVent)
+ if (_vm->_awayMission.love.romulansUnconsciousFromLaughingGas)
showText(TX_SPEAKER_SPOCK, TX_LOV3_017);
else if (haveItem(OBJECT_IRLG))
showText(TX_SPEAKER_SPOCK, TX_LOV3_004);
@@ -175,7 +175,7 @@ void Room::love3UseSTricorderOnTurbines() {
}
void Room::love3UseSTricorderOnInsulation() {
- if (_vm->_awayMission.love.field3e)
+ if (_vm->_awayMission.love.insulationOnGround)
spockScan(DIR_W, TX_LOV3_002, false);
}
@@ -273,4 +273,260 @@ void Room::love3PutN2TankBack() {
loadActorAnim(OBJECT_GAS_TANK, "r4n2", 0, 0, 0);
}
+
+// Use wrench on engineering panel, insulation comes out
+void Room::love3UseWrenchOnEngineeringPanel() {
+ walkCrewman(OBJECT_KIRK, 0x37, 0xb4, 3);
+}
+
+void Room::love3ReachedEngineeringPanel() {
+ loadActorAnim2(OBJECT_KIRK, "kuselw", -1, -1, 4);
+ playVoc("MUR3E1S");
+}
+
+void Room::love3OpenedEngineeringPanel() {
+ if (!_vm->_awayMission.love.insulationOnGround) {
+ playVoc("MADR4E4A");
+ loadActorAnim(OBJECT_INSULATION, "s3r4p1", 0, 0, 0);
+ _vm->_awayMission.love.insulationOnGround = true;
+ }
+ showText(TX_LOV3N021);
+}
+
+
+void Room::love3UseWrenchOnMonitor() {
+ showText(TX_SPEAKER_SPOCK, TX_LOV3_018);
+}
+
+
+void Room::love3UseWaterOnMonitor() {
+ walkCrewmanC(OBJECT_KIRK, 0xc8, 0xb2, &Room::love3ReachedMonitorToUseWater);
+}
+
+void Room::love3ReachedMonitorToUseWater() {
+ loadActorAnimC(OBJECT_KIRK, "kusemn", -1, -1, &Room::love3PouredWaterOnMonitor);
+}
+
+void Room::love3PouredWaterOnMonitor() {
+ // BUGFIX: the speaker should be Lt. Ferris. In the original, the speaker wasn't
+ // specified.
+ // However, there is no substitute text for when Lt. Ferris is dead.
+ showText(TX_SPEAKER_FERRIS, TX_LOV3_021);
+
+ loseItem(OBJECT_IH2O);
+}
+
+
+void Room::love3UseCrewmanOnEngineeringPanelOrGrate() {
+ showText(TX_LOV3N030);
+}
+
+
+void Room::love3UseWrenchOnGrate() {
+ walkCrewmanC(OBJECT_KIRK, 0xf6, 0xaa, &Room::love3ReachedGateWithWrench);
+ _vm->_awayMission.disableInput = true;
+}
+
+void Room::love3ReachedGateWithWrench() {
+ if (_vm->_awayMission.love.grateRemoved)
+ loadActorAnimC(OBJECT_KIRK, "s3r4g2a", -1, -1, &Room::love3OpenedOrClosedGrate);
+ else
+ loadActorAnimC(OBJECT_KIRK, "s3r4g2", -1, -1, &Room::love3OpenedOrClosedGrate);
+ loadActorStandAnim(OBJECT_GRATE);
+ playVoc("MUR3E1S");
+}
+
+void Room::love3OpenedOrClosedGrate() {
+ _vm->_awayMission.disableInput = false;
+ loadActorStandAnim(OBJECT_KIRK);
+
+ if (!_vm->_awayMission.love.grateRemoved) {
+ _vm->_awayMission.love.grateRemoved = true;
+ loadActorAnim(OBJECT_GRATE, "s3r4g3", 0, 0, 0);
+ showText(TX_LOV3N016);
+ if (!_vm->_awayMission.love.gotPointsForOpeningGrate) {
+ _vm->_awayMission.love.gotPointsForOpeningGrate = true;
+ _vm->_awayMission.love.missionScore++;
+ }
+ }
+ else {
+ loadActorAnim(OBJECT_GRATE, "s3r4g1", 0x116, 0x8f, 0);
+ _vm->_awayMission.love.grateRemoved = false;
+ showText(TX_LOV3N032);
+ }
+}
+
+
+void Room::love3UseCrewmanOnShaft() {
+ showText(TX_LOV3N011);
+}
+
+
+void Room::love3UseWaterOnShaft() {
+ walkCrewmanC(OBJECT_KIRK, 0x100, 0xa6, &Room::love3ReachedShaftUsingWater);
+}
+
+void Room::love3ReachedShaftUsingWater() {
+ if (!_vm->_awayMission.love.grateRemoved)
+ showText(TX_LOV3N025);
+ else
+ loadActorAnimC(OBJECT_KIRK, "kuseme", -1, -1, &Room::love3PouredWaterDownShaft);
+}
+
+void Room::love3PouredWaterDownShaft() {
+ showText(TX_LOV3N009);
+ loseItem(OBJECT_IH2O);
+}
+
+
+void Room::love3UseNitrousOxideOnShaft() {
+ walkCrewmanC(OBJECT_KIRK, 0x100, 0xa6, &Room::love3ReachedShaftUsingNitrousOxide);
+}
+
+void Room::love3ReachedShaftUsingNitrousOxide() {
+ if (!_vm->_awayMission.love.grateRemoved)
+ showText(TX_LOV3N025);
+ else
+ loadActorAnimC(OBJECT_KIRK, "kuseme", -1, -1, &Room::love3PouredNitrousOxideDownShaft);
+}
+
+void Room::love3PouredNitrousOxideDownShaft() {
+ showText(TX_LOV3N018);
+ showText(TX_SPEAKER_SPOCK, TX_LOV3_012);
+ loseItem(OBJECT_IN2O);
+}
+
+
+void Room::love3UseAmmoniaOnShaft() {
+ walkCrewmanC(OBJECT_KIRK, 0x100, 0xa6, &Room::love3ReachedShaftUsingAmmonia);
+}
+
+void Room::love3ReachedShaftUsingAmmonia() {
+ if (!_vm->_awayMission.love.grateRemoved)
+ showText(TX_LOV3N025);
+ else
+ loadActorAnimC(OBJECT_KIRK, "kuseme", -1, -1, &Room::love3PouredAmmoniaDownShaft);
+}
+
+void Room::love3PouredAmmoniaDownShaft() {
+ if (!_vm->_awayMission.love.romulansUnconsciousFromVirus) {
+ showText(TX_LOV3N001);
+ if (!_vm->_awayMission.redshirtDead)
+ showText(TX_SPEAKER_FERRIS, TX_LOV3_023);
+ }
+
+ loseItem(OBJECT_INH3);
+}
+
+
+void Room::love3UseRomulanLaughingGasOnShaft() {
+ if (_vm->_awayMission.love.gotPointsForGassingRomulans) {
+ // BUG-ish: you could get the points for this by starting the action, then
+ // canceling it before Kirk reaches the shaft.
+ _vm->_awayMission.love.gotPointsForGassingRomulans = true;
+ _vm->_awayMission.love.missionScore += 6;
+ }
+ if (_vm->_awayMission.love.romulansUnconsciousFromLaughingGas)
+ showText(TX_SPEAKER_SPOCK, TX_LOV3_011);
+ else {
+ walkCrewmanC(OBJECT_KIRK, 0xf6, 0xa4, &Room::love3ReachedShaftUsingRomulanLaughingGas);
+ }
+}
+
+void Room::love3ReachedShaftUsingRomulanLaughingGas() {
+ if (!_vm->_awayMission.love.grateRemoved)
+ showText(TX_LOV3N025);
+ else {
+ loadActorAnimC(OBJECT_KIRK, "kuseme", -1, -1, &Room::love3PouredRomulanLaughingGasDownShaft);
+ playVoc("EFX24");
+ }
+}
+
+void Room::love3PouredRomulanLaughingGasDownShaft() {
+ loseItem(OBJECT_IRLG);
+ _vm->_awayMission.love.romulansUnconsciousFromLaughingGas = true;
+
+ if (_vm->_awayMission.love.romulansUnconsciousFromVirus) {
+ showText(TX_LOV3NA08);
+ _vm->_awayMission.love.romulansUnconsciousFromLaughingGas = false;
+ }
+ else {
+ showText(TX_LOV3NA09);
+ playVoc("ROMULANL");
+ }
+}
+
+
+// Get the wrench on the ground
+void Room::love3GetWrench() {
+ walkCrewmanC(OBJECT_KIRK, 0x104, 0xb6, &Room::love3ReachedWrenchToGet);
+}
+
+void Room::love3ReachedWrenchToGet() {
+ loadActorAnimC(OBJECT_KIRK, "s5r1kg", -1, -1, &Room::love3PickedUpWrench);
+}
+
+void Room::love3PickedUpWrench() {
+ loadActorStandAnim(OBJECT_KIRK);
+ giveItem(OBJECT_IWRENCH);
+ loadActorStandAnim(OBJECT_WRENCH);
+ _vm->_awayMission.love.wrenchTaken = true;
+ showText(TX_LOV3N031);
+}
+
+
+// Get the N2 gas tank in the service panel (fails due to weight)
+void Room::love3GetGasTank() {
+ walkCrewmanC(OBJECT_KIRK, 0x121, 0xb7, &Room::love3ReachedGasTankToGet);
+}
+
+void Room::love3ReachedGasTankToGet() {
+ if (_vm->_awayMission.love.gasTankUnscrewed)
+ showText(TX_LOV3N007);
+ else
+ showText(TX_LOV3N014);
+}
+
+
+// Use antigrav unit N2 gas tank in the service panel (succeeds)
+void Room::love3UseAntigravOnGasTank() {
+ walkCrewmanC(OBJECT_KIRK, 0x10e, 0xae, &Room::love3ReachedGasTankUsingAntigrav);
+}
+
+void Room::love3ReachedGasTankUsingAntigrav() {
+ if (_vm->_awayMission.love.gasTankUnscrewed) {
+ loadActorAnimC(OBJECT_KIRK, "kusehe", -1, -1, &Room::love3PickedUpGasTank);
+ playVoc("SE3PLBAT");
+ }
+ else {
+ showText(TX_LOV3N010);
+ showText(TX_SPEAKER_SPOCK, TX_LOV3_015);
+ }
+}
+
+void Room::love3PickedUpGasTank() {
+ giveItem(OBJECT_IN2GAS);
+ loadActorStandAnim(OBJECT_GAS_TANK);
+ _vm->_awayMission.love.tookN2TankFromServicePanel = true;
+
+ showText(TX_LOV3NJ32);
+ if (!_vm->_awayMission.redshirtDead)
+ showText(TX_SPEAKER_FERRIS, TX_LOV3_025);
+}
+
+void Room::love3GetInsulation() {
+ walkCrewmanC(OBJECT_KIRK, 0x32, 0xbe, &Room::love3ReachedInsulationToGet);
+}
+
+void Room::love3ReachedInsulationToGet() {
+ if (!_vm->_awayMission.love.field3c)
+ loadActorAnimC(OBJECT_KIRK, "s5r1kg", -1, -1, &Room::love3PickedUpInsulation);
+}
+
+void Room::love3PickedUpInsulation() {
+ loadActorStandAnim(OBJECT_KIRK);
+ giveItem(OBJECT_IINSULAT);
+ showText(TX_LOV3N029);
+}
+
}
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index 16c5d206d1..2960ff1637 100644
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -459,7 +459,12 @@ void StarTrekEngine::updateActorAnimations() {
if (nextAnimFrame == actor->numAnimFrames - 1) {
actor->field62++;
if (actor->triggerActionWhenAnimFinished) {
- addAction(Action(ACTION_FINISHED_ANIMATION, actor->finishedAnimActionParam, 0, 0));
+ if (actor->finishedAnimCallback != nullptr) {
+ addAction(Action(ACTION_CALLBACK, actor->finishedAnimCallback));
+ actor->finishedAnimCallback = nullptr;
+ }
+ else
+ addAction(Action(ACTION_FINISHED_ANIMATION, actor->finishedAnimActionParam, 0, 0));
}
}
}
@@ -530,7 +535,12 @@ void StarTrekEngine::updateActorAnimations() {
if (actor->iwSrcPosition == -1) {
if (actor->triggerActionWhenAnimFinished) {
actor->triggerActionWhenAnimFinished = false;
- addAction(Action(ACTION_FINISHED_WALKING, actor->finishedAnimActionParam & 0xff, 0, 0));
+ if (actor->finishedAnimCallback != nullptr) {
+ addAction(Action(ACTION_CALLBACK, actor->finishedAnimCallback));
+ actor->finishedAnimCallback = nullptr;
+ }
+ else
+ addAction(Action(ACTION_FINISHED_WALKING, actor->finishedAnimActionParam & 0xff, 0, 0));
}
actor->sprite.bitmap.reset();
@@ -1855,13 +1865,13 @@ uint16 StarTrekEngine::getRandomWord() {
* ".txt" files are just lists of strings. This traverses the file to get a particular
* string index.
*/
-Common::String StarTrekEngine::getLoadedText(int itemIndex) {
+Common::String StarTrekEngine::getLoadedText(int textIndex) {
SharedPtr<FileStream> txtFile = loadFile(_txtFilename + ".txt");
byte *data = txtFile->_data;
- while (itemIndex != 0) {
+ while (textIndex != 0) {
while (*(data++) != '\0');
- itemIndex--;
+ textIndex--;
}
return (char *)data;
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index ee741eb598..acd912afbb 100644
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -395,7 +395,7 @@ public:
// Misc
uint16 getRandomWord();
- Common::String getLoadedText(int itemIndex);
+ Common::String getLoadedText(int textIndex);
public:
@@ -448,6 +448,8 @@ public:
Common::Point _objectWalkPosition;
// Actions to perform after a crewman finishes walking to a position.
+ // Room-specific code can specify that a specific action of type
+ // "ACTION_FINISHED_WALKING" occurs after moving a crewman somewhere.
Action _actionOnWalkCompletion[MAX_BUFFERED_WALK_ACTIONS];
bool _actionOnWalkCompletionInUse[MAX_BUFFERED_WALK_ACTIONS];