Permalink
Browse files

STARTREK: LOVE3 finished.

Added "callback" variants of the "walkCrewman" and "loadActorAnim"
functions to simplify chains of calls in room-specific code.
  • Loading branch information...
Drenn1 authored and sev- committed Jun 22, 2018
1 parent 16042fa commit 08ead492d8ff338a469ca92881919d8ff22e12b3
@@ -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,13 +54,19 @@ struct Action : Common::Serializable {
byte b2;
byte b3;

void (Room::*roomFuncPtr)();

Action() {}
Action(int _type, int _b1, int _b2, int _b3)
: type((byte)_type),
b1((byte)_b1),
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; }
@@ -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;
}
}

@@ -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;
@@ -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 @@ struct Actor {
field62(),
triggerActionWhenAnimFinished(),
finishedAnimActionParam(),
finishedAnimCallback(),
//animationString2[8](),
field70(),
field72(),
@@ -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;
}
}

@@ -98,6 +98,7 @@ class Room {

// 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 @@ class Room {
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 @@ class Room {
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();
@@ -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[] = {
@@ -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);
Oops, something went wrong.

0 comments on commit 08ead49

Please sign in to comment.