aboutsummaryrefslogtreecommitdiff
path: root/engines/lastexpress
diff options
context:
space:
mode:
authorJulien Templier2010-10-21 23:39:48 +0000
committerJulien Templier2010-10-21 23:39:48 +0000
commitc35d23aa95d12e5b622d9c25558f91ddf5eb066f (patch)
treeaa34c609aa6064630553298463229b4d3aee22ab /engines/lastexpress
parenta621302a719d384560fd8f2765639a948ef0cee9 (diff)
downloadscummvm-rg350-c35d23aa95d12e5b622d9c25558f91ddf5eb066f.tar.gz
scummvm-rg350-c35d23aa95d12e5b622d9c25558f91ddf5eb066f.tar.bz2
scummvm-rg350-c35d23aa95d12e5b622d9c25558f91ddf5eb066f.zip
LASTEXPRESS: Implement 7 AI logic functions
svn-id: r53681
Diffstat (limited to 'engines/lastexpress')
-rw-r--r--engines/lastexpress/entities/coudert.cpp100
-rw-r--r--engines/lastexpress/entities/francois.cpp178
-rw-r--r--engines/lastexpress/entities/kahina.cpp98
-rw-r--r--engines/lastexpress/entities/milos.cpp101
-rw-r--r--engines/lastexpress/entities/mmeboutarel.cpp100
-rw-r--r--engines/lastexpress/entities/tatiana.cpp98
-rw-r--r--engines/lastexpress/shared.h1
7 files changed, 669 insertions, 7 deletions
diff --git a/engines/lastexpress/entities/coudert.cpp b/engines/lastexpress/entities/coudert.cpp
index 6093110c6c..d585205eb0 100644
--- a/engines/lastexpress/entities/coudert.cpp
+++ b/engines/lastexpress/entities/coudert.cpp
@@ -3124,7 +3124,105 @@ IMPLEMENT_FUNCTION(50, Coudert, function50)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(51, Coudert, function51)
- error("Coudert: callback function 51 not implemented!");
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionNone:
+ if (getState()->time > kTime2133000 && !getProgress().field_40) {
+ getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB);
+ getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand);
+ getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand);
+
+ setCallback(1);
+ setup_updateEntity(kCarRedSleeping, kPosition_2000);
+ }
+ break;
+
+ case kActionOpenDoor:
+ if (savepoint.param.intValue == kObjectCompartmentB)
+ getData()->entityPosition = kPosition_7500;
+
+ getSound()->playSound(kEntityPlayer, "LIB014");
+ getAction()->playAnimation(kEventCoudertGoingOutOfVassiliCompartment);
+ getEntities()->updateEntity(kEntityCoudert, kCarRedSleeping, kPosition_2000);
+ getScenes()->loadSceneFromObject(savepoint.param.intValue == kObjectCompartmentB ? kObjectCompartmentB : kObjectCompartmentA);
+ getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB, true);
+ getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand);
+ getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand);
+
+ setCallback(3);
+ setup_updateEntity(kCarRedSleeping, kPosition_2000);
+ break;
+
+ case kActionDefault:
+ getData()->car = kCarRedSleeping;
+ getData()->entityPosition = kPosition_7500;
+ getData()->location = kLocationOutsideCompartment;
+
+ getSavePoints()->push(kEntityCoudert, kEntityMax, kActionMaxFreeFromCage);
+
+ if (ENTITY_PARAM(0, 5)) {
+ ENTITY_PARAM(0, 5) = 0;
+
+ getSavePoints()->push(kEntityCoudert, kEntityMertens, kAction155853632);
+ getSavePoints()->push(kEntityCoudert, kEntityMertens, kActionEndSound);
+ }
+
+ if (ENTITY_PARAM(0, 3)) {
+ ENTITY_PARAM(0, 3) = 0;
+
+ getSavePoints()->push(kEntityCoudert, kEntityVerges, kAction155853632);
+ getSavePoints()->push(kEntityCoudert, kEntityVerges, kActionEndSound);
+ }
+
+ getEntities()->drawSequenceLeft(kEntityCoudert, "627Wb");
+ getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentB, true);
+ getSavePoints()->push(kEntityCoudert, kEntityTatiana, kAction154071333);
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ setCallback(2);
+ setup_function18();
+ break;
+
+ case 2:
+ case 4:
+ case 6:
+ setup_function45();
+ break;
+
+ case 3:
+ setCallback(4);
+ setup_function18();
+ break;
+
+ case 5:
+ setCallback(5);
+ setup_function18();
+ break;
+ }
+ break;
+
+ case kAction168316032:
+ getObjects()->update(kObjectCompartmentA, kEntityCoudert, kObjectLocationNone, kCursorNormal, kCursorHand);
+ getObjects()->update(kObjectCompartmentB, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorHand);
+ break;
+
+ case kAction235061888:
+ getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB, true);
+ getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand);
+ getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand);
+
+ setCallback(5);
+ setup_updateEntity(kCarRedSleeping, kPosition_2000);
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/francois.cpp b/engines/lastexpress/entities/francois.cpp
index 3bd95ca92b..40c1ae4a86 100644
--- a/engines/lastexpress/entities/francois.cpp
+++ b/engines/lastexpress/entities/francois.cpp
@@ -109,7 +109,92 @@ IMPLEMENT_FUNCTION_II(7, Francois, savegame, SavegameType, uint32)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION_II(8, Francois, updateEntity, CarIndex, EntityPosition)
- error("Francois: callback function 8 not implemented!");
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionNone:
+ if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) {
+ CALLBACK_ACTION();
+ } else {
+ if (!getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 2000)
+ || !getInventory()->hasItem(kItemFirebird)
+ || getEvent(kEventFrancoisShowEgg)
+ || getEvent(kEventFrancoisShowEggD)
+ || getEvent(kEventFrancoisShowEggNight)
+ || getEvent(kEventFrancoisShowEggNightD)) {
+ if (getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 2000)
+ && getInventory()->get(kItemBeetle)->location == kObjectLocation1
+ && !getEvent(kEventFrancoisShowBeetle)
+ && !getEvent(kEventFrancoisShowBeetleD))
+ getData()->inventoryItem = kItemMatchBox;
+ } else {
+ getData()->inventoryItem = kItemFirebird;
+ }
+
+ if (ENTITY_PARAM(0, 1)
+ && getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 1000)
+ && !getEntities()->isInsideCompartments(kEntityPlayer)
+ && !getEntities()->checkFields10(kEntityPlayer)) {
+ setCallback(1);
+ setup_savegame(kSavegameTypeEvent, kEventFrancoisTradeWhistle);
+ }
+ }
+ break;
+
+ case kAction1:
+ switch (savepoint.param.intValue) {
+ default:
+ break;
+
+ case 1:
+ setCallback(2);
+ setup_savegame(kSavegameTypeEvent, kEventFrancoisShowBeetle);
+ break;
+
+ case 18:
+ if (isNight())
+ getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisShowEggNightD : kEventFrancoisShowEggNight);
+ else
+ getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisShowEggD : kEventFrancoisShowEgg);
+
+ getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp);
+ break;
+ }
+ break;
+
+ case kActionExcuseMeCath:
+ case kActionExcuseMe:
+ getSound()->excuseMe(_entityIndex);
+ break;
+
+ case kActionDefault:
+ if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2))
+ CALLBACK_ACTION();
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisTradeWhistleD : kEventFrancoisTradeWhistle);
+ getInventory()->addItem(kItemWhistle);
+ getInventory()->removeItem(kItemMatchBox);
+ getInventory()->get(kItemBeetle)->location = kObjectLocation2;
+ getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp);
+ ENTITY_PARAM(0, 1) = 0;
+ break;
+
+ case 2:
+ getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisShowBeetleD : kEventFrancoisShowBeetle);
+ getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp);
+ getData()->inventoryItem = kItemNone;
+ break;
+ }
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
@@ -539,7 +624,96 @@ IMPLEMENT_FUNCTION(13, Francois, function13)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION_IIS(14, Francois, function14, ObjectIndex, EntityPosition)
- error("Francois: callback function 14 not implemented!");
+ // Expose parameters as IISS and ignore the default exposed parameters
+ EntityData::EntityParametersIISS *parameters = (EntityData::EntityParametersIISS*)_data->getCurrentParameters();
+
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionDefault:
+ strcpy((char *)&parameters->seq2, "605H");
+ strcat((char *)&parameters->seq2, (char *)&parameters->seq1);
+
+ setCallback(1);
+ setup_function9();
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ setCallback(2);
+ setup_updateEntity(kCarRedSleeping, (EntityPosition)parameters->param2);
+ break;
+
+ case 2:
+ if (getInventory()->get(kItemBeetle)->location == kObjectLocation3) {
+ getEntities()->drawSequenceLeft(kEntityFrancois, (char *)&parameters->seq2);
+ getEntities()->enterCompartment(kEntityFrancois, (ObjectIndex)parameters->param1, true);
+
+ setCallback(3);
+ setup_playSound("Fra2005A");
+ } else {
+ if (parameters->param2 >= kPosition_5790) {
+ setCallback(10);
+ setup_updateEntity(kCarRedSleeping, kPosition_9460);
+ } else {
+ setCallback(9);
+ setup_updateEntity(kCarRedSleeping, kPosition_540);
+ }
+ }
+ break;
+
+ case 3:
+ case 5:
+ setCallback(getCallback() == 3 ? 4 : 6);
+ setup_updateFromTime(rnd(450));
+ break;
+
+ case 4:
+ case 6:
+ setCallback(getCallback() == 4 ? 5 : 7);
+ setup_playSound(rnd(2) ? "Fra2005B" : "Fra2005C");
+ break;
+
+ case 7:
+ setCallback(8);
+ setup_updateFromTime(rnd(150));
+ break;
+
+ case 8:
+ getEntities()->exitCompartment(kEntityFrancois, (ObjectIndex)parameters->param1);
+ // Fallback to next case
+
+ case 9:
+ setCallback(10);
+ setup_updateEntity(kCarRedSleeping, kPosition_9460);
+ break;
+
+ case 10:
+ setCallback(11);
+ setup_updateFromTime(900);
+ break;
+
+ case 11:
+ setCallback(12);
+ setup_updateEntity(kCarRedSleeping, kPosition_5790);
+ break;
+
+ case 12:
+ setCallback(13);
+ setup_function10();
+ break;
+
+ case 13:
+ CALLBACK_ACTION();
+ break;
+ }
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp
index 881ac12700..1655e90394 100644
--- a/engines/lastexpress/entities/kahina.cpp
+++ b/engines/lastexpress/entities/kahina.cpp
@@ -1120,7 +1120,103 @@ IMPLEMENT_FUNCTION(25, Kahina, function25)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(26, Kahina, function26)
- error("Kahina: callback function 26 not implemented!");
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionDefault:
+ if (!getEvent(kEventAnnaBaggageArgument)) {
+ setCallback(1);
+ setup_function19(kCarRedSleeping, kPosition_8200);
+ break;
+ }
+
+ getScenes()->loadSceneFromItemPosition(kItemFirebird);
+ getInventory()->get(kItemFirebird)->location = kObjectLocation5;
+ getSavePoints()->push(kEntityKahina, kEntityKronos, kAction138085344);
+ getInventory()->setLocationAndProcess(kItemBriefcase, kObjectLocation2);
+ getProgress().field_78 = 1;
+
+ CALLBACK_ACTION();
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ if (getEntities()->checkFields19(kEntityPlayer, kCarGreenSleeping, kPosition_7850)) {
+ setCallback(2);
+ setup_function19(kCarRedSleeping, kPosition_9460);
+ } else {
+ setCallback(6);
+ setup_enterExitCompartment("616Aa", kObjectCompartmentA);
+ }
+ break;
+
+ case 2:
+ setCallback(3);
+ setup_updateFromTime(1800);
+ break;
+
+ case 3:
+ setCallback(4);
+ setup_function19(kCarRedSleeping, kPosition_8200);
+ break;
+
+ case 4:
+ if (getEntities()->checkFields19(kEntityPlayer, kCarGreenSleeping, kPosition_7850)) {
+ setCallback(5);
+ setup_function19(kCarRedSleeping, kPosition_9270);
+ } else {
+ setCallback(6);
+ setup_enterExitCompartment("616Aa", kObjectCompartmentA);
+ }
+ break;
+
+ case 5:
+ case 9:
+ getEntities()->clearSequences(kEntityKahina);
+
+ CALLBACK_ACTION();
+ break;
+
+ case 6:
+ getData()->location = kLocationInsideCompartment;
+ getEntities()->clearSequences(kEntityKahina);
+
+ getObjects()->update(kObjectCompartmentA, kEntityPlayer, getObjects()->get(kObjectCompartmentA).location, kCursorNormal, kCursorNormal);
+ getObjects()->update(kObject48, kEntityPlayer, getObjects()->get(kObject48).location, kCursorNormal, kCursorNormal);
+
+ setCallback(7);
+ setup_updateFromTime(900);
+ break;
+
+ case 7:
+ getObjects()->update(kObjectCompartmentA, kEntityPlayer, getObjects()->get(kObjectCompartmentA).location, kCursorHandKnock, kCursorHand);
+ getObjects()->update(kObject48, kEntityPlayer, getObjects()->get(kObject48).location, kCursorHandKnock, kCursorHand);
+
+ if (getInventory()->get(kItemFirebird)->location == kObjectLocation1 || getInventory()->get(kItemFirebird)->location == kObjectLocation2) {
+ getScenes()->loadSceneFromItemPosition(kItemFirebird);
+ getInventory()->get(kItemFirebird)->location = kObjectLocation5;
+ getSavePoints()->push(kEntityKahina, kEntityKronos, kAction138085344);
+ ENTITY_PARAM(0, 3) = 1;
+ }
+
+ setCallback(8);
+ setup_enterExitCompartment("616Ba", kObjectCompartmentA);
+ break;
+
+ case 8:
+ getData()->location = kLocationOutsideCompartment;
+
+ setCallback(9);
+ setup_updateEntity(kCarKronos, kPosition_9270);
+ break;
+ }
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp
index a3e4a962e3..092b0c9945 100644
--- a/engines/lastexpress/entities/milos.cpp
+++ b/engines/lastexpress/entities/milos.cpp
@@ -25,6 +25,8 @@
#include "lastexpress/entities/milos.h"
+#include "lastexpress/entities/vesna.h"
+
#include "lastexpress/game/action.h"
#include "lastexpress/game/entities.h"
#include "lastexpress/game/inventory.h"
@@ -973,7 +975,104 @@ IMPLEMENT_FUNCTION(24, Milos, function24)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(25, Milos, function25)
- error("Milos: callback function 25 not implemented!");
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionNone:
+ if (!getEvent(kEventMilosCompartmentVisitTyler) && !getProgress().field_54 && !ENTITY_PARAM(0, 4)) {
+ UPDATE_PARAM_PROC(params->param3, getState()->time, 13500)
+ getSavePoints()->push(kEntityMilos, kEntityVesna, kAction155913424);
+ params->param3 = 0;
+ UPDATE_PARAM_PROC_END
+ }
+
+ if (params->param1) {
+ UPDATE_PARAM(params->param4, getState()->timeTicks, 75);
+
+ params->param1 = 0;
+ params->param2 = 1;
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation1, kCursorNormal, kCursorNormal);
+ }
+
+ params->param4 = 0;
+ break;
+
+ case kActionKnock:
+ case kActionOpenDoor:
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, params->param1 ? kObjectLocation3 : kObjectLocation1, kCursorNormal, kCursorNormal);
+
+ if (params->param1) {
+ setCallback(5);
+ setup_playSound(rnd(2) ? "CAT1505" : "CAT1505A");
+ } else {
+ setCallback(savepoint.action == kActionKnock ? 1 : 2);
+ setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013");
+ }
+ break;
+
+ case kActionDefault:
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand);
+
+ if (!getEvent(kEventMilosCompartmentVisitTyler) && !getProgress().field_54 && !ENTITY_PARAM(0, 4))
+ getSavePoints()->push(kEntityMilos, kEntityVesna, kAction155913424);
+ break;
+
+ case kActionDrawScene:
+ if (params->param1 || params->param2) {
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand);
+
+ params->param1 = 0;
+ params->param2 = 0;
+ }
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ case 2:
+ if (getEntities()->isInsideCompartment(kEntityVesna, kCarRedSleeping, kPosition_3050)) {
+ setCallback(3);
+ setup_playSound("VES1015A");
+ break;
+ }
+
+ if (getEvent(kEventMilosCompartmentVisitTyler) || ENTITY_PARAM(0, 4)) {
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ break;
+ }
+
+ RESET_ENTITY_STATE(kEntityVesna, Vesna, setup_chapter3Handler);
+
+ getData()->location = kLocationInsideCompartment;
+
+ setCallback(4);
+ setup_savegame(kSavegameTypeEvent, kEventMilosCompartmentVisitTyler);
+ break;
+
+ case 3:
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation1, kCursorTalk, kCursorNormal);
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation1, kCursorHandKnock, kCursorHand);
+
+ params->param1 = 1;
+ break;
+
+ case 4:
+ getAction()->playAnimation(kEventMilosCompartmentVisitTyler);
+ getScenes()->loadSceneFromPosition(kCarRestaurant, 5);
+ getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ break;
+
+ case 5:
+ params->param1 = 0;
+ params->param2 = 1;
+ break;
+ }
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/mmeboutarel.cpp b/engines/lastexpress/entities/mmeboutarel.cpp
index 86acb90018..bf0066a911 100644
--- a/engines/lastexpress/entities/mmeboutarel.cpp
+++ b/engines/lastexpress/entities/mmeboutarel.cpp
@@ -796,7 +796,105 @@ IMPLEMENT_FUNCTION(23, MmeBoutarel, chapter4Handler)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(24, MmeBoutarel, function24)
- error("MmeBoutarel: callback function 24 not implemented!");
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionNone:
+ TIME_CHECK(kTime2470500, params->param4, setup_function25);
+
+ if (params->param2) {
+ UPDATE_PARAM(params->param5, getState()->timeTicks, 75);
+
+ params->param1 = 1;
+ params->param2 = 0;
+
+ getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal);
+ getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ }
+
+ params->param5 = 0;
+ break;
+
+ case kActionKnock:
+ case kActionOpenDoor:
+ getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal);
+ getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal);
+
+ if (params->param2) {
+ if (getInventory()->hasItem(kItemPassengerList)) {
+ setCallback(5);
+ setup_playSound(rnd(2) ? "CAT1510" : getSound()->wrongDoorCath());
+ } else {
+ setCallback(6);
+ setup_playSound(getSound()->wrongDoorCath());
+ }
+ } else {
+ ++params->param3;
+
+ setCallback(savepoint.action == kActionKnock ? 2 : 1);
+ setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013");
+ }
+ break;
+
+ case kActionDefault:
+ getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ break;
+
+ case kActionDrawScene:
+ if (params->param1 || params->param2) {
+ getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand);
+ params->param1 = 0;
+ params->param2 = 0;
+ }
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ case 2:
+ setCallback(params->param3 > 1 ? 3 : 4);
+ setup_playSound(params->param3 > 1 ? "MME1038C" : "MME1038");
+ break;
+
+ case 3:
+ case 4:
+ getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorTalk, kCursorNormal);
+ getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorTalk, kCursorNormal);
+ params->param2 = 1;
+ break;
+
+ case 5:
+ case 6:
+ params->param1 = 1;
+ params->param2 = 0;
+ break;
+
+ case 7:
+ getSavePoints()->push(kEntityMmeBoutarel, kEntityCoudert, kAction123199584);
+ break;
+
+ case 8:
+ getSavePoints()->push(kEntityMmeBoutarel, kEntityCoudert, kAction88652208);
+ break;
+ }
+ break;
+
+ case kAction122865568:
+ setCallback(8);
+ setup_playSound("Mme1151A");
+ break;
+
+ case kAction221683008:
+ setCallback(7);
+ setup_playSound("Mme1038");
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp
index 2c6f74dff5..4bd73c1ee0 100644
--- a/engines/lastexpress/entities/tatiana.cpp
+++ b/engines/lastexpress/entities/tatiana.cpp
@@ -607,7 +607,103 @@ IMPLEMENT_FUNCTION(21, Tatiana, function21)
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_FUNCTION(22, Tatiana, function22)
- error("Tatiana: callback function 22 not implemented!");
+ switch (savepoint.action) {
+ default:
+ break;
+
+ case kActionNone:
+ if (params->param1 == kTimeInvalid || getState()->time <= kTime1179000)
+ goto label_update;
+
+ UPDATE_PARAM_PROC_TIME(kTime1233000, (!getEvent(kEventTatianaAskMatchSpeakRussian) && !getEvent(kEventTatianaAskMatch) || getEntities()->isInGreenCarEntrance(kEntityPlayer)), params->param1, 0)
+label_update:
+ if (!getEvent(kEventTatianaAskMatchSpeakRussian)
+ && !getEvent(kEventTatianaAskMatch)
+ && getInventory()->hasItem(kItemMatchBox)
+ && getEntities()->isInGreenCarEntrance(kEntityPlayer)) {
+ getObjects()->update(kObject25, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorForward);
+ getObjects()->update(kObjectTrainTimeTable, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorForward);
+ }
+ UPDATE_PARAM_PROC_END
+
+ params->param1 = kTimeInvalid;
+
+ getObjects()->update(kObject25, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue);
+ getObjects()->update(kObjectTrainTimeTable, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue);
+ getEntities()->updatePositionExit(kEntityTatiana, kCarGreenSleeping, 70);
+ getEntities()->updatePositionExit(kEntityTatiana, kCarGreenSleeping, 71);
+
+ if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) {
+ getSound()->excuseMe(kEntityTatiana);
+
+ if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62))
+ getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72);
+ }
+
+ getData()->inventoryItem = kItemNone;
+
+ setup_function23();
+ break;
+
+ case kAction1:
+ getData()->inventoryItem = kItemNone;
+
+ setCallback(4);
+ setup_savegame(kSavegameTypeEvent, kEventTatianaGivePoem);
+ break;
+
+ case kActionOpenDoor:
+ setCallback(3);
+ setup_savegame(kSavegameTypeEvent, kEventTatianaAskMatchSpeakRussian);
+ break;
+
+ case kActionDefault:
+ getSavePoints()->push(kEntityTatiana, kEntityVassili, kAction122732000);
+
+ setCallback(1);
+ setup_function15();
+ break;
+
+ case kActionCallback:
+ switch (getCallback()) {
+ default:
+ break;
+
+ case 1:
+ setCallback(2);
+ setup_updateEntity(kCarGreenSleeping, kPosition_540);
+ break;
+
+ case 2:
+ if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) {
+ getSound()->excuseMe(kEntityTatiana);
+
+ if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62))
+ getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72);
+ }
+
+ getEntities()->drawSequenceLeft(kEntityTatiana, "306B");
+ getEntities()->updatePositionEnter(kEntityTatiana, kCarGreenSleeping, 70);
+ getEntities()->updatePositionEnter(kEntityTatiana, kCarGreenSleeping, 71);
+ break;
+
+ case 3:
+ getAction()->playAnimation(getEvent(kEventAlexeiSalonVassili) ? kEventTatianaAskMatchSpeakRussian : kEventTatianaAskMatch);
+ getScenes()->loadSceneFromPosition(kCarGreenSleeping, 62);
+ getData()->inventoryItem = kItemParchemin;
+
+ getObjects()->update(kObject25, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue);
+ getObjects()->update(kObjectTrainTimeTable, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue);
+ break;
+
+ case 4:
+ getAction()->playAnimation(kEventTatianaGivePoem);
+ getInventory()->removeItem(kItemParchemin);
+ getScenes()->processScene();
+ break;
+ }
+ break;
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h
index c4c05e68ed..b5d81aa53e 100644
--- a/engines/lastexpress/shared.h
+++ b/engines/lastexpress/shared.h
@@ -85,6 +85,7 @@ enum TimeValue {
kTime1225800 = 1225800,
kTimeCityBarLeDuc = 1228500,
kTimeExitBarLeDuc = 1231200,
+ kTime1233000 = 1233000,
kTime1242000 = 1242000,
kTime1260000 = 1260000,
kTimeCityNancy = 1303200,