diff options
author | Matthew Stewart | 2018-06-21 23:33:02 -0400 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-09 08:37:30 +0200 |
commit | 08ead492d8ff338a469ca92881919d8ff22e12b3 (patch) | |
tree | 7b51f34ef76ca28cc12d3daa7c663ffb53bca773 /engines | |
parent | 16042faa655f53553ec26ef908e5528871e046ce (diff) | |
download | scummvm-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.
Diffstat (limited to 'engines')
-rw-r--r-- | engines/startrek/action.h | 12 | ||||
-rw-r--r-- | engines/startrek/awaymission.cpp | 10 | ||||
-rw-r--r-- | engines/startrek/awaymission.h | 9 | ||||
-rw-r--r-- | engines/startrek/object.h | 11 | ||||
-rw-r--r-- | engines/startrek/room.cpp | 41 | ||||
-rw-r--r-- | engines/startrek/room.h | 37 | ||||
-rw-r--r-- | engines/startrek/rooms/function_map.h | 36 | ||||
-rw-r--r-- | engines/startrek/rooms/love1.cpp | 4 | ||||
-rw-r--r-- | engines/startrek/rooms/love3.cpp | 266 | ||||
-rw-r--r-- | engines/startrek/startrek.cpp | 20 | ||||
-rw-r--r-- | engines/startrek/startrek.h | 4 |
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]; |