Permalink
Browse files

STARTREK: Revamp of action callbacks.

Old system of putting a callback in an action wouldn't work since it
wasn't serializable. Now it seaches for an index corresponding to the
function pointer before constructing an action.
  • Loading branch information...
Drenn1 authored and sev- committed Jun 24, 2018
1 parent d8e255e commit a5c7d6ae11c255647e2026ae447e76f0ae52c67f
@@ -43,9 +43,7 @@ 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_CALLBACK = 255 // Custom action in ScummVM; calls a function in the Room class
ACTION_OPTIONS = 13 // Not really an action, but selectable from action menu
};

struct Action : Common::Serializable {
@@ -54,21 +52,13 @@ struct Action : Common::Serializable {
byte b2;
byte b3;

// Only used with ACTION_CALLBACK.
// TODO: Fix serialization. Can this even be serialized?
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; }
@@ -571,12 +571,6 @@ 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;
}
}

@@ -93,11 +93,8 @@ struct Actor {
// "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;
@@ -150,7 +147,6 @@ struct Actor {
field62(),
triggerActionWhenAnimFinished(),
finishedAnimActionParam(),
finishedAnimCallback(),
//animationString2[8](),
field70(),
field72(),
@@ -172,6 +172,23 @@ Common::Point Room::getBeamInPosition(int crewmanIndex) {
}


// For actions of type ACTION_FINISHED_ANIMATION or ACTION_FINISHED_WALKING, this takes
// a function pointer and returns the index corresponding to that callback.
// Creates a fatal error on failure.
int Room::findFunctionPointer(int action, void (Room::*funcPtr)()) {
assert(action == ACTION_FINISHED_ANIMATION || action == ACTION_FINISHED_WALKING);

for (int i = 0; i < _numRoomActions; i++) {
if (_roomActionList[i].action.type == action && _roomActionList[i].funcPtr == funcPtr)
return _roomActionList[i].action.b1;
}

if (action == ACTION_FINISHED_ANIMATION)
error("Couldn't find FINISHED_ANIMATION function pointer");
else
error("Couldn't find FINISHED_WALKING function pointer");
}

// Interface for room-specific code

void Room::loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y, uint16 finishedAnimActionParam) {
@@ -190,7 +207,6 @@ void Room::loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y,
if (finishedAnimActionParam != 0) {
actor->triggerActionWhenAnimFinished = true;
actor->finishedAnimActionParam = finishedAnimActionParam;
actor->finishedAnimCallback = nullptr;
}
}

@@ -211,8 +227,7 @@ void Room::loadActorAnimC(int actorIndex, Common::String anim, int16 x, int16 y,

if (funcPtr != nullptr) {
actor->triggerActionWhenAnimFinished = true;
actor->finishedAnimActionParam = 0;
actor->finishedAnimCallback = funcPtr;
actor->finishedAnimActionParam = findFunctionPointer(ACTION_FINISHED_ANIMATION, funcPtr);
}
}

@@ -330,7 +345,6 @@ void Room::walkCrewman(int actorIndex, int16 destX, int16 destY, uint16 finished
if (success && finishedAnimActionParam != 0) {
actor->triggerActionWhenAnimFinished = true;
actor->finishedAnimActionParam = finishedAnimActionParam;
actor->finishedAnimCallback = nullptr;
}
}

@@ -347,7 +361,7 @@ void Room::walkCrewmanC(int actorIndex, int16 destX, int16 destY, void (Room::*f
if (success && funcPtr != nullptr) {
actor->triggerActionWhenAnimFinished = true;
actor->finishedAnimActionParam = 0;
actor->finishedAnimCallback = funcPtr;
actor->finishedAnimActionParam = findFunctionPointer(ACTION_FINISHED_WALKING, funcPtr);
}
}

@@ -96,6 +96,8 @@ class Room {
int _numRoomActions;


int findFunctionPointer(int action, void (Room::*funcPtr)());

// Interface for room-specific code
void loadActorAnim(int actorIndex, Common::String anim, int16 x, int16 y, uint16 field66 = 0); // Cmd 0x00
void loadActorAnimC(int actorIndex, Common::String anim, int16 x, int16 y, void (Room::*funcPtr)());// Cmd 0x00
@@ -1113,6 +1113,8 @@ RoomAction love3ActionList[] = {
{ Action(ACTION_USE, OBJECT_IWRENCH, 0x21, 0), &Room::love3UseWrenchOnMonitor },

{ Action(ACTION_USE, OBJECT_IH2O, 0x21, 0), &Room::love3UseWaterOnMonitor },
{ Action(ACTION_FINISHED_WALKING, 14, 0, 0), &Room::love3ReachedMonitorToUseWater },
{ Action(ACTION_FINISHED_ANIMATION, 6, 0, 0), &Room::love3PouredWaterOnMonitor },

{ Action(ACTION_USE, OBJECT_KIRK, 0x20, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
{ Action(ACTION_USE, OBJECT_SPOCK, 0x20, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },
@@ -1124,28 +1126,59 @@ RoomAction love3ActionList[] = {
{ Action(ACTION_USE, OBJECT_REDSHIRT, 11, 0), &Room::love3UseCrewmanOnEngineeringPanelOrGrate },

{ Action(ACTION_USE, OBJECT_IWRENCH, 11, 0), &Room::love3UseWrenchOnGrate },
{ Action(ACTION_FINISHED_WALKING, 4, 0, 0), &Room::love3ReachedGateWithWrench },
{ Action(ACTION_FINISHED_ANIMATION, 7, 0, 0), &Room::love3OpenedOrClosedGrate },

{ 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_FINISHED_WALKING, 5, 0, 0), &Room::love3ReachedShaftUsingWater },
{ Action(ACTION_FINISHED_ANIMATION, 8, 0, 0), &Room::love3PouredWaterDownShaft },

{ Action(ACTION_USE, OBJECT_IN2O, 0x22, 0), &Room::love3UseNitrousOxideOnShaft },
{ Action(ACTION_FINISHED_WALKING, 6, 0, 0), &Room::love3ReachedShaftUsingNitrousOxide },
{ Action(ACTION_FINISHED_ANIMATION, 9, 0, 0), &Room::love3PouredNitrousOxideDownShaft },

{ Action(ACTION_USE, OBJECT_INH3, 0x22, 0), &Room::love3UseAmmoniaOnShaft },
{ Action(ACTION_FINISHED_WALKING, 7, 0, 0), &Room::love3ReachedShaftUsingAmmonia },
{ Action(ACTION_FINISHED_ANIMATION, 10, 0, 0), &Room::love3PouredAmmoniaDownShaft },

{ Action(ACTION_USE, OBJECT_IRLG, 0x22, 0), &Room::love3UseRomulanLaughingGasOnShaft },
{ Action(ACTION_FINISHED_WALKING, 8, 0, 0), &Room::love3ReachedShaftUsingRomulanLaughingGas },
{ Action(ACTION_FINISHED_ANIMATION, 11, 0, 0), &Room::love3PouredRomulanLaughingGasDownShaft },

{ Action(ACTION_GET, 10, 0, 0), &Room::love3GetWrench },
{ Action(ACTION_FINISHED_WALKING, 9, 0, 0), &Room::love3ReachedWrenchToGet },
{ Action(ACTION_FINISHED_ANIMATION, 12, 0, 0), &Room::love3PickedUpWrench },

{ Action(ACTION_GET, 12, 0, 0), &Room::love3GetGasTank },
{ Action(ACTION_FINISHED_WALKING, 10, 0, 0), &Room::love3ReachedGasTankToGet },

{ Action(ACTION_USE, OBJECT_IANTIGRA, 12, 0), &Room::love3UseAntigravOnGasTank },
{ Action(ACTION_FINISHED_WALKING, 11, 0, 0), &Room::love3ReachedGasTankUsingAntigrav },
{ Action(ACTION_FINISHED_ANIMATION, 13, 0, 0), &Room::love3PickedUpGasTank },

{ Action(ACTION_GET, 9, 0, 0), &Room::love3GetInsulation },
{ Action(ACTION_FINISHED_WALKING, 12, 0, 0), &Room::love3ReachedInsulationToGet },
{ Action(ACTION_FINISHED_ANIMATION, 14, 0, 0), &Room::love3PickedUpInsulation },
// TODO: common code
};

RoomAction love4ActionList[] = {
{ Action(ACTION_TICK, 1, 0, 0), &Room::love4Tick1 },
{ Action(ACTION_TICK, 10, 0, 0), &Room::love4Tick10 },

{ Action(ACTION_WALK, 8, 0, 0), &Room::love4WalkToDoor },
{ Action(ACTION_WALK, 0x20, 0, 0), &Room::love4WalkToDoor },
{ Action(ACTION_TOUCHED_HOTSPOT, 0, 0, 0), &Room::love4TouchedHotspot0 },
{ Action(ACTION_FINISHED_WALKING, 1, 0, 0), &Room::love4DoorOpenedOrReached },
{ Action(ACTION_FINISHED_ANIMATION, 1, 0, 0), &Room::love4DoorOpenedOrReached },

{ Action(ACTION_USE, OBJECT_KIRK, 0x21, 0), &Room::love4UseKirkOnLadder },
{ Action(ACTION_FINISHED_WALKING, 2, 0, 0), &Room::love4ReachedLadder },
{ Action(ACTION_USE, OBJECT_IPHASERS, 9, 0), &Room::love4UseStunPhaserOnRomulan },
{ Action(ACTION_USE, OBJECT_IPHASERS, 10, 0), &Room::love4UseStunPhaserOnRomulan },
{ Action(ACTION_USE, OBJECT_IPHASERS, 11, 0), &Room::love4UseStunPhaserOnRomulan },
@@ -1176,10 +1209,20 @@ RoomAction love4ActionList[] = {
{ Action(ACTION_USE, OBJECT_IMTRICOR, 12, 0), &Room::love4UseMTricorderOnRomulan },
{ Action(ACTION_USE, OBJECT_IMTRICOR, -1, 0), &Room::love4UseMTricorderAnywhere },
{ Action(ACTION_USE, OBJECT_ISTRICOR, -1, 0), &Room::love4UseSTricorderAnywhere },

{ Action(ACTION_USE, OBJECT_ICURE, 9, 0), &Room::love4UseCureOnRomulan },
{ Action(ACTION_USE, OBJECT_ICURE, 10, 0), &Room::love4UseCureOnRomulan },
{ Action(ACTION_USE, OBJECT_ICURE, 11, 0), &Room::love4UseCureOnRomulan },
{ Action(ACTION_USE, OBJECT_ICURE, 12, 0), &Room::love4UseCureOnRomulan },
{ Action(ACTION_FINISHED_WALKING, 3, 0, 0), &Room::love4MccoyReachedRomulan4 },
{ Action(ACTION_FINISHED_ANIMATION, 2, 0, 0), &Room::love4MccoyCuredRomulan4 },
{ Action(ACTION_FINISHED_WALKING, 4, 0, 0), &Room::love4MccoyReachedRomulan3 },
{ Action(ACTION_FINISHED_ANIMATION, 3, 0, 0), &Room::love4MccoyCuredRomulan3 },
{ Action(ACTION_FINISHED_WALKING, 5, 0, 0), &Room::love4MccoyReachedRomulan2 },
{ Action(ACTION_FINISHED_ANIMATION, 4, 0, 0), &Room::love4MccoyCuredRomulan2 },
{ Action(ACTION_FINISHED_WALKING, 6, 0, 0), &Room::love4MccoyReachedRomulan1 },
{ Action(ACTION_FINISHED_ANIMATION, 5, 0, 0), &Room::love4MccoyCuredRomulan1 },

{ Action(ACTION_USE, OBJECT_IH2O, 9, 0), &Room::love4UseWaterOnRomulan },
{ Action(ACTION_USE, OBJECT_IH2O, 10, 0), &Room::love4UseWaterOnRomulan },
{ Action(ACTION_USE, OBJECT_IH2O, 11, 0), &Room::love4UseWaterOnRomulan },
@@ -1216,6 +1259,9 @@ RoomAction love5ActionList[] = {
{ Action(ACTION_LOOK, 11, 0, 0), &Room::love5LookAtDrCheever },
{ Action(ACTION_LOOK, 9, 0, 0), &Room::love5LookAtPreax },
{ Action(ACTION_TALK, 9, 0, 0), &Room::love5TalkToPreax },
{ Action(ACTION_FINISHED_WALKING, 5, 0, 0), &Room::love5MccoyReachedSpockToCure },
{ Action(ACTION_FINISHED_ANIMATION, 6, 0, 0), &Room::love5MccoyCuredSpock },
{ Action(ACTION_FINISHED_WALKING, 6, 0, 0), &Room::love5CrewmanReachedBeamoutPosition },
{ Action(ACTION_TALK, 10, 0, 0), &Room::love5TalkToDrMarcus },
{ Action(ACTION_TALK, 11, 0, 0), &Room::love5TalkToDrCheever },
{ Action(ACTION_TALK, OBJECT_KIRK, 0, 0), &Room::love5TalkToKirk },
@@ -1231,9 +1277,16 @@ RoomAction love5ActionList[] = {
{ Action(ACTION_USE, OBJECT_IH2O, 9, 0), &Room::love5UseWaterOnPreax },
{ Action(ACTION_USE, OBJECT_ISAMPLE, 9, 0), &Room::love5UseCureSampleOnPreax },
{ Action(ACTION_USE, OBJECT_ICURE, 9, 0), &Room::love5UseCureOnPreax },
{ Action(ACTION_FINISHED_WALKING, 4, 0, 0), &Room::love5ReachedPreaxUsingCure },
{ Action(ACTION_FINISHED_ANIMATION, 5, 0, 0), &Room::love5CuredPreax },
{ Action(ACTION_USE, -1, 9, 0), &Room::love5UseAnythingOnPreax },
{ Action(ACTION_USE, OBJECT_KIRK, 10, 0), &Room::love5UseKirkOnMarcusOrCheever },
{ Action(ACTION_USE, OBJECT_KIRK, 11, 0), &Room::love5UseKirkOnMarcusOrCheever },
{ Action(ACTION_FINISHED_WALKING, 1, 0, 0), &Room::love5KirkReachedCheever },
{ Action(ACTION_FINISHED_ANIMATION, 2, 0, 0), &Room::love5KirkUntiedCheever },
{ Action(ACTION_FINISHED_WALKING, 2, 0, 0), &Room::love5KirkReachedMarcus },
{ Action(ACTION_FINISHED_ANIMATION, 3, 0, 0), &Room::love5KirkUntiedMarcus },
{ Action(ACTION_FINISHED_ANIMATION, 4, 0, 0), &Room::love5MarcusStoodUp },
// TODO: common code
};

@@ -459,12 +459,7 @@ void StarTrekEngine::updateActorAnimations() {
if (nextAnimFrame == actor->numAnimFrames - 1) {
actor->field62++;
if (actor->triggerActionWhenAnimFinished) {
if (actor->finishedAnimCallback != nullptr) {
addAction(Action(ACTION_CALLBACK, actor->finishedAnimCallback));
actor->finishedAnimCallback = nullptr;
}
else
addAction(Action(ACTION_FINISHED_ANIMATION, actor->finishedAnimActionParam, 0, 0));
addAction(Action(ACTION_FINISHED_ANIMATION, actor->finishedAnimActionParam, 0, 0));
}
}
}
@@ -535,12 +530,7 @@ void StarTrekEngine::updateActorAnimations() {
if (actor->iwSrcPosition == -1) {
if (actor->triggerActionWhenAnimFinished) {
actor->triggerActionWhenAnimFinished = false;
if (actor->finishedAnimCallback != nullptr) {
addAction(Action(ACTION_CALLBACK, actor->finishedAnimCallback));
actor->finishedAnimCallback = nullptr;
}
else
addAction(Action(ACTION_FINISHED_WALKING, actor->finishedAnimActionParam & 0xff, 0, 0));
addAction(Action(ACTION_FINISHED_WALKING, actor->finishedAnimActionParam & 0xff, 0, 0));
}

actor->sprite.bitmap.reset();

0 comments on commit a5c7d6a

Please sign in to comment.