diff options
Diffstat (limited to 'engines/lastexpress/entities')
71 files changed, 49625 insertions, 0 deletions
diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp new file mode 100644 index 0000000000..d46bb325be --- /dev/null +++ b/engines/lastexpress/entities/abbot.cpp @@ -0,0 +1,1910 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/abbot.h" + +#include "lastexpress/entities/verges.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Abbot::Abbot(LastExpressEngine *engine) : Entity(engine, kEntityAbbot) { + ADD_CALLBACK_FUNCTION(Abbot, reset); + ADD_CALLBACK_FUNCTION(Abbot, draw); + ADD_CALLBACK_FUNCTION(Abbot, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Abbot, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Abbot, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Abbot, draw2); + ADD_CALLBACK_FUNCTION(Abbot, updateFromTime); + ADD_CALLBACK_FUNCTION(Abbot, updateFromTicks); + ADD_CALLBACK_FUNCTION(Abbot, playSound); + ADD_CALLBACK_FUNCTION(Abbot, savegame); + ADD_CALLBACK_FUNCTION(Abbot, updateEntity); + ADD_CALLBACK_FUNCTION(Abbot, callSavepoint); + ADD_CALLBACK_FUNCTION(Abbot, updatePosition); + ADD_CALLBACK_FUNCTION(Abbot, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Abbot, chapter1); + ADD_CALLBACK_FUNCTION(Abbot, chapter2); + ADD_CALLBACK_FUNCTION(Abbot, chapter3); + ADD_CALLBACK_FUNCTION(Abbot, chapter3Handler); + ADD_CALLBACK_FUNCTION(Abbot, function19); + ADD_CALLBACK_FUNCTION(Abbot, function20); + ADD_CALLBACK_FUNCTION(Abbot, function21); + ADD_CALLBACK_FUNCTION(Abbot, function22); + ADD_CALLBACK_FUNCTION(Abbot, function23); + ADD_CALLBACK_FUNCTION(Abbot, function24); + ADD_CALLBACK_FUNCTION(Abbot, function25); + ADD_CALLBACK_FUNCTION(Abbot, function26); + ADD_CALLBACK_FUNCTION(Abbot, function27); + ADD_CALLBACK_FUNCTION(Abbot, function28); + ADD_CALLBACK_FUNCTION(Abbot, function29); + ADD_CALLBACK_FUNCTION(Abbot, function30); + ADD_CALLBACK_FUNCTION(Abbot, function31); + ADD_CALLBACK_FUNCTION(Abbot, function32); + ADD_CALLBACK_FUNCTION(Abbot, function33); + ADD_CALLBACK_FUNCTION(Abbot, function34); + ADD_CALLBACK_FUNCTION(Abbot, function35); + ADD_CALLBACK_FUNCTION(Abbot, function36); + ADD_CALLBACK_FUNCTION(Abbot, function37); + ADD_CALLBACK_FUNCTION(Abbot, function38); + ADD_CALLBACK_FUNCTION(Abbot, chapter4); + ADD_CALLBACK_FUNCTION(Abbot, function40); + ADD_CALLBACK_FUNCTION(Abbot, chapter4Handler); + ADD_CALLBACK_FUNCTION(Abbot, function42); + ADD_CALLBACK_FUNCTION(Abbot, function43); + ADD_CALLBACK_FUNCTION(Abbot, function44); + ADD_CALLBACK_FUNCTION(Abbot, function45); + ADD_CALLBACK_FUNCTION(Abbot, function46); + ADD_CALLBACK_FUNCTION(Abbot, drinkAfterDefuse); + ADD_CALLBACK_FUNCTION(Abbot, function48); + ADD_CALLBACK_FUNCTION(Abbot, pickBomb); + ADD_CALLBACK_FUNCTION(Abbot, chapter5); + ADD_CALLBACK_FUNCTION(Abbot, chapter5Handler); + ADD_CALLBACK_FUNCTION(Abbot, function52); + ADD_CALLBACK_FUNCTION(Abbot, function53); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Abbot, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Abbot, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Abbot, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(4, Abbot, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_6470, kPosition_6130, kCarRedSleeping, kObjectCompartmentC, true, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Abbot, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SSI(6, Abbot, draw2, EntityIndex) + Entity::draw2(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(7, Abbot, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(8, Abbot, updateFromTicks, uint32) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(9, Abbot, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Abbot, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(11, Abbot, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 18) || getEntities()->isPlayerPosition(kCarRedSleeping, 18)) { + getSound()->excuseMe(kEntityAbbot); + } else { + if (getEvent(kEventAbbotIntroduction)) + getSound()->playSound(kEntityPlayer, "CAT1013"); + else + getSound()->excuseMeCath(); + } + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(12, Abbot, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(13, Abbot, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Abbot, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Abbot, chapter1) + if (savepoint.action == kActionDefault) + getSavePoints()->addData(kEntityAbbot, kAction203073664, 0); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Abbot, chapter2) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityAbbot); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Abbot, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAbbot); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + getData()->clothes = kClothesDefault; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Abbot, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_draw("804DD"); + break; + + case 2: + getSavePoints()->push(kEntityAbbot, kEntityCooks, kAction236976550); + getEntities()->drawSequenceRight(kEntityAbbot, "804DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAbbot); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 4: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(5); + setup_enterExitCompartment("617AC", kObjectCompartmentC); + break; + + case 5: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + + setup_function19(); + break; + } + break; + + case kAction192054567: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Abbot, function19) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime1953000) { + if (!params->param1) { + params->param1 = 1; + setCallback(3); + setup_playSound("MrB3010"); + } + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAbbot, "508A"); + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122358304); + + setCallback(1); + setup_playSound("Abb3010"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateFromTime(900); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityAbbot, "508B"); + break; + + case 3: + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122288808); + setup_function20(); + break; + } + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Abbot, function20) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime1966500 && getEntities()->isInRestaurant(kEntityBoutarel)) + setup_function21(); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAbbot, "509A"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Abbot, function21) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_draw("509B"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_enterExitCompartment("617Mc", kObjectCompartmentC); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_draw("804US"); + break; + + case 5: + getEntities()->drawSequenceRight(kEntityAbbot, "029J"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityAbbot); + + setCallback(6); + setup_callbackActionOnDirection(); + break; + + case 6: + getEntities()->drawSequenceLeft(kEntityAbbot, "029H"); + getSavePoints()->push(kEntityAbbot, kEntityPascale, kAction207769280); + break; + + case 7: + setup_function22(); + break; + } + break; + + case kAction122288808: + getSavePoints()->push(kEntityAbbot, kEntityTables4, kAction136455232); + getData()->location = kLocationInsideCompartment; + + setCallback(7); + setup_draw("029B"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Abbot, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_SAVEPOINT(kTime1971000, params->param1, kEntityAbbot, kEntityServers0, kAction218586752); + + if (getState()->time > kTime1989000 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->inventoryItem = kItemNone; + setup_function23(); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAbbotIntroduction); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAbbot, "029E"); + if (!getEvent(kEventAbbotIntroduction)) + getData()->inventoryItem = (InventoryItem)kCursorProcess; + break; + + case kActionCallback: + if (getCallback() != 1) + break; + + getAction()->playAnimation(kEventAbbotIntroduction); + getSound()->playSound(kEntityPlayer, "LIB036"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityAbbot, "029E"); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAbbot, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Abbot, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + getEntities()->updatePositionEnter(kEntityAbbot, kCarRestaurant, 67); + + setCallback(1); + setup_callSavepoint("029F", kEntityTables4, kActionDrawTablesWithChairs, "029G"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 67); + getSavePoints()->push(kEntityAbbot, kEntityServers0, kAction270068760); + getSavePoints()->push(kEntityAbbot, kEntityAnna, kAction238936000); + getEntities()->drawSequenceRight(kEntityAbbot, "804DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAbbot); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment2("617Cc", kObjectCompartmentC); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + + setup_function24(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Abbot, function24) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->time, 900); + + setup_function25(); + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (savepoint.action == kActionKnock) { + setCallback(1); + setup_playSound("LIB012"); + } else { + setCallback(2); + setup_playSound("LIB013"); + } + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAbbot); + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound("Abb3001"); + break; + + case 3: + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Abbot, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("617Dc", kObjectCompartmentC); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_updatePosition("115A", kCarRestaurant, 56); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + getScenes()->loadSceneFromItemPosition(kItem3); + + setup_function26(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Abbot, function26) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->time, 4500); + + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) + setup_function27(); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAbbot, kEntityKronos, kAction157159392); + getEntities()->drawSequenceLeft(kEntityAbbot, "115B"); + break; + + case kAction101169422: + params->param1 = 1; + break; + + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Abbot, function27) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updatePosition("115C", kCarRestaurant, 56); + break; + + case 2: + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 3: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(4); + setup_enterExitCompartment("617Ac", kObjectCompartmentC); + break; + + case 4: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + + setup_function28(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Abbot, function28) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime2052000, params->param1, 1, setup_function29); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122358304); + getEntities()->drawSequenceLeft(kEntityAbbot, "508A"); + + setCallback(1); + setup_playSound("abb3013"); + break; + + case kActionCallback: + if (getCallback() == 1) + getEntities()->drawSequenceLeft(kEntityAbbot, "508B"); + break; + + case kAction222609266: + setup_function30(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Abbot, function29) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122288808); + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(1); + setup_enterExitCompartment("617Bc", kObjectCompartmentC); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 2: + setCallback(3); + setup_updateFromTicks(450); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + + case 4: + setCallback(5); + setup_updateFromTime(225); + break; + + case 5: + setCallback(6); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 6: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(7); + setup_enterExitCompartment("617Ac", kObjectCompartmentC); + break; + + case 7: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122358304); + getEntities()->drawSequenceLeft(kEntityAbbot, "508B"); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Abbot, function30) +switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_playSound("Abb3030"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122288808); + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(2); + setup_enterExitCompartment("617Bc", kObjectCompartmentC); + break; + + case 2: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_updatePosition("115A", kCarRestaurant, 56); + break; + + case 5: + getScenes()->loadSceneFromItemPosition(kItem3); + getData()->location = kLocationInsideCompartment; + + setup_function31(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Abbot, function31) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param4 != kTimeInvalid && params->param2 < getState()->time) { + if (getState()->time < getState()->time) { + params->param4 = kTimeInvalid; + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + } else { + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param4) + params->param4 = getState()->time + 450; + + if (params->param4 < getState()->time) { + params->param4 = kTimeInvalid; + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + } + } + } + + if (!params->param1) + break; + + UPDATE_PARAM(params->param5, getState()->time, 450); + + setCallback(6); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionDefault: + params->param2 = getState()->time + 4500; + params->param3 = getState()->time + 18000; + + getEntities()->drawSequenceLeft(kEntityAbbot, "115B"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updatePosition("115E", kCarRestaurant, 56); + break; + + case 2: + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + getSavePoints()->push(kEntityAbbot, kEntityAlexei, kAction122358304); + getSound()->playSound(kEntityAbbot, "Abb3020"); + + setCallback(3); + setup_updatePosition("125A", kCarRestaurant, 52); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAbbot, "125B"); + + setCallback(4); + setup_playSound("Abb3021"); + break; + + case 4: + getSound()->playSound(kEntityAbbot, "Abb3023"); + getEntities()->updatePositionEnter(kEntityAbbot, kCarRestaurant, 52); + + setCallback(5); + setup_draw2("125C1", "125C2", kEntityAlexei); + break; + + case 5: + getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 52); + getEntities()->drawSequenceLeft(kEntityAbbot, "125D"); + getSavePoints()->push(kEntityAbbot, kEntityAlexei, kAction122288808); + params->param1 = 1; + + UPDATE_PARAM(params->param5, getState()->time, 450); + + setCallback(6); + setup_callbackActionRestaurantOrSalon(); + break; + + case 6: + getData()->location = kLocationOutsideCompartment; + + setCallback(7); + setup_updatePosition("125E", kCarRestaurant, 52); + break; + + case 7: + setup_function32(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Abbot, function32) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(1); + setup_enterExitCompartment("617Ac", kObjectCompartmentC); + break; + + case 2: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122358304); + + setup_function33(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Abbot, function33) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 != kTimeInvalid && getState()->time > kTime2115000) { + if (getState()->time <= kTime2124000) { + if (!getEntities()->isDistanceBetweenEntities(kEntityAbbot, kEntityPlayer, 2000) || !params->param1) + params->param1 = getState()->time; + + if (params->param1 >= getState()->time) + break; + } + + params->param1 = kTimeInvalid; + + setCallback(1); + setup_playSound("Abb3014"); + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAbbot, "508A"); + break; + + case kActionCallback: + if (getCallback() == 1) + getEntities()->drawSequenceLeft(kEntityAbbot, "508B"); + break; + + case kAction123712592: + setup_function34(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Abbot, function34) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_playSound("Abb3031"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122288808); + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(2); + setup_enterExitCompartment("617Bc", kObjectCompartmentC); + break; + + case 2: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_updatePosition("115A", kCarRestaurant, 56); + break; + + case 5: + getScenes()->loadSceneFromItemPosition(kItem3); + + getData()->location = kLocationInsideCompartment; + setup_function35(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Abbot, function35) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 == kTimeInvalid) + break; + + if (params->param1 >= getState()->time) { + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param2) + params->param2 = getState()->time + 450; + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + + getSavePoints()->push(kEntityAbbot, kEntityAugust, kAction136196244); + + setCallback(1); + setup_updateFromTime(0); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAbbot, "115B"); + params->param1 = getState()->time + 9000; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + getSound()->playSound(kEntityAbbot, "Abb3040", SoundManager::kFlagInvalid, 45); + getEntities()->updatePositionEnter(kEntityAbbot, kCarRestaurant, 57); + + setCallback(3); + setup_callSavepoint("121A", kEntityAugust, kAction122358304, "BOGUS"); + break; + + case 3: + getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 57); + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + getData()->location = kLocationInsideCompartment; + + setup_function36(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Abbot, function36) + switch (savepoint.action) { + default: + break; + + case kActionNone: + switch (params->param2) { + default: + break; + + case 1: + if (params->param3 == kTimeInvalid) + break; + + if (params->param1 >= getState()->time) { + + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param3) + params->param3 = getState()->time + 675; + + if (params->param3 >= getState()->time) + break; + } + + params->param3 = kTimeInvalid; + + getSound()->playSound(kEntityAbbot, "Abb3041"); + break; + + case 2: + UPDATE_PARAM(params->param4, getState()->time, 900); + + getSound()->playSound(kEntityAbbot, "Abb3042"); + break; + + case 3: + getSound()->playSound(kEntityAbbot, "Abb3043"); + getEntities()->updatePositionEnter(kEntityAbbot, kCarRestaurant, 57); + + setCallback(1); + setup_callSavepoint("121D", kEntityAugust, kAction122288808, "BOGUS"); + break; + } + break; + + case kActionEndSound: + ++params->param2; + break; + + case kActionDefault: + params->param1 = getState()->time + 4500; + getEntities()->drawSequenceLeft(kEntityAbbot, "121B"); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRestaurant, 57)) + getScenes()->loadSceneFromPosition(kCarRestaurant, 50); + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 57); + setup_function37(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Abbot, function37) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(2); + setup_enterExitCompartment("617Ac", kObjectCompartmentC); + break; + + case 2: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction122358304); + + setup_function38(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Abbot, function38) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAbbot, "508A"); + + setCallback(1); + setup_playSound("Abb3014A"); + break; + + case kActionCallback: + if (getCallback() == 1) + getEntities()->drawSequenceLeft(kEntityAbbot, "508B"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Abbot, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAbbot); + + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 1) = 0; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(40, Abbot, function40, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->updateEntity(kEntityAbbot, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + } else if (!getEvent(kEventAbbotInvitationDrink) + && getEntities()->isDistanceBetweenEntities(kEntityAbbot, kEntityPlayer, 1000) + && !getEntities()->isInsideCompartments(kEntityPlayer) + && !getEntities()->checkFields10(kEntityPlayer)) { + + if (getData()->car == kCarGreenSleeping || getData()->car == kCarRedSleeping) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAbbotInvitationDrink); + } + } + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityAbbot, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAbbotInvitationDrink); + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Abbot, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_SAVEPOINT(kTime2358000, params->param1, kEntityAbbot, kEntityServers0, kAction218128129); + + if (getState()->time > kTime2389500 && getEntities()->isSomebodyInsideRestaurantOrSalon()) + setup_function42(); + + break; + + case kActionDefault: + getSavePoints()->push(kEntityAbbot, kEntityTables4, kAction136455232); + getEntities()->drawSequenceLeft(kEntityAbbot, "029E"); + getData()->location = kLocationInsideCompartment; + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityAbbot, "029E"); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAbbot, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Abbot, function42) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 67); + + setCallback(1); + setup_callSavepoint("029F", kEntityTables4, kActionDrawTablesWithChairs, "029G"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 67); + getSavePoints()->push(kEntityAbbot, kEntityServers0, kAction270068760); + getEntities()->drawSequenceRight(kEntityAbbot, "804DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAbbot); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment2("617Cc", kObjectCompartmentC); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityAbbot); + + setup_function43(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, Abbot, function43) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 && params->param4 != kTimeInvalid && params->param2 < getState()->time) { + if (getState()->time < kTime2452500) { + params->param4 = kTimeInvalid; + + setCallback(1); + setup_playSound("Abb4002"); + break; + } else { + if (!getEntities()->isDistanceBetweenEntities(kEntityAbbot, kEntityPlayer, 1000) || getSound()->isBuffered(kEntityBoutarel) || !params->param4) + params->param4 = getState()->time + 450; + + if (params->param4 < getState()->time) { + params->param4 = kTimeInvalid; + + setCallback(1); + setup_playSound("Abb4002"); + break; + } + } + } + +label_callback_1: + TIME_CHECK(kTime2466000, params->param5, setup_function44); + + if (params->param3) { + UPDATE_PARAM(params->param6, getState()->timeTicks, 75); + + params->param2 = 1; + params->param3 = 0; + + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param6 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (params->param3) { + setCallback(savepoint.param.intValue == 50 ? 5 : 6); + setup_playSound(savepoint.param.intValue == 50 ? getSound()->justAMinuteCath() : getSound()->wrongDoorCath()); + } else { + setCallback(savepoint.action == kActionKnock ? 2 : 3); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param2 || params->param3) { + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param2 = 0; + params->param3 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + case 3: + setCallback(4); + setup_playSound("Abb3001"); + break; + + case 4: + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObject50, kEntityAbbot, kObjectLocation1, kCursorTalk, kCursorNormal); + + params->param3 = 1; + break; + + case 5: + case 6: + params->param2 = 1; + params->param3 = 0; + break; + } + break; + + case kAction101687594: + params->param1 = 1; + break; + + case kAction159003408: + params->param1 = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Abbot, function44) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityAbbot); + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kAction104060776: + setup_function45(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, Abbot, function45) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6471; + getData()->car = kCarRedSleeping; + getData()->location = kLocationOutsideCompartment; + + RESET_ENTITY_STATE(kEntityVerges, Verges, setup_function38); + + getEntities()->drawSequenceLeft(kEntityAbbot, "617Ec"); + getEntities()->enterCompartment(kEntityAbbot, kObjectCompartmentC, true); + + setCallback(1); + setup_playSound("Abb4010"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("617Kc", kObjectCompartmentC); + break; + + case 2: + getEntities()->exitCompartment(kEntityAbbot, kObjectCompartmentC, true); + getSavePoints()->push(kEntityAbbot, kEntityVerges, kAction125233040); + + setup_function46(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Abbot, function46) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6471; + + setCallback(1); + setup_function40(kCarRestaurant, kPosition_850); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_drinkAfterDefuse(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, Abbot, drinkAfterDefuse) + switch (savepoint.action) { + default: + break; + + case kAction1: + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventAbbotDrinkGiveDetonator); + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_draw("126A"); + break; + + case 2: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAbbot, "126B"); + getData()->inventoryItem = kItemBomb; + break; + + case 3: + getAction()->playAnimation(kEventAbbotDrinkGiveDetonator); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Abbot, function48) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(0, 1)) + getData()->inventoryItem = kItemInvalid; + + UPDATE_PARAM_PROC(params->param1, getState()->time, 1800) + getData()->inventoryItem = kItemNone; + + setCallback(4); + setup_updatePosition("126C", kCarRedSleeping, 52); + UPDATE_PARAM_PROC_END + + TIME_CHECK_CALLBACK_INVENTORY(kTime2533500, params->param2, 5, setup_callbackActionRestaurantOrSalon); + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(9); + setup_savegame(kSavegameTypeEvent, kEventAbbotDrinkDefuse); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_850; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + + getSavePoints()->push(kEntityAbbot, kEntityVerges, kAction125233040); + + setCallback(1); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updatePosition("126A", kCarRestaurant, 52); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAbbot, "126B"); + break; + + case 4: + if (!getEvent(kEventAbbotDrinkDefuse) && ENTITY_PARAM(0, 1)) + getData()->inventoryItem = kItemInvalid; + + getEntities()->drawSequenceLeft(kEntityAbbot, "126B"); + params->param1 = 0; + + TIME_CHECK_CALLBACK_INVENTORY(kTime2533500, params->param2, 5, setup_callbackActionRestaurantOrSalon); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + + setCallback(6); + setup_updatePosition("126D", kCarRestaurant, 52); + break; + + case 6: + setCallback(7); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment2("617Cc", kObjectCompartmentC); + break; + + case 8: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityAbbot); + + setup_function44(); + break; + + case 9: + getAction()->playAnimation(kEventAbbotDrinkDefuse); + getEntities()->drawSequenceLeft(kEntityAbbot, "126B"); + getSavePoints()->push(kEntityAbbot, kEntityAnna, kAction100969180); + getScenes()->loadSceneFromPosition(kCarRestaurant, 58); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(49, Abbot, pickBomb) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->timeTicks, 150); + + getSavePoints()->push(kEntityAbbot, kEntityAbbot, kAction157489665); + break; + + case kActionKnock: + if (!getSound()->isBuffered("LIB012", true)) + getSound()->playSound(kEntityPlayer, "LIB012"); + break; + + case kActionOpenDoor: + case kAction157489665: + getSavePoints()->push(kEntityAbbot, kEntityTatiana, kAction238790488); + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + + case kActionDefault: + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + + getSavePoints()->call(kEntityAbbot, kEntityTables4, kActionDrawTablesWithChairs, "029G"); + getSavePoints()->push(kEntityAbbot, kEntityServers0, kAction270068760); + getSavePoints()->push(kEntityAbbot, kEntityBoutarel, kAction125039808); + getObjects()->update(kObjectCompartment2, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(getObjects()->get(kObjectCompartment2).location2 < kObjectLocation2 ? kEventAbbotWrongCompartmentBed : kEventAbbotWrongCompartment); + getEntities()->updateEntity(kEntityAbbot, kCarRedSleeping, kPosition_6470); + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadSceneFromObject(kObjectCompartment2, true); + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment2("617Cc", kObjectCompartmentC); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityAbbot); + getObjects()->update(kObjectCompartmentC, kEntityAbbot, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setup_function43(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(50, Abbot, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAbbot); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + getData()->clothes = kClothesDefault; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(51, Abbot, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function52(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(52, Abbot, function52) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAbbot); + + getData()->entityPosition = kPositionNone; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarNone; + break; + + case kAction135600432: + setup_function53(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(53, Abbot, function53) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getInventory()->setLocationAndProcess(kItem25, kObjectLocation1); + getSavePoints()->push(kEntityAbbot, kEntityAnna, kAction158480160); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventLocomotiveAbbotGetSomeRest); + getScenes()->processScene(); + break; + + case 2: + getAction()->playAnimation(kEventLocomotiveAbbotShoveling); + getScenes()->processScene(); + break; + } + break; + + case kAction168646401: + if (!getEvent(kEventLocomotiveAbbotGetSomeRest)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventLocomotiveAbbotGetSomeRest); + break; + } + + if (!getEvent(kEventLocomotiveAbbotShoveling)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventLocomotiveAbbotShoveling); + break; + } + + getAction()->playAnimation(kEventLocomotiveAbbotShoveling); + getScenes()->processScene(); + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/abbot.h b/engines/lastexpress/entities/abbot.h new file mode 100644 index 0000000000..4637fbd817 --- /dev/null +++ b/engines/lastexpress/entities/abbot.h @@ -0,0 +1,225 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ABBOT_H +#define LASTEXPRESS_ABBOT_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Abbot : public Entity { +public: + Abbot(LastExpressEngine *engine); + ~Abbot() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Draws the entity along with another one + * + * @param sequence1 The sequence to draw + * @param sequence2 The sequence to draw for the second entity + * @param entity The EntityIndex of the second entity + */ + DECLARE_FUNCTION_3(draw2, const char* sequence1, const char* sequence2, EntityIndex entity) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates parameter 2 using ticks value + * + * @param ticks The number of ticks to add + */ + DECLARE_FUNCTION_1(updateFromTicks, uint32 ticks) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + DECLARE_FUNCTION(function30) + DECLARE_FUNCTION(function31) + DECLARE_FUNCTION(function32) + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + DECLARE_FUNCTION(function36) + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * ??? + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(function40, CarIndex car, EntityPosition position) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + DECLARE_FUNCTION(function42) + DECLARE_FUNCTION(function43) + DECLARE_FUNCTION(function44) + DECLARE_FUNCTION(function45) + DECLARE_FUNCTION(function46) + DECLARE_FUNCTION(drinkAfterDefuse) + DECLARE_FUNCTION(function48) + DECLARE_FUNCTION(pickBomb) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + DECLARE_FUNCTION(function52) + DECLARE_FUNCTION(function53) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ABBOT_H diff --git a/engines/lastexpress/entities/alexei.cpp b/engines/lastexpress/entities/alexei.cpp new file mode 100644 index 0000000000..30e1c4384b --- /dev/null +++ b/engines/lastexpress/entities/alexei.cpp @@ -0,0 +1,1897 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/alexei.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Alexei::Alexei(LastExpressEngine *engine) : Entity(engine, kEntityAlexei) { + ADD_CALLBACK_FUNCTION(Alexei, reset); + ADD_CALLBACK_FUNCTION(Alexei, playSound); + ADD_CALLBACK_FUNCTION(Alexei, updateFromTicks); + ADD_CALLBACK_FUNCTION(Alexei, draw); + ADD_CALLBACK_FUNCTION(Alexei, updatePosition); + ADD_CALLBACK_FUNCTION(Alexei, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Alexei, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Alexei, callSavepoint); + ADD_CALLBACK_FUNCTION(Alexei, savegame); + ADD_CALLBACK_FUNCTION(Alexei, updateEntity); + ADD_CALLBACK_FUNCTION(Alexei, draw2); + ADD_CALLBACK_FUNCTION(Alexei, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Alexei, function13); + ADD_CALLBACK_FUNCTION(Alexei, function14); + ADD_CALLBACK_FUNCTION(Alexei, function15); + ADD_CALLBACK_FUNCTION(Alexei, function16); + ADD_CALLBACK_FUNCTION(Alexei, chapter1); + ADD_CALLBACK_FUNCTION(Alexei, chapter1Handler); + ADD_CALLBACK_FUNCTION(Alexei, function19); + ADD_CALLBACK_FUNCTION(Alexei, function20); + ADD_CALLBACK_FUNCTION(Alexei, function21); + ADD_CALLBACK_FUNCTION(Alexei, function22); + ADD_CALLBACK_FUNCTION(Alexei, function23); + ADD_CALLBACK_FUNCTION(Alexei, function24); + ADD_CALLBACK_FUNCTION(Alexei, function25); + ADD_CALLBACK_FUNCTION(Alexei, function26); + ADD_CALLBACK_FUNCTION(Alexei, function27); + ADD_CALLBACK_FUNCTION(Alexei, chapter2); + ADD_CALLBACK_FUNCTION(Alexei, chapter2Handler); + ADD_CALLBACK_FUNCTION(Alexei, function30); + ADD_CALLBACK_FUNCTION(Alexei, function31); + ADD_CALLBACK_FUNCTION(Alexei, chapter3); + ADD_CALLBACK_FUNCTION(Alexei, chapter3Handler); + ADD_CALLBACK_FUNCTION(Alexei, function34); + ADD_CALLBACK_FUNCTION(Alexei, function35); + ADD_CALLBACK_FUNCTION(Alexei, function36); + ADD_CALLBACK_FUNCTION(Alexei, chapter4); + ADD_CALLBACK_FUNCTION(Alexei, chapter4Handler); + ADD_CALLBACK_FUNCTION(Alexei, function39); + ADD_CALLBACK_FUNCTION(Alexei, function40); + ADD_CALLBACK_FUNCTION(Alexei, function41); + ADD_CALLBACK_FUNCTION(Alexei, function42); + ADD_CALLBACK_FUNCTION(Alexei, function43); + ADD_CALLBACK_FUNCTION(Alexei, function44); + ADD_CALLBACK_FUNCTION(Alexei, function45); + ADD_CALLBACK_FUNCTION(Alexei, function46); + ADD_CALLBACK_FUNCTION(Alexei, function47); + ADD_CALLBACK_FUNCTION(Alexei, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Alexei, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Alexei, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(3, Alexei, updateFromTicks, uint32) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(4, Alexei, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(5, Alexei, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(6, Alexei, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Alexei, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(8, Alexei, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(9, Alexei, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Alexei, updateEntity, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionExcuseMeCath: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 18) || getEntities()->isPlayerPosition(kCarRedSleeping, 18)) { + getSound()->excuseMe(kEntityAlexei); + } else { + if (getEvent(kEventAlexeiSalonVassili) || (getEvent(kEventTatianaAskMatchSpeakRussian) && getInventory()->hasItem(kItemPassengerList))) { + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1012" : "CAT1012A"); + } else { + getSound()->excuseMeCath(); + } + } + // Stop execution here + return; + + case kActionDefault: + getData()->inventoryItem = kItemNone; + break; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(11, Alexei, draw2) + Entity::draw2(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Alexei, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Alexei, function13) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAlexei, kEntityMertens, kAction302614416); + getEntities()->drawSequenceLeft(kEntityAlexei, "602DB"); + getEntities()->enterCompartment(kEntityAlexei, kObjectCompartment2, true); + + getData()->location = kLocationInsideCompartment; + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_7500)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartment2, true); + } + break; + + case 2: + getEntities()->exitCompartment(kEntityAlexei, kObjectCompartment2, true); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_7500; + getEntities()->clearSequences(kEntityAlexei); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction135664192: + setCallback(2); + setup_enterExitCompartment("602Eb", kObjectCompartment2); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Alexei, function14) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("602Fb", kObjectCompartment2); + break; + + case kActionCallback: + if (getCallback() == 1) { + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityAlexei, kEntityMertens, kAction302614416); + getEntities()->drawSequenceLeft(kEntityAlexei, "602DB"); + getEntities()->enterCompartment(kEntityAlexei, kObjectCompartment2, true); + } + break; + + case kAction135664192: + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->exitCompartment(kEntityAlexei, kObjectCompartment2, true); + + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Alexei, function15) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_CHECK(params->param2, getState()->time, params->param1) + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updatePosition("103D", kCarRestaurant, 52); + } + } + break; + + case kActionDefault: + params->param1 = 5 * (3 * rnd(60) + 90); + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updatePosition("103C", kCarRestaurant, 52); + break; + + case 2: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAlexei, "103E"); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAlexei, "103B"); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IS(16, Alexei, function16, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param7 && params->param1 < getState()->time && !params->param8) { + params->param8 = 1; + + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + + if (params->param5) { + UPDATE_PARAM(CURRENT_PARAMS(1, 1), getState()->timeTicks, 75); + + params->param5 = 0; + params->param6 = 1; + + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + CURRENT_PARAMS(1, 1) = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (params->param5) { + if (savepoint.param.intValue == 18) { + setCallback(4); + setup_playSound(getSound()->justAMinuteCath()); + break; + } + + if (getInventory()->hasItem(kItemPassengerList)) { + setCallback(5); + setup_playSound(rnd(2) ? getSound()->wrongDoorCath() : "CAT1503"); + } else { + setCallback(6); + setup_playSound(getSound()->wrongDoorCath()); + } + } else { + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAlexei, (char*)¶ms->seq); + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param6 || params->param5) { + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param5 = 0; + params->param6 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound("ALX1134A"); + break; + + case 3: + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorTalk, kCursorNormal); + params->param5 = 1; + break; + + case 4: + case 5: + case 6: + params->param5 = 0; + params->param6 = 1; + break; + + case 7: + setCallback(8); + setup_updateFromTicks(300); + break; + + case 8: + setCallback(9); + setup_enterExitCompartment("602Gb", kObjectCompartment2); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityAlexei, kEntityMertens, kAction156567128); + getEntities()->drawSequenceLeft(kEntityAlexei, "602Hb"); + getEntities()->enterCompartment(kEntityAlexei, kObjectCompartment2, true); + break; + + case 10: + getEntities()->exitCompartment(kEntityAlexei, kObjectCompartment2, true); + + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_7500; + + getEntities()->drawSequenceLeft(kEntityAlexei, (char *)¶ms->seq); + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param7 = 0; + break; + } + break; + + case kAction124697504: + setCallback(10); + setup_enterExitCompartment("602Ib", kObjectCompartment2); + break; + + case kAction221617184: + params->param7 = 1; + getSavePoints()->push(kEntityAlexei, kEntityMertens, kAction100906246); + + setCallback(7); + setup_playSound("CON1024"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Alexei, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler) + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject10, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Alexei, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime1089000 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + params->param2 = kItemNone; + + getData()->location = kLocationOutsideCompartment; + getData()->inventoryItem = kItemNone; + + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 63); + getInventory()->setLocationAndProcess(kItem17, kObjectLocation1); + + setCallback(1); + setup_callSavepoint("005D", kEntityTables1, kActionDrawTablesWithChairs, "005E"); + break; + } + + if (params->param1) { + UPDATE_PARAM(params->param3, getState()->timeTicks, 90); + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + } else { + params->param3 = 0; + } + break; + + case kAction1: + params->param2 = kItemNone; + getData()->inventoryItem = kItemNone; + + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventAlexeiDiner); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAlexei, kEntityTables1, kAction136455232); + getEntities()->drawSequenceLeft(kEntityAlexei, "005B"); + + params->param2 = kItemInvalid; + getData()->inventoryItem = kItemInvalid; + break; + + case kActionDrawScene: + params->param1 = getEntities()->isPlayerPosition(kCarRestaurant, 63) ? 1 : 0; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 63); + setup_function19(); + break; + + case 2: + getAction()->playAnimation(getProgress().jacket == kJacketGreen ? kEventAlexeiDiner : kEventAlexeiDinerOriginalJacket); + getSavePoints()->push(kEntityAlexei, kEntityTables1, kActionDrawTablesWithChairs, "005E"); + + getData()->entityPosition = kPosition_3650; + getData()->location = kLocationOutsideCompartment; + + getEntities()->clearSequences(kEntityAlexei); + getInventory()->get(kItem17)->location = kObjectLocation1; + getScenes()->loadSceneFromPosition(kCarRestaurant, 63); + + setup_function19(); + break; + } + break; + + case kAction168046720: + getData()->inventoryItem = kItemNone; + break; + + case kAction168627977: + getData()->inventoryItem = (InventoryItem)LOBYTE(params->param2); + break; + + case kAction225182640: + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19 ,Alexei, function19) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_draw("811DS"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_9460); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_draw("811US"); + break; + + case 5: + setCallback(6); + setup_draw("933"); + break; + + case 6: + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 63); + getScenes()->loadSceneFromItemPosition(kItem17); + getSavePoints()->push(kEntityAlexei, kEntityTables1, kAction136455232); + + setCallback(7); + setup_callSavepoint("005F", kEntityTables1, kActionDrawTablesWithChairs, "005G"); + break; + + case 7: + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 63); + getSavePoints()->push(kEntityAlexei, kEntityServers1, kAction302996448); + + setCallback(8); + setup_draw("934"); + break; + + case 8: + setCallback(9); + setup_draw("811DS"); + break; + + case 9: + setCallback(10); + setup_function13(); + break; + + case 10: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 61)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(11); + setup_function16(kTime1098000, "411"); + break; + + case 11: + setup_function20(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Alexei, function20) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function14(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_updatePosition("103A", kCarRestaurant, 52); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + setup_function26(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Alexei, function21) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_CHECK(params->param2, getState()->time, params->param1) + getData()->location = kLocationOutsideCompartment; + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_updatePosition("103C", kCarRestaurant, 52); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventAlexeiSalonPoem); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAlexei, "103B"); + params->param1 = 225 * (4 * rnd(3) + 4); + + if (!getEvent(kEventAlexeiSalonPoem)) + getData()->inventoryItem = kItemParchemin; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationInsideCompartment; + setup_function22(); + break; + + case 2: + getAction()->playAnimation(kEventAlexeiSalonPoem); + getData()->location = kLocationOutsideCompartment; + + getEntities()->drawSequenceRight(kEntityAlexei, "103D"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 52); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityAlexei, "103B"); + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 52); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Alexei, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(params->param2, getState()->time, params->param2) + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_updatePosition("103D", kCarRestaurant, 52); + break; + } + UPDATE_PARAM_PROC_END + + if (params->param3 == kTimeInvalid || getState()->time <= kTime1111500) + break; + + if (getState()->time > kTime1138500) { + params->param3 = kTimeInvalid; + } else { + if (!getEntities()->isInSalon(kEntityPlayer) || getEntities()->isInSalon(kEntityPlayer) || !params->param3) + params->param3 = getState()->time; + + if (params->param3 >= getState()->time) + break; + + params->param3 = kTimeInvalid; + } + + getData()->inventoryItem = kItemNone; + + setup_function23(); + break; + + case kAction1: + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventAlexeiSalonPoem); + break; + + case kActionDefault: + params->param1 = 255 * (4 * rnd(4) + 8); + getEntities()->drawSequenceLeft(kEntityAlexei, "103E"); + if (!getEvent(kEventAlexeiSalonPoem)) + getData()->inventoryItem = kItemParchemin; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationInsideCompartment; + setup_function21(); + break; + + case 2: + getAction()->playAnimation(kEventAlexeiSalonPoem); + getData()->inventoryItem = kItemNone; + getData()->location = kLocationOutsideCompartment; + + getEntities()->drawSequenceRight(kEntityAlexei, "103D"); + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 52); + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 52); + getData()->location = kLocationInsideCompartment; + + setup_function21(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Alexei, function23) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->inventoryItem = (!getEntities()->isInRestaurant(kEntityAlexei) || getEvent(kEventAlexeiSalonPoem)) ? kItemNone : kItemParchemin; + break; + + case kAction1: + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventAlexeiSalonPoem); + break; + + case kActionDefault: + getData()->location = kLocationInsideCompartment; + getSavePoints()->push(kEntityAlexei, kEntityTatiana, kAction124973510); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAlexeiSalonVassili); + + getData()->location = kLocationOutsideCompartment; + + getEntities()->drawSequenceLeft(kEntityAlexei, "103F"); + getScenes()->processScene(); + + setup_function24(); + break; + + case 2: + getAction()->playAnimation(kEventAlexeiSalonPoem); + + getData()->inventoryItem = kItemNone; + + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + break; + } + break; + + case kAction157159392: + if (getEntities()->isInSalon(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAlexeiSalonVassili); + } else { + setup_function24(); + } + break; + + case kAction188784532: + setup_function24(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Alexei, function24) + switch (savepoint.action) { + default: + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAlexeiSalonCath); + break; + + case kActionDefault: + if (getEvent(kEventAlexeiSalonVassili)) + getData()->inventoryItem = kItemInvalid; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAlexeiSalonCath); + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_9460; + getEntities()->clearSequences(kEntityAlexei); + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + setup_function25(); + break; + + case 2: + setup_function25(); + break; + } + break; + + case kAction135854208: + getData()->inventoryItem = kItemNone; + setCallback(2); + setup_draw("103G"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Alexei, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function13(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 61)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(2); + setup_function16(kTime1179000, "411"); + break; + + case 2: + setCallback(3); + setup_function16(kTime1323000, "412"); + break; + + case 3: + setup_function26(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Alexei, function26) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime1512000, params->param1, setup_function27) + break; + + case kActionDefault: + getData()->entityPosition = kPosition_7500; + getData()->car = kCarGreenSleeping; + getData()->location = kLocationInsideCompartment; + + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject10, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 61)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 66); + + getEntities()->clearSequences(kEntityAlexei); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Alexei, function27) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObject10, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 66)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + getEntities()->drawSequenceLeft(kEntityAlexei, "412"); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Alexei, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAlexei); + + getObjects()->update(kObjectCompartment2, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject10, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObjectHandleInsideBathroom, kEntityAlexei, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Alexei, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(kTime1791000, "411"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function14(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_draw("811US"); + break; + + case 5: + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 63); + + setCallback(6); + setup_callSavepoint("018B", kEntityTables1, kAction136455232, "BOGUS"); + break; + + case 6: + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 63); + getSavePoints()->push(kEntityAlexei, kEntityTatiana, kAction290869168); + setup_function30(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Alexei, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getData()->car = kCarRestaurant; + getData()->location = kLocationInsideCompartment; + + getEntities()->drawSequenceLeft(kEntityAlexei, "018C"); + getSavePoints()->push(kEntityAlexei, kEntityTables1, kAction136455232); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 63); + getSavePoints()->push(kEntityAlexei, kEntityTatiana, kAction156444784); + getEntities()->drawSequenceLeft(kEntityAlexei, "018E"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getProgress().field_68 = 1; + + setCallback(2); + setup_playSound("TAT2116"); + break; + + case 2: + getSound()->playSound(kEntityAlexei, "TAt2116A"); + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 63); + + setCallback(3); + setup_callSavepoint("018F", kEntityTatiana, kAction123857088, "BOGUS"); + break; + + case 3: + getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 63); + setup_function31(); + break; + } + break; + + case kAction236053296: + getEntities()->drawSequenceRight(kEntityAlexei, "018D1"); + getEntities()->drawSequenceRight(kEntityTatiana, "018D2"); + getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 63); + + if (savepoint.param.intValue) + getScenes()->loadSceneFromPosition(kCarRestaurant, (Position)savepoint.param.intValue); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Alexei, function31) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityAlexei, "811DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAlexei); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function13(); + break; + + case 2: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 61)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(3); + setup_function16(kTimeEnd, "411"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Alexei, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAlexei); + + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject10, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Alexei, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function34(); + break; + + case kAction122288808: + getData()->entityPosition = kPosition_9270; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + setCallback(1); + setup_function13(); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAlexei, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Alexei, function34) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 61)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(1); + setup_function16(kTime2083500, "411"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function14(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_updatePosition("103A", kCarRestaurant, 52); + break; + + case 5: + setCallback(6); + setup_function35(); + break; + + case 6: + setCallback(7); + setup_function13(); + break; + + case 7: + getObjects()->update(kObject10, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 61)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 66); + + setCallback(8); + setup_function16(kTime2124000, "NONE"); + break; + + case 8: + setCallback(9); + setup_function14(); + break; + + case 9: + setCallback(10); + setup_function36(); + break; + + case 10: + getObjects()->update(kObject10, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 66)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(11); + setup_function16(kTime16451100, "411"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Alexei, function35) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInSalon(kEntityPlayer)) { + UPDATE_PARAM_PROC(params->param2, getState()->time, 2700) + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + UPDATE_PARAM_PROC_END + } else { + params->param2 = 0; + } + + UPDATE_PARAM_PROC(params->param3, getState()->time, params->param1) + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + setCallback(3); + setup_function15(); + break; + } + UPDATE_PARAM_PROC_END + +label_callback_3: + UPDATE_PARAM(params->param4, getState()->time, 9000); + + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionDefault: + params->param1 = 15 * rnd(120); + getEntities()->drawSequenceLeft(kEntityAlexei, "103B"); + getData()->location = kLocationInsideCompartment; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 4: + getData()->location = kLocationOutsideCompartment; + + setCallback((byte)(getCallback() + 1)); + setup_updatePosition("124C", kCarRestaurant, 52); + break; + + case 2: + case 5: + CALLBACK_ACTION(); + break; + + case 3: + params->param1 = 15 * rnd(120); + params->param3 = 0; + goto label_callback_3; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Alexei, function36) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 || params->param2) + break; + + UPDATE_PARAM(params->param4, getState()->timeTicks, params->param1); + + getEntities()->drawSequenceRight(kEntityAlexei, "124B"); + + params->param2 = 1; + params->param4 = 0; + break; + + case kActionExitCompartment: + if (params->param2) { + getEntities()->drawSequenceLeft(kEntityAlexei, "124A"); + params->param1 = 5 * (3 * rnd(15) + 15); + params->param2 = 0; + } + break; + + case kActionDefault: + params->param1 = 5 * (3 * rnd(15) + 15); + + setCallback(1); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getSavePoints()->push(kEntityAlexei, kEntityAbbot, kAction222609266); + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updatePosition("103A", kCarRestaurant, 52); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAlexei, "124A"); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + + case kAction122288808: + setCallback(4); + setup_function13(); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAlexei, "BLANK"); + params->param3 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Alexei, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAlexei); + + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject10, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Alexei, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(kTime2354400, "411"); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function39(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Alexei, function39) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param2) + break; + + if (!params->param4) { + params->param3 = getState()->time + 4500; + params->param4 = getState()->time + 9000; + } + + if (params->param5 != kTimeInvalid && params->param3 < getState()->time) { + + if (params->param4 >= getState()->time) { + if (getEntities()->isInGreenCarEntrance(kEntityPlayer) || !params->param5) + params->param5 = getState()->time; + + if (params->param5 >= getState()->time) + break; + } + + params->param4 = kTimeInvalid; + + getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 70); + getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 71); + + if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) { + getSound()->excuseMe(kEntityAlexei); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72); + } + + setup_function40(); + } + break; + + case kActionExitCompartment: + if (!params->param2 && !params->param2) + getEntities()->drawSequenceLeft(kEntityAlexei, "306F"); + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("602FB", kObjectCompartment2); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) { + if (params->param1) { + if (!params->param2) + break; + } else if (!params->param2) { + getEntities()->drawSequenceRight(kEntityAlexei, "306A"); + break; + } + + setup_function40(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + + case 2: + getEntities()->clearSequences(kEntityAlexei); + + if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) { + getSound()->excuseMe(kEntityAlexei); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72); + } + + getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 70); + getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 71); + break; + } + break; + + case kAction123536024: + params->param2 = 1; + break; + + case kAction123712592: + getEntities()->clearSequences(kEntityAlexei); + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Alexei, function40) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceRight(kEntityAlexei, "602Eb"); + getEntities()->enterCompartment(kEntityAlexei, kObjectCompartment2); + + getData()->location = kLocationInsideCompartment; + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_7500)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartment2); + } + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + getEntities()->exitCompartment(kEntityAlexei, kObjectCompartment2); + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityAlexei); + + setup_function41(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Alexei, function41) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 66)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(1); + setup_function16(kTime2403000, "411"); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function42(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Alexei, function42) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function14(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAlexei, kEntityTatiana, kAction191198209); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_updatePosition("103A", kCarRestaurant, 52); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + setup_function43(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, Alexei, function43) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time < kTime1806300 && params->param2 < getState()->time) { + if (!params->param2) + params->param2 = getState()->time + params->param1; + + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + setCallback(1); + setup_function15(); + break; + } + } + +label_callback_1: + if (getState()->time > kTime2457000 && !params->param3) { + params->param3 = 1; + + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + } + break; + + case kActionDefault: + params->param1 = 5 * (3 * rnd(120) + 180); + getEntities()->drawSequenceLeft(kEntityAlexei, "103B"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 5 * (3 * rnd(120) + 180); + params->param2 = 0; + goto label_callback_1; + + case 2: + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updatePosition("124C", kCarRestaurant, 52); + break; + + case 3: + setup_function44(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Alexei, function44) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2457000 && !params->param1) { + params->param1 = 1; + + getEntities()->updatePositionExit(kEntityAlexei, kCarGreenSleeping, 70); + getEntities()->updatePositionExit(kEntityAlexei, kCarGreenSleeping, 71); + + if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) { + getSound()->excuseMe(kEntityAlexei); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72); + + setup_function45(); + } + } + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->location = kLocationOutsideCompartment; + getData()->entityPosition = kPosition_9460; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) { + setCallback(2); + setup_draw("306A"); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityAlexei); + + if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) { + getSound()->excuseMe(kEntityAlexei); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72); + } + + getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 70); + getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 71); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityAlexei, "306F"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, Alexei, function45) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function13(); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 66)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + if (getInventory()->hasItem(kItemBomb)) { + setup_function46(); + } else { + setCallback(2); + setup_function16(kTimeEnd, "412"); + } + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Alexei, function46) + error("Alexei: callback function 46 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, Alexei, function47) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityAlexei); + + getData()->entityPosition = kPositionNone; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarNone; + + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Alexei, chapter5) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityAlexei); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/alexei.h b/engines/lastexpress/entities/alexei.h new file mode 100644 index 0000000000..dc1a136143 --- /dev/null +++ b/engines/lastexpress/entities/alexei.h @@ -0,0 +1,213 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ALEXEI_H +#define LASTEXPRESS_ALEXEI_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Alexei : public Entity { +public: + Alexei(LastExpressEngine *engine); + ~Alexei() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Updates parameter 2 using ticks value + * + * @param ticks The number of ticks to add + */ + DECLARE_FUNCTION_1(updateFromTicks, uint32 ticks) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Draws the entity along with another one + * + * @param savepoint The savepoint + * - The sequence to draw + * - The sequence to draw for the second entity + * - The EntityIndex of the second entity + */ + DECLARE_FUNCTION_NOSETUP(draw2) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + DECLARE_FUNCTION(function13) + DECLARE_FUNCTION(function14) + DECLARE_FUNCTION(function15) + + /** + * ??? + * + * @param timeValue The time value + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_2(function16, TimeValue timeValue, const char* sequence) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + DECLARE_FUNCTION(function30) + DECLARE_FUNCTION(function31) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + DECLARE_FUNCTION(function36) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + DECLARE_FUNCTION(function39) + DECLARE_FUNCTION(function40) + DECLARE_FUNCTION(function41) + DECLARE_FUNCTION(function42) + DECLARE_FUNCTION(function43) + DECLARE_FUNCTION(function44) + DECLARE_FUNCTION(function45) + DECLARE_FUNCTION(function46) + DECLARE_FUNCTION(function47) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ALEXEI_H diff --git a/engines/lastexpress/entities/alouan.cpp b/engines/lastexpress/entities/alouan.cpp new file mode 100644 index 0000000000..0a66004a49 --- /dev/null +++ b/engines/lastexpress/entities/alouan.cpp @@ -0,0 +1,504 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/alouan.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Alouan::Alouan(LastExpressEngine *engine) : Entity(engine, kEntityAlouan) { + ADD_CALLBACK_FUNCTION(Alouan, reset); + ADD_CALLBACK_FUNCTION(Alouan, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Alouan, playSound); + ADD_CALLBACK_FUNCTION(Alouan, updateFromTime); + ADD_CALLBACK_FUNCTION(Alouan, updateEntity); + ADD_CALLBACK_FUNCTION(Alouan, compartment6); + ADD_CALLBACK_FUNCTION(Alouan, compartment8); + ADD_CALLBACK_FUNCTION(Alouan, compartment6to8); + ADD_CALLBACK_FUNCTION(Alouan, compartment8to6); + ADD_CALLBACK_FUNCTION(Alouan, chapter1); + ADD_CALLBACK_FUNCTION(Alouan, chapter1Handler); + ADD_CALLBACK_FUNCTION(Alouan, function12); + ADD_CALLBACK_FUNCTION(Alouan, chapter2); + ADD_CALLBACK_FUNCTION(Alouan, chapter2Handler); + ADD_CALLBACK_FUNCTION(Alouan, chapter3); + ADD_CALLBACK_FUNCTION(Alouan, chapter3Handler); + ADD_CALLBACK_FUNCTION(Alouan, chapter4); + ADD_CALLBACK_FUNCTION(Alouan, chapter4Handler); + ADD_CALLBACK_FUNCTION(Alouan, function19); + ADD_CALLBACK_FUNCTION(Alouan, chapter5); + ADD_CALLBACK_FUNCTION(Alouan, chapter5Handler); + ADD_CALLBACK_FUNCTION(Alouan, function22); + ADD_CALLBACK_FUNCTION(Alouan, function23); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Alouan, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(2, Alouan, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Alouan, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(4, Alouan, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(5, Alouan, updateEntity, CarIndex, EntityPosition) + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Alouan, compartment6) + COMPARTMENT_TO(Alouan, kObjectCompartment6, kPosition_4070, "621Cf", "621Df"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Alouan, compartment8) + COMPARTMENT_TO(Alouan, kObjectCompartment8, kPosition_2740, "621Ch", "621Dh"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Alouan, compartment6to8) + COMPARTMENT_FROM_TO(Alouan, kObjectCompartment6, kPosition_4070, "621Bf", kObjectCompartment8, kPosition_2740, "621Ah"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Alouan, compartment8to6) + COMPARTMENT_FROM_TO(Alouan, kObjectCompartment8, kPosition_2740, "621Bh", kObjectCompartment6, kPosition_4070, "621Af"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Alouan, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Alouan, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + + TIME_CHECK_CALLBACK(kTime1096200, params->param1, 1, setup_compartment8to6); + +label_callback1: + if (getState()->time > kTime1162800 && !params->param2) { + params->param2 = 1; + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4070); + getData()->entityPosition = kPosition_4070; + } + + if (getState()->time > kTime1179000 && !params->param3) { + params->param3 = 1; + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); + + setCallback(2); + setup_compartment6to8(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_4840; + goto label_callback1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Alouan, function12) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartment7, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment5, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityAlouan); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Alouan, chapter2) + if (savepoint.action != kActionDefault) + return; + + getEntities()->clearSequences(kEntityAlouan); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + setup_chapter2Handler(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Alouan, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 == kTimeInvalid) + break; + + if (getState()->time <= kTime1777500) { + if (!getEntities()->isPlayerInCar(kCarGreenSleeping) || !params->param2) + params->param2 = getState()->time + 75; + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + + setCallback(params->param1 ? 1 : 2); + if (params->param1) + setup_compartment8(); + else + setup_compartment6(); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); + params->param1 = 1; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 3: + params->param1 = 0; + setCallback(4); + setup_playSound("Har2011"); + break; + + case 4: + setCallback(5); + setup_updateFromTime(900); + break; + + case 5: + getSavePoints()->push(kEntityAlouan, kEntityFrancois, kAction190219584); + break; + } + break; + + case kAction189489753: + setCallback(3); + setup_compartment8to6(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Alouan, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAlouan); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Alouan, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTimeCitySalzbourg, params->param1, 1, setup_compartment8to6); + +label_callback1: + if (params->param2 != kTimeInvalid && getState()->time > kTime1989000) + TIME_CHECK_CAR(kTime2119500, params->param5, 5, setup_compartment8); + +label_callback2: + TIME_CHECK_PLAYSOUND(kTime2052000, params->param3, 3, "Har1005"); + +label_callback3: + TIME_CHECK_CALLBACK(kTime2133000, params->param4, 4, setup_compartment6to8); + +label_callback4: + if (params->param5 != kTimeInvalid && getState()->time > kTime2151000) + TIME_CHECK_CAR(kTime2241000, params->param5, 5, setup_compartment8); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_4840; + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + + case 4: + goto label_callback4; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Alouan, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAlouan); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Alouan, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 != kTimeInvalid) + TIME_CHECK_CAR(kTime2443500, params->param1, 1, setup_compartment8); + +label_callback1: + TIME_CHECK_CALLBACK(kTime2455200, params->param2, 2, setup_compartment8to6); + +label_callback2: + if (getState()->time > kTime2475000 && !params->param3) { + params->param3 = 1; + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); + + setCallback(3); + setup_compartment6to8(); + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4070); + goto label_callback2; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Alouan, function19) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartment7, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment5, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityAlouan); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Alouan, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAlouan); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Alouan, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function22(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Alouan, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->time, 2700); + setup_function23(); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + break; + + case kActionDrawScene: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) + setup_function23(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Alouan, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_4070); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("619AF", kObjectCompartment5); + break; + + case 2: + getEntities()->clearSequences(kEntityAlouan); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + + getObjects()->update(kObjectCompartment6, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(24, Alouan) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/alouan.h b/engines/lastexpress/entities/alouan.h new file mode 100644 index 0000000000..282117fcea --- /dev/null +++ b/engines/lastexpress/entities/alouan.h @@ -0,0 +1,139 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ALOUAN_H +#define LASTEXPRESS_ALOUAN_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Alouan : public Entity { +public: + Alouan(LastExpressEngine *engine); + ~Alouan() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION(compartment6) + DECLARE_FUNCTION(compartment8) + DECLARE_FUNCTION(compartment6to8) + DECLARE_FUNCTION(compartment8to6) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + DECLARE_FUNCTION(function12) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + DECLARE_FUNCTION(function19) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ALOUAN_H diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp new file mode 100644 index 0000000000..f81d95754e --- /dev/null +++ b/engines/lastexpress/entities/anna.cpp @@ -0,0 +1,3400 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/anna.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/fight.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Anna::Anna(LastExpressEngine *engine) : Entity(engine, kEntityAnna) { + ADD_CALLBACK_FUNCTION(Anna, reset); + ADD_CALLBACK_FUNCTION(Anna, draw); + ADD_CALLBACK_FUNCTION(Anna, updatePosition); + ADD_CALLBACK_FUNCTION(Anna, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Anna, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Anna, callSavepoint); + ADD_CALLBACK_FUNCTION(Anna, playSound); + ADD_CALLBACK_FUNCTION(Anna, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Anna, savegame); + ADD_CALLBACK_FUNCTION(Anna, updateEntity); + ADD_CALLBACK_FUNCTION(Anna, updateFromTime); + ADD_CALLBACK_FUNCTION(Anna, function12); + ADD_CALLBACK_FUNCTION(Anna, draw2); + ADD_CALLBACK_FUNCTION(Anna, updateFromTicks); + ADD_CALLBACK_FUNCTION(Anna, function15); + ADD_CALLBACK_FUNCTION(Anna, chapter1); + ADD_CALLBACK_FUNCTION(Anna, function17); + ADD_CALLBACK_FUNCTION(Anna, function18); + ADD_CALLBACK_FUNCTION(Anna, chapter1Handler); + ADD_CALLBACK_FUNCTION(Anna, function20); + ADD_CALLBACK_FUNCTION(Anna, function21); + ADD_CALLBACK_FUNCTION(Anna, function22); + ADD_CALLBACK_FUNCTION(Anna, function23); + ADD_CALLBACK_FUNCTION(Anna, function24); + ADD_CALLBACK_FUNCTION(Anna, function25); + ADD_CALLBACK_FUNCTION(Anna, function26); + ADD_CALLBACK_FUNCTION(Anna, function27); + ADD_CALLBACK_FUNCTION(Anna, function28); + ADD_CALLBACK_FUNCTION(Anna, function29); + ADD_CALLBACK_FUNCTION(Anna, function30); + ADD_CALLBACK_FUNCTION(Anna, function31); + ADD_CALLBACK_FUNCTION(Anna, function32); + ADD_CALLBACK_FUNCTION(Anna, function33); + ADD_CALLBACK_FUNCTION(Anna, function34); + ADD_CALLBACK_FUNCTION(Anna, function35); + ADD_CALLBACK_FUNCTION(Anna, function36); + ADD_CALLBACK_FUNCTION(Anna, function37); + ADD_CALLBACK_FUNCTION(Anna, function38); + ADD_CALLBACK_FUNCTION(Anna, function39); + ADD_CALLBACK_FUNCTION(Anna, function40); + ADD_CALLBACK_FUNCTION(Anna, function41); + ADD_CALLBACK_FUNCTION(Anna, chapter2); + ADD_CALLBACK_FUNCTION(Anna, chapter2Handler); + ADD_CALLBACK_FUNCTION(Anna, chapter3); + ADD_CALLBACK_FUNCTION(Anna, function45); + ADD_CALLBACK_FUNCTION(Anna, chapter3Handler); + ADD_CALLBACK_FUNCTION(Anna, function47); + ADD_CALLBACK_FUNCTION(Anna, function48); + ADD_CALLBACK_FUNCTION(Anna, leaveTableWithAugust); + ADD_CALLBACK_FUNCTION(Anna, function50); + ADD_CALLBACK_FUNCTION(Anna, function51); + ADD_CALLBACK_FUNCTION(Anna, function52); + ADD_CALLBACK_FUNCTION(Anna, function53); + ADD_CALLBACK_FUNCTION(Anna, function54); + ADD_CALLBACK_FUNCTION(Anna, function55); + ADD_CALLBACK_FUNCTION(Anna, function56); + ADD_CALLBACK_FUNCTION(Anna, function57); + ADD_CALLBACK_FUNCTION(Anna, function58); + ADD_CALLBACK_FUNCTION(Anna, function59); + ADD_CALLBACK_FUNCTION(Anna, function60); + ADD_CALLBACK_FUNCTION(Anna, function61); + ADD_CALLBACK_FUNCTION(Anna, function62); + ADD_CALLBACK_FUNCTION(Anna, function63); + ADD_CALLBACK_FUNCTION(Anna, baggage); + ADD_CALLBACK_FUNCTION(Anna, function65); + ADD_CALLBACK_FUNCTION(Anna, chapter4); + ADD_CALLBACK_FUNCTION(Anna, chapter4Handler); + ADD_CALLBACK_FUNCTION(Anna, function68); + ADD_CALLBACK_FUNCTION(Anna, function69); + ADD_CALLBACK_FUNCTION(Anna, function70); + ADD_CALLBACK_FUNCTION(Anna, function71); + ADD_CALLBACK_FUNCTION(Anna, function72); + ADD_CALLBACK_FUNCTION(Anna, function73); + ADD_CALLBACK_FUNCTION(Anna, chapter5); + ADD_CALLBACK_FUNCTION(Anna, chapter5Handler); + ADD_CALLBACK_FUNCTION(Anna, function76); + ADD_CALLBACK_FUNCTION(Anna, function77); + ADD_CALLBACK_FUNCTION(Anna, function78); + ADD_CALLBACK_FUNCTION(Anna, function79); + ADD_CALLBACK_FUNCTION(Anna, function80); + ADD_CALLBACK_FUNCTION(Anna, finalSequence); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Anna, reset) + Entity::reset(savepoint, true, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Anna, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(3, Anna, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(4, Anna, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Anna, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(6, Anna, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(7, Anna, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Anna, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(9, Anna, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Anna, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + if (getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction) || getProgress().chapter >= kChapter2) + getSound()->playSound(kEntityPlayer, "CAT1001"); + else + getSound()->excuseMeCath(); + + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(11, Anna, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Anna, function12) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param2 && ENTITY_PARAM(0, 1)) + params->param2 = 1; + + if (params->param6) { + UPDATE_PARAM_PROC(params->param7, getState()->timeTicks, 75) + getSavePoints()->push(kEntityAnna, kEntityAnna, kActionEndSound); + + params->param6 = 0; + params->param7 = 0; + UPDATE_PARAM_PROC_END + } + + if (params->param4) { + UPDATE_PARAM(params->param8, getState()->timeTicks, 75); + + params->param4 = 0; + params->param5 = 1; + + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorHand); + + --params->param1; + + getSavePoints()->push(kEntityAnna, kEntityAnna, kActionEndSound); + } + + params->param8 = 0; + break; + + case kActionEndSound: + if (params->param2) { + CALLBACK_ACTION(); + break; + } + + ++params->param1; + + switch (params->param1) { + default: + break; + + case 1: + getSound()->playSound(kEntityAnna, "ANN2135A"); + break; + + case 2: + getSound()->playSound(kEntityAnna, "ANN2135B"); + break; + + case 3: + getSound()->playSound(kEntityAnna, "ANN2135C"); + break; + + case 4: + getSound()->playSound(kEntityAnna, "ANN2135C"); + break; + + case 5: + getSound()->playSound(kEntityAnna, "ANN2135L"); + break; + + case 6: + getSound()->playSound(kEntityAnna, "ANN2135K"); + break; + + case 7: + getSound()->playSound(kEntityAnna, "ANN2135H"); + break; + + case 8: + getSound()->playSound(kEntityAnna, "ANN2135K"); + break; + + case 9: + getSound()->playSound(kEntityAnna, "ANN2135I"); + break; + + case 10: + getSound()->playSound(kEntityAnna, "ANN2135J"); + break; + + case 11: + getSound()->playSound(kEntityAnna, "ANN2135M"); + break; + + case 12: + getSound()->playSound(kEntityAnna, "ANN2135L"); + break; + + case 13: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + break; + + case kActionKnock: + if (params->param4) { + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorHand); + + if (savepoint.param.intValue == 53) { + getSound()->playSound(kEntityPlayer, getSound()->justAMinuteCath()); + } else if (getInventory()->hasItem(kItemPassengerList)) { + if (rnd(2)) { + getSound()->playSound(kEntityPlayer, getSound()->wrongDoorCath()); + } else { + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1506A" : "CAT1506"); + } + } else { + getSound()->playSound(kEntityPlayer, getSound()->wrongDoorCath()); + } + + params->param4 = 0; + params->param5 = 0; + } else { + getSound()->removeFromQueue(kEntityAnna); + + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_playSound("LIB012"); + } + break; + + case kActionOpenDoor: + getSound()->removeFromQueue(kEntityAnna); + setCallback(3); + setup_playSound("LIB013"); + break; + + case kActionDefault: + params->param1 = 1; + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 49)) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + + getEntities()->drawSequenceLeft(kEntityAnna, "418C"); + + if (getSound()->isBuffered(kEntityAnna)) + getSound()->processEntry(kEntityAnna); + + getSound()->playSound(kEntityAnna, "ANN2135A"); + break; + + case kActionDrawScene: + if (params->param5 || params->param4) { + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + params->param4 = 0; + params->param5 = 0; + } + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 60)) { + ++params->param3; + if (params->param3 == 2) { + setCallback(2); + setup_draw("418B"); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_playSound("Ann1016"); + break; + + case 2: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorTalk, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorTalk, kCursorHand); + params->param4 = 1; + break; + + case 3: + if (!getSound()->isBuffered(kEntityMax)) { + setCallback(4); + setup_playSound("MAX1120"); + break; + } + // Fallback to next case + + case 4: + --params->param1; + params->param6 = 1; + break; + + case 5: + getEntities()->drawSequenceLeft(kEntityAnna, "418A"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SSI(13, Anna, draw2, EntityIndex) + Entity::draw2(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(14, Anna, updateFromTicks, uint32) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IS(15, Anna, function15, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 < getState()->time && !params->param7) { + params->param7 = 1; + + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + + if (params->param5) { + UPDATE_PARAM(params->param8, getState()->timeTicks, 75); + + params->param5 = 0; + params->param6 = 1; + + CursorStyle cursor = getEntities()->isInsideCompartment(kEntityMax, kCarRedSleeping, kPosition_4070) ? kCursorHand : kCursorNormal; + + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, cursor); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, cursor); + } + + params->param8 = 0; + break; + + case kActionOpenDoor: + if (getEntities()->isInsideCompartment(kEntityMax, kCarRedSleeping, kPosition_4070)) { + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_playSound("LIB013"); + break; + } + // Fallback to next action + + case kActionKnock: + if (params->param5) { + CursorStyle cursor = getEntities()->isInsideCompartment(kEntityMax, kCarRedSleeping, kPosition_4070) ? kCursorHand : kCursorNormal; + + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, cursor); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, cursor); + + if (savepoint.param.intValue == kObject53) { + setCallback(6); + setup_playSound(getSound()->justAMinuteCath()); + } else { + if (getInventory()->hasItem(kItemPassengerList)) { + setCallback(7); + setup_playSound(rnd(2) ? getSound()->wrongDoorCath() : (rnd(2) ? "CAT1506" : "CAT1506A")); + } else { + setCallback(8); + setup_playSound(getSound()->wrongDoorCath()); + } + } + } else { + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 3 : 4); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->drawSequenceLeft(kEntityAnna, (char *)¶ms->seq); + break; + + case kActionDrawScene: + if (params->param6 || params->param5) { + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param5 = 0; + params->param6 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (!getSound()->isBuffered(kEntityMax)) { + setCallback(2); + setup_playSound("MAX1120"); + break; + } + // Fallback to next case + + case 2: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case 3: + case 4: + setCallback(5); + setup_playSound("ANN1016"); + break; + + case 5: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorTalk, kCursorNormal); + params->param5 = 1; + break; + + case 6: + case 7: + case 8: + params->param5 = 0; + params->param6 = 1; + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Anna, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityAnna, kAction291662081, 0); + getSavePoints()->addData(kEntityAnna, kAction238936000, 1); + + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(17, Anna, function17, uint32, uint32) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->inventoryItem = (params->param3 && getEntities()->isDistanceBetweenEntities(kEntityAnna, kEntityPlayer, 2000)) ? (InventoryItem)LOBYTE(params->param3) : kItemNone; + + if (getEntities()->updateEntity(kEntityAnna, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + CALLBACK_ACTION(); + } + break; + + case kAction1: + if (savepoint.param.intValue == 8) { + getData()->inventoryItem = (InventoryItem)(getData()->inventoryItem & kItemToggleLow); + params->param3 &= 0xFFFFFFF7; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaGiveScarf); + } else { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventGotALight); + } + break; + + case kActionExcuseMeCath: + if (getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction) || getProgress().chapter >= kChapter2) + getSound()->playSound(kEntityPlayer, "CAT1001"); + else + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntityAnna); + break; + + case kActionDefault: + if (getProgress().jacket == kJacketGreen) { + if (!getEvent(kEventGotALight) && !getEvent(kEventGotALightD) && !getEvent(kEventAugustPresentAnna) && !getEvent(kEventAugustPresentAnnaFirstIntroduction)) + params->param3 = kItemInvalid; + + if (!params->param3 && !getEvent(kEventAnnaGiveScarfAsk) && !getEvent(kEventAnnaGiveScarfDinerAsk) && !getEvent(kEventAnnaGiveScarfSalonAsk)) + params->param3 |= 8; + } + + if (getEntities()->updateEntity(kEntityAnna, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEvent(kEventAnnaGiveScarf) + || getEvent(kEventAnnaGiveScarfDiner) + || getEvent(kEventAnnaGiveScarfSalon) + || getEvent(kEventAnnaGiveScarfMonogram) + || getEvent(kEventAnnaGiveScarfDinerMonogram) + || getEvent(kEventAnnaGiveScarfSalonMonogram)) + getAction()->playAnimation(kEventAnnaGiveScarfAsk); + else if (getEvent(kEventAugustPresentAnna) + || getEvent(kEventAugustPresentAnnaFirstIntroduction)) + getAction()->playAnimation(kEventAnnaGiveScarfMonogram); + else + getAction()->playAnimation(kEventAnnaGiveScarf); + + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + break; + + case 2: + getAction()->playAnimation(getData()->direction == kDirectionUp ? kEventGotALightD : kEventGotALight); + getData()->inventoryItem = (InventoryItem)(getData()->inventoryItem & kItemToggleHigh); + params->param3 &= 0xFFFFFF7F; + + if (getProgress().jacket == kJacketGreen && !getEvent(kEventAnnaGiveScarfAsk) && !getEvent(kEventAnnaGiveScarfDinerAsk) && !getEvent(kEventAnnaGiveScarfSalonAsk)) + params->param3 |= 8; + + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(18, Anna, function18, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 && params->param1 < getState()->time && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->inventoryItem = kItemNone; + CALLBACK_ACTION(); + break; + } + + if (params->param5 && !params->param4) { + UPDATE_PARAM_PROC(params->param6, getState()->time, 900) + params->param2 |= kItemScarf; + params->param5 = 0; + params->param6 = 0; + UPDATE_PARAM_PROC_END + } + + if (params->param3) { + UPDATE_PARAM(params->param7, getState()->timeTicks, 90); + + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + } else { + params->param7 = 0; + } + break; + + case kAction1: + setCallback(savepoint.param.intValue == 8 ? 1 : 2); + setup_savegame(kSavegameTypeEvent, savepoint.param.intValue == 8 ? kEventAnnaGiveScarf : kEventDinerMindJoin); + break; + + case kActionDefault: + if (getProgress().jacket == kJacketGreen) { + if (!getEvent(kEventDinerMindJoin) && !getEvent(kEventAugustPresentAnna) && !getEvent(kEventAugustPresentAnnaFirstIntroduction)) + params->param2 |= kItemInvalid; + + if (!params->param2 && !getEvent(kEventAnnaGiveScarfAsk) && !getEvent(kEventAnnaGiveScarfDinerAsk) && !getEvent(kEventAnnaGiveScarfSalonAsk)) + params->param2 |= 8; + } + + getData()->inventoryItem = (InventoryItem)LOBYTE(params->param2); + break; + + case kActionDrawScene: + params->param3 = getEntities()->isPlayerPosition(kCarRestaurant, 62); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEvent(kEventAnnaGiveScarf) || getEvent(kEventAnnaGiveScarfDiner) || getEvent(kEventAnnaGiveScarfSalon) + || getEvent(kEventAnnaGiveScarfMonogram) || getEvent(kEventAnnaGiveScarfDinerMonogram) || getEvent(kEventAnnaGiveScarfSalonMonogram)) { + getAction()->playAnimation(kEventAnnaGiveScarfDinerAsk); + } else { + getAction()->playAnimation((getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction)) ? kEventAnnaGiveScarfDinerMonogram : kEventAnnaGiveScarfDiner); + params->param5 = 1; + } + + params->param2 &= 0xFFFFFFF7; + getData()->inventoryItem = (InventoryItem)params->param2; + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + break; + + case 2: + getAction()->playAnimation(kEventDinerMindJoin); + + params->param2 &= 0xFFFFFFF7; + + if (getProgress().jacket == kJacketGreen + && !getEvent(kEventAnnaGiveScarfAsk) + && !getEvent(kEventAnnaGiveScarfDinerAsk) + && !getEvent(kEventAnnaGiveScarfSalonAsk)) { + params->param2 |= 8; + } + + getData()->inventoryItem = (InventoryItem)LOBYTE(params->param2); + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + break; + } + break; + + case kAction168046720: + getData()->inventoryItem = kItemNone; + params->param4 = 1; + break; + + case kAction168627977: + getData()->inventoryItem = (InventoryItem)LOBYTE(params->param2); + params->param4 = 0; + break; + + case kAction170016384: + case kAction259136835: + case kAction268773672: + getData()->inventoryItem = kItemNone; + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Anna, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("618Ca", kObjectCompartment1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_8514; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("618Af", kObjectCompartmentF); + break; + + case 3: + getEntities()->clearSequences(kEntityAnna); + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + + setup_function20(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Anna, function20) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function15(kTime1093500, "NONE"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("618Bf", kObjectCompartmentF); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityAnna, kEntityMax, kAction71277948); + setup_function21(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Anna, function21) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function17(kCarRestaurant, kPosition_850); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_draw("801US"); + break; + + case 3: + getEntities()->drawSequenceRight(kEntityAnna, "001B"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityAnna); + + setCallback(4); + setup_callbackActionOnDirection(); + break; + + case 4: + setup_function22(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Anna, function22) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAnna, "001A"); + getSavePoints()->push(kEntityAnna, kEntityPascale, kAction223262556); + break; + + case kAction157370960: + getData()->location = kLocationInsideCompartment; + setup_function23(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Anna, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAnna, "001D"); + getSavePoints()->push(kEntityAnna, kEntityServers0, kAction270410280); + getSavePoints()->push(kEntityAnna, kEntityTables0, kAction136455232); + + setCallback(1); + setup_function18(kTimeNone); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityAnna, "001E"); + setCallback(2); + setup_playSound("ANN1048"); + break; + + case 2: + setCallback(3); + setup_draw("001F"); + break; + + case 3: + getSavePoints()->push(kEntityAnna, kEntityServers0, kAction203859488); + setup_function24(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Anna, function24) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAnna, "001G"); + + setCallback(1); + setup_function18(kTimeNone); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityAnna, "001H"); + setCallback(2); + setup_playSound("ANN1049"); + break; + + case 2: + getSavePoints()->push(kEntityAnna, kEntityServers0, kAction136702400); + setup_function25(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Anna, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAnna, "001J"); + getProgress().field_28 = 1; + + setCallback(1); + setup_function18(kTimeNone); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 2: + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + setup_function26(); + break; + } + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAnna, "BLANK"); + break; + + case kAction201437056: + getEntities()->drawSequenceLeft(kEntityAnna, "001J"); + setCallback(2); + setup_function18(kTime1138500); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Anna, function26) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 62); + + setCallback(1); + setup_callSavepoint("001L", kEntityTables0, kActionDrawTablesWithChairs, "001H"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 62); + getSavePoints()->push(kEntityAnna, kEntityServers0, kAction237485916); + getEntities()->drawSequenceRight(kEntityAnna, "801DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAnna); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + setCallback(3); + setup_function17(kCarRedSleeping, kPosition_4070); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("618Af", kObjectCompartmentF); + break; + + case 4: + getEntities()->clearSequences(kEntityAnna); + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + + setup_function27(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Anna, function27) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityAnna, kEntityMax, kAction101687594); + setCallback(1); + setup_function15(kTime1156500, "NONE"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + if (getProgress().field_14 == 29) { + params->param1 = getState()->time + 900; + setCallback(2); + setup_function15((TimeValue)params->param1, "NONE"); + } else { + setCallback(3); + setup_enterExitCompartment("618Bf", kObjectCompartmentF); + } + break; + + case 3: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityAnna, kEntityMax, kAction71277948); + setup_function28(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Anna, function28) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function17(kCarRestaurant, kPosition_850); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + getData()->entityPosition = kPosition_1540; + getScenes()->loadSceneFromItemPosition(kItem3); + + setCallback(3); + setup_updatePosition("104A", kCarRestaurant, 56); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + setup_function29(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Anna, function29) + error("Anna: callback function 29 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Anna, function30) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 != kTimeInvalid && getState()->time) { + if (getState()->time > kTime1188000) { + params->param3 = kTimeInvalid; + getSound()->playSound(kEntityAnna, "AUG1004"); + } else { + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param3) + params->param3 = getState()->time + 450; + + if (params->param3 < getState()->time) { + params->param3 = kTimeInvalid; + getSound()->playSound(kEntityAnna, "AUG1004"); + } + } + } + + if (params->param2 && params->param4 != kTimeInvalid && getState()->time > kTime1179000) { + + if (getState()->time > kTime1192500) { + params->param4 = kTimeInvalid; + setup_function30(); + break; + } + + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param4) + params->param4 = getState()->time + 150; + + if (params->param4 < getState()->time) { + params->param4 = kTimeInvalid; + setup_function30(); + break; + } + } + + if (params->param1) { + UPDATE_PARAM(params->param5, getState()->timeTicks, 90); + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + } else { + params->param5 = 0; + } + break; + + case kActionEndSound: + params->param2 = 1; + break; + + case kActionDefault: + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction122358304); + getEntities()->drawSequenceLeft(kEntityAnna, "106B"); + break; + + case kActionDrawScene: + params->param1 = getEntities()->isPlayerPosition(kCarRestaurant, 56); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Anna, function31) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getSound()->playSound(kEntityAnna, "AUG1005"); + + setCallback(2); + setup_updateFromTicks(150); + break; + + case 2: + getEntities()->updatePositionEnter(kEntityAnna, kCarRestaurant, 56); + + setCallback(3); + setup_draw2("106C1", "106C2", kEntityAugust); + break; + + case 3: + getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 56); + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction159332865); + + setup_function32(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Anna, function32) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function17(kCarRedSleeping, kPosition_4070); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("618Af", kObjectCompartmentF); + break; + + case 2: + getEntities()->clearSequences(kEntityAnna); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + + setup_function33(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Anna, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityAnna, kEntityMax, kAction101687594); + + params->param1 = getState()->time + 4500; + setCallback(1); + setup_function15((TimeValue)params->param1, "NONE"); + break; + + case kActionCallback: + if (getCallback() == 1) { + getObjects()->updateLocation2(kObjectCompartmentF, kObjectLocation1); + setup_function34(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Anna, function34) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1 && getEntities()->isPlayerPosition(kCarRedSleeping, 60)) { + UPDATE_PARAM_PROC(params->param2, getState()->time, 150) + setCallback(1); + setup_draw("419B"); + break; + UPDATE_PARAM_PROC_END + } + +label_callback_1: + TIME_CHECK(kTime1489500, params->param3, setup_function35); + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 2 : 3); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 78)) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationOutsideCompartment; + + getEntities()->drawSequenceLeft(kEntityAnna, "419A"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityAnna, "419C"); + params->param1 = 1; + goto label_callback_1; + + case 2: + case 3: + if (!getSound()->isBuffered(kEntityMax)) { + setCallback(4); + setup_playSound("MAX1120"); + break; + } + // Fallback to next case + + case 4: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Anna, function35) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) + break; + + UPDATE_PARAM(params->param3, getState()->timeTicks, 75); + + switch (params->param2) { + default: + break; + + case 0: + getSound()->playSound(kEntityAnna, "ANN2135E"); + break; + + case 1: + getSound()->playSound(kEntityAnna, "ANN2135F"); + break; + + case 2: + getSound()->playSound(kEntityAnna, "ANN2135G"); + break; + + case 3: + getSound()->playSound(kEntityAnna, "ANN2135D"); + break; + } + + params->param1 = 0; + params->param3 = 0; + break; + + case kActionEndSound: + ++params->param2; + + if (params->param2 > 3) + params->param2 = 0; + + params->param1 = 1; + break; + + case kActionKnock: + case kActionOpenDoor: + if (getSound()->isBuffered(kEntityAnna)) + getSound()->processEntry(kEntityAnna); + + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaVisitToCompartmentGun); + break; + + case kActionDefault: + getData()->clothes = kClothes1; + params->param1 = 1; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAnnaVisitToCompartmentGun); + getSound()->playSound(kEntityPlayer, "LIB015"); + getData()->location = kLocationOutsideCompartment; + getData()->entityPosition = kPosition_4840; + + getEntities()->updateEntity(kEntityAnna, kCarRedSleeping, kPosition_8200); + getScenes()->loadSceneFromObject(kObjectCompartmentF, true); + getSavePoints()->push(kEntityAnna, kEntityVassili, kAction339669520); + getSavePoints()->push(kEntityAnna, kEntityVerges, kAction339669520); + getSavePoints()->push(kEntityAnna, kEntityCoudert, kAction339669520); + getSavePoints()->push(kEntityAnna, kEntityMax, kAction71277948); + + setup_function36(); + break; + + case 2: + setup_function36(); + break; + } + break; + + case kAction226031488: + if (getSound()->isBuffered(kEntityAnna)) + getSound()->processEntry(kEntityAnna); + + getSavePoints()->push(kEntityAnna, kEntityMax, kAction71277948); + break; + + case kAction238358920: + setCallback(2); + setup_enterExitCompartment("608Cf", kObjectCompartmentF); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Anna, function36) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_8200); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(2); + setup_enterExitCompartment("608Aa", kObjectCompartmentA); + break; + + case 2: + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityAnna); + + setup_function37(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Anna, function37) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + break; + + case kAction191477936: + setup_function38(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Anna, function38) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_7500; + + setCallback(1); + setup_playSound("ANN1010"); + break; + + case kActionCallback: + if (getCallback() == 1) { + getSound()->playSound(kEntityPlayer, "MUS043"); + setup_function40(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(39, Anna, function39, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->updateEntity(kEntityAnna, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + + CALLBACK_ACTION(); + } + break; + + case kAction1: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaGoodNight); + break; + + case kActionExcuseMe: + getSound()->playSound(kEntityAnna, "ANN1107A"); + break; + + case kActionDefault: + getData()->inventoryItem = kItemNone; + if (!getEvent(kEventAnnaGoodNight) && !getEvent(kEventAnnaGoodNightInverse)) + getData()->inventoryItem = kItemInvalid; + + if (getEntities()->updateEntity(kEntityAnna, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + + CALLBACK_ACTION(); + } + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(getData()->direction == kDirectionNone ? kEventAnnaGoodNight : kEventAnnaGoodNightInverse); + getData()->inventoryItem = kItemNone; + + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Anna, function40) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("608Cb", kObjectCompartmentB); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_function39(kCarRedSleeping, kPosition_4070); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("608Bf", kObjectCompartmentF); + break; + + case 3: + getEntities()->clearSequences(kEntityAnna); + getData()->location = kLocationInsideCompartment; + + setCallback(4); + setup_updateFromTime(150); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("608Cf", kObjectCompartmentF); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + setCallback(6); + setup_function39(kCarRedSleeping, kPosition_7500); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("608Bb", kObjectCompartmentB); + break; + + case 7: + getEntities()->clearSequences(kEntityAnna); + getData()->location = kLocationInsideCompartment; + + setCallback(8); + setup_updateFromTime(150); + break; + + case 8: + setCallback(9); + setup_enterExitCompartment("608Cb", kObjectCompartmentB); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + + setCallback(10); + setup_function39(kCarRedSleeping, kPosition_4070); + break; + + case 10: + setCallback(11); + setup_enterExitCompartment("608Bf", kObjectCompartmentF); + break; + + case 11: + getEntities()->clearSequences(kEntityAnna); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_4070; + + setup_function41(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Anna, function41) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->time, 2700); + + params->param5++; + switch (params->param5) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityAnna, "419A"); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityAnna, "419B"); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityAnna, "419C"); + params->param1 = 0; + break; + } + + params->param2 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAnna, kEntityMax, kAction101687594); + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->drawSequenceLeft(kEntityAnna, "419C"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + if (!getSound()->isBuffered(kEntityMax)) { + setCallback(3); + setup_playSound("MAX1120"); + break; + } + // Fallback to next case + + case 3: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Anna, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAnna); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43 ,Anna, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function15(kTime1786500, "418C"); + break; + + case 2: + setCallback(3); + setup_function12(); + break; + + case 3: + setCallback(4); + setup_function15(kTime1818000, "418C"); + break; + + case 4: + setCallback(5); + setup_function12(); + break; + + case 5: + setCallback(6); + setup_function15(kTimeEnd, "418C"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Anna, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAnna); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothes3; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(45, Anna, function45, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_enterExitCompartment("625Bf", kObjectCompartmentF); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAnna, kEntityCoudert, params->param1 ? kAction185737168 : kAction185671840); + getSound()->playSound(kEntityAnna, "Ann3147"); + getEntities()->drawSequenceLeft(kEntityAnna, "625EF"); + getEntities()->enterCompartment(kEntityAnna, kObjectCompartmentF, true); + break; + + case 2: + getEntities()->exitCompartment(kEntityAnna, kObjectCompartmentF, true); + CALLBACK_ACTION(); + break; + } + break; + + case kAction157894320: + setCallback(2); + setup_updateFromTime(75); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Anna, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getEntities()->isPlayerPosition(kCarRedSleeping, 60)) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + if (getCallback() == 1 || getCallback() == 2) { + if (ENTITY_PARAM(0, 1)) { + setup_function47(); + } else { + setCallback(2); + setup_function15((TimeValue)(getState()->time + 4500), "418C"); + } + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, Anna, function47) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_enterExitCompartment("688Bf", kObjectCompartmentF); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityAnna, kEntityMax, kAction71277948); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("801VS"); + break; + + case 4: + getSound()->playSound(kEntityAnna, getEvent(kEventAugustLunch) ? "Ann3136" : "Ann3136A", SoundManager::kFlagInvalid, 30); + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction122358304); + + setCallback(5); + setup_draw2("026B1", "026B2", kEntityAugust); + break; + + case 5: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + setup_function48(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Anna, function48) + error("Anna: callback function 48 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(49, Anna, leaveTableWithAugust) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getSavePoints()->push(kEntityAnna, kEntityTables3, kActionDrawTablesWithChairs, "010M"); + getEntities()->clearSequences(kEntityAugust); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityTables3, "026J3"); + getEntities()->drawSequenceRight(kEntityAugust, "026J2"); + getEntities()->drawSequenceRight(kEntityAnna, "026J1"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(50, Anna, function50) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_playSound("ann3141"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + setCallback(3); + setup_leaveTableWithAugust(); + break; + + case 3: + setup_function51(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(51, Anna, function51) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getSound()->playSound(kEntityAnna, "Aug3008"); + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_draw2("112E1", "112E2", kEntityAugust); + } + } + break; + + case kActionDefault: + getSound()->playSound(kEntityAnna, "Aug3142", SoundManager::kFlagInvalid, 30); + getEntities()->updatePositionEnter(kEntityAnna, kCarRestaurant, 57); + getEntities()->drawSequenceRight(kEntityAnna, "112A"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAnna); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAnna, "112B"); + getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 57); + getSavePoints()->push(kEntityAnna, kEntityServers1, kAction219377792); + break; + + case 2: + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction122288808); + + setup_function52(); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityAnna, "112D"); + + if (getState()->time >= kTimeEnterAttnangPuchheim) { + params->param1 = 1; + } else { + setCallback(4); + setup_playSound("Ann3142A"); + } + break; + + case 4: + setCallback(5); + setup_updateFromTime(1800); + break; + + case 5: + setCallback(6); + setup_playSound("Aug3007"); + break; + + case 6: + params->param1 = 1; + break; + } + break; + + case kAction101169422: + if (getEvent(kEventKronosVisit)) { + setCallback(3); + setup_updatePosition("112J", kCarRestaurant, 57); + break; + } + + if (getState()->time >= kTimeEnterAttnangPuchheim) { + params->param1 = 1; + } else { + setCallback(4); + setup_playSound("Ann3142A"); + } + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityAnna, "112D"); + getSavePoints()->push(kEntityAnna, kEntityKronos, kAction157159392); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAnna, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(52, Anna, function52) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->exitCompartment(kEntityAnna, kObjectCompartmentF); + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityAnna); + + setup_function53(); + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->drawSequenceRight(kEntityAnna, "688Af"); + getEntities()->enterCompartment(kEntityAnna, kObjectCompartmentF); + getData()->location = kLocationInsideCompartment; + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4070) || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4455)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartmentF); + } + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(53, Anna, function53) + error("Anna: callback function 53 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(54, Anna, function54) + error("Anna: callback function 54 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(55, Anna, function55) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 78)) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getInventory()->setLocationAndProcess(kItemKey, kObjectLocation1); + + setCallback(1); + setup_function45(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9270); + break; + + case 2: + setup_function56(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(56, Anna, function56) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAnna); + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarKronos; + break; + + case kAction191668032: + setup_function57(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(57, Anna, function57) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_850; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction191668032); + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + getSavePoints()->push(kEntityAnna, kEntityCoudert, kAction205033696); + getEntities()->drawSequenceLeft(kEntityAnna, "625Ef"); + getEntities()->enterCompartment(kEntityAnna, kObjectCompartmentF, true); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityAnna, "625Gf"); + getEntities()->enterCompartment(kEntityAnna, kObjectCompartmentF, true); + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction169032608); + break; + + case 4: + if (getSound()->isBuffered(kEntityAugust)) { + setCallback(4); + setup_updateFromTime(75); + } else { + setCallback(5); + setup_playSound("Aug3009"); + } + break; + + case 5: + getSound()->playSound(kEntityAnna, "Aug3009A"); + + setCallback(6); + setup_enterExitCompartment("628Bf", kObjectCompartmentF); + break; + + case 6: + getEntities()->exitCompartment(kEntityAnna, kObjectCompartmentF, true); + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction122288808); + + setup_function59(); + break; + } + break; + + case kAction123712592: + getEntities()->drawSequenceLeft(kEntityAnna, "628Af"); + + if (getSound()->isBuffered(kEntityAugust)) { + setCallback(4); + setup_updateFromTime(75); + } else { + setCallback(5); + setup_playSound("Aug3009"); + } + break; + + case kAction192063264: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4070) + || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4455)) { + getEntities()->exitCompartment(kEntityAnna, kObjectCompartmentF, true); + setup_function58(); + } else { + setCallback(3); + setup_enterExitCompartment("625Ff", kObjectCompartmentF); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(58, Anna, function58) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaSearchingCompartment); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAnnaSearchingCompartment); + getEntities()->clearSequences(kEntityAnna); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 8); + getSound()->playSound(kEntityAnna, "lib015"); + getSavePoints()->push(kEntityAnna, kEntityAugust, kAction122288808); + setup_function59(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(59, Anna, function59) + error("Anna: callback function 59 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(60, Anna, function60) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityAnna, kEntityMax, kAction122358304); + getSound()->playSound(kEntityAnna, rnd(2) ? "Ann3126" : "Ann3127"); + + setCallback(1); + setup_enterExitCompartment("630Cf", kObjectCompartmentF); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("630Df", kObjectCompartmentF); + break; + + case 2: + getEntities()->clearSequences(kEntityAnna); + getSavePoints()->push(kEntityAnna, kEntityCoudert, kAction189026624); + break; + + case 3: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityAnna); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction156049968: + setCallback(3); + setup_enterExitCompartment("629EF", kObjectCompartmentF); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(61, Anna, function61) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getState()->timeDelta = 3; + + setCallback(1); + setup_savegame(kSavegameTypeIndex, 0); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_function45(false); + break; + + case 2: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_draw("802US"); + break; + + case 5: + getEntities()->drawSequenceRight(kEntityAnna, "802UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityAnna); + + setCallback(6); + setup_callbackActionOnDirection(); + break; + + case 6: + getEntities()->clearSequences(kEntityAnna); + setup_function62(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(62, Anna, function62) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2259000 && !params->param2) { + params->param2 = 1; + getSavePoints()->push(kEntityAnna, kEntityVesna, kAction189299008); + setup_function63(); + } + break; + + case kActionDefault: + getData()->car = kCarBaggage; + getProgress().field_54 = 1; + break; + + case kAction235856512: + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(63, Anna, function63) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityAnna, kEntityChapters, kAction171843264); + break; + + // Game over with Anna killed! + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAnnaKilled); + getLogic()->gameOver(kSavegameTypeTime, kTime2250000, kSceneGameOverAnnaDied, true); + } + break; + + // Anna will get killed... + case kAction272177921: + if (getSound()->isBuffered("MUS012")) + getSound()->processEntry("MUS012"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaKilled); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(64, Anna, baggage) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAnna); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaBaggageArgument); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAnnaBaggageArgument); + + setCallback(2); + setup_savegame(kSavegameTypeTime, (EventIndex)kTimeNone); + break; + + case 2: + params->param1 = getFight()->setup(kFightAnna); + + if (params->param1) + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, params->param1 == Fight::kFightEndLost); + else { + getState()->time += 1800; + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventAnnaBagagePart2); + } + break; + + case 3: + getAction()->playAnimation(kEventAnnaBagagePart2); + getScenes()->loadSceneFromPosition(kCarBaggage, 96); + + getProgress().field_54 = 0; + getState()->time = kTime2266200; + + setup_function65(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(65, Anna, function65) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothes3; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(1); + setup_function15(kTimeEnd, "NONE"); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(66, Anna, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAnna); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothes2; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(67, Anna, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isPlayerPosition(kCarRedSleeping, 46)) { + UPDATE_PARAM_GOTO(params->param4, getState()->timeTicks, 30, label_next); + + getScenes()->loadSceneFromPosition(kCarRedSleeping, 8); + } + + params->param4 = 0; + +label_next: + if (params->param1) { + UPDATE_PARAM(params->param5, getState()->timeTicks, 75); + + params->param1 = 0; + params->param2 = 1; + + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, getEntities()->isInsideCompartment(kEntityMax, kCarRedSleeping, kPosition_4070) ? kCursorHand : kCursorNormal); + } + + params->param5 = 0; + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + getData()->location = kLocationInsideCompartment; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaConversation_34); + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (params->param1) { + setCallback(5); + setup_playSound(getSound()->justAMinuteCath()); + } else { + setCallback(savepoint.action == kActionKnock ? 2 : 3); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->drawSequenceLeft(kEntityAnna, "511B"); + break; + + case kActionDrawScene: + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + params->param1 = 0; + params->param2 = 0; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAnnaConversation_34); + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 8); + + setup_function68(); + break; + + case 2: + case 3: + setCallback(4); + setup_playSound("ANN1016"); + break; + + case 4: + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorTalk, kCursorNormal); + params->param1 = 1; + break; + + case 5: + params->param1 = 0; + params->param2 = 1; + break; + } + break; + + case kAction191001984: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getData()->inventoryItem = kItemNone; + + setup_function69(); + break; + + case kAction219971920: + params->param3 = 1; + getData()->inventoryItem = kItemInvalid; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(68, Anna, function68) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + setCallback(1); + setup_function15(kTime2511900, "NONE"); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + break; + + case kAction191001984: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + setup_function69(); + break; + + case kAction201431954: + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(69, Anna, function69) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM(params->param2, getState()->time, 4500); + + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_9270; + getData()->location = kLocationOutsideCompartment; + + setup_function70(); + break; + } + + TIME_CHECK_CALLBACK(kTime2535300, params->param3, 4, setup_callbackActionRestaurantOrSalon); + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case kActionDrawScene: + if (params->param1 && getEntities()->isInsideTrainCar(kEntityPlayer, kCarRedSleeping)) { + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationOutsideCompartment; + + setup_function70(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updatePosition("127A", kCarRestaurant, 56); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAnna, "127B"); + getSavePoints()->push(kEntityAnna, kEntityServers1, kAction258136010); + break; + + case 4: + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_updatePosition("127G", kCarRestaurant, 56); + break; + + case 5: + setup_function70(); + break; + } + break; + + case kAction100969180: + getEntities()->clearSequences(kEntityAnna); + params->param1 = 1; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityAnna, "127E"); + getSavePoints()->push(kEntityAnna, kEntityAbbot, kAction203073664); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAnna, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(70, Anna, function70) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function72(kCarRedSleeping, kPosition_4070); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function71(); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + getEntities()->clearSequences(kEntityAnna); + setup_function73(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(71, Anna, function71) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->exitCompartment(kEntityAnna, kObjectCompartmentF); + getData()->entityPosition = kPosition_4070; + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityAnna, "625Af"); + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 7) + || getEntities()->isPlayerPosition(kCarRedSleeping, 28) + || getEntities()->isPlayerPosition(kCarRedSleeping, 56)) + getScenes()->loadScene(getScenes()->processIndex(getState()->scene)); + + getEntities()->enterCompartment(kEntityAnna, kObjectCompartmentF); + + getData()->location = kLocationInsideCompartment; + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4070) + || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4455)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartmentF, true); + } + break; + + case kActionDrawScene: + if (!getEvent(kEventAnnaTiredKiss) + && getEntities()->isDistanceBetweenEntities(kEntityPlayer, kEntityAnna, 2000) + && getEntities()->hasValidFrame(kEntityAnna) + && getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaTiredKiss); + } + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAnnaTiredKiss); + getScenes()->loadSceneFromPosition(kCarRestaurant, 29); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(72, Anna, function72, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEvent(kEventAnnaTired) || getEntities()->isWalkingOppositeToPlayer(kEntityAnna)) + getData()->inventoryItem = kItemNone; + else + getData()->inventoryItem = kItemInvalid; + + if (getEntities()->updateEntity(kEntityAnna, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + CALLBACK_ACTION(); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaTired); + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityAnna, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + } else if (!getEvent(kEventAnnaTired)) + getData()->inventoryItem = kItemInvalid; + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAnnaTired); + + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(73, Anna, function73) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 == kTimeInvalid || params->param1 >= getState()->time) + break; + + if (params->param2 >= getState()->time) { + if (!((getEntities()->isPlayerInCar(kCarGreenSleeping) || getEntities()->isPlayerInCar(kCarRedSleeping)) && params->param3)) + params->param3 = getState()->time; + + if (params->param3 >= getState()->time) + break; + } + + params->param3 = kTimeInvalid; + + if (!getEntities()->isPlayerInCar(kCarGreenSleeping) && !getEntities()->isPlayerInCar(kCarRedSleeping)) + getSound()->playSound(kEntityPlayer, "BUMP"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventTrainHijacked); + break; + + case kActionKnock: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(2); + setup_playSound("LIB012"); + break; + + case kActionOpenDoor: + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventAnnaKissTrainHijacked); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getState()->timeDelta = 1; + + params->param1 = getState()->time + 4500; + params->param2 = getState()->time + 9000; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventTrainHijacked); + getSavePoints()->push(kEntityAnna, kEntityChapters, kAction139254416); + break; + + case 2: + setCallback(3); + setup_playSound("Ann4200"); + break; + + case 3: + getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + + case 4: + getAction()->playAnimation(kEventAnnaKissTrainHijacked); + getSavePoints()->push(kEntityAnna, kEntityChapters, kAction139254416); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(74, Anna, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAnna); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarBaggageRear; + getData()->clothes = kClothes3; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(75, Anna, chapter5Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + if (getCallback() == 1) { + if (getProgress().field_C) + getAction()->playAnimation(getEvent(kEventAnnaKissTrainHijacked) ? kEventAnnaBaggageTies2 : kEventAnnaBaggageTies); + else + getAction()->playAnimation(getEvent(kEventAnnaKissTrainHijacked) ? kEventAnnaBaggageTies3 : kEventAnnaBaggageTies4); + + getScenes()->loadSceneFromPosition(kCarBaggage, 8); + setup_function76(); + } + break; + + case kAction272177921: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAnnaBaggageTies); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(76, Anna, function76) + if (savepoint.action == kAction158480160) + setup_function77(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(77, Anna, function77) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime3645000 && !params->param2) { + params->param2 = 1; + getState()->timeDelta = 0; + } + break; + + case kActionKnock: + case kActionOpenDoor: + getSound()->playSound(kEntityPlayer, savepoint.action == kActionKnock ? "LIB012" : "LIB014"); + + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventAnnaDialogGoToJerusalem); + break; + + case kActionDefault: + getObjects()->update(kObject106, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (!params->param1 && getEntities()->isInsideTrainCar(kEntityPlayer, kCarBaggage)) { + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 1; + break; + + case 2: + getObjects()->update(kObject106, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getAction()->playAnimation(kEventAnnaDialogGoToJerusalem); + + getState()->time = kTimeCityConstantinople; + getState()->timeDelta = 0; + + getSavePoints()->push(kEntityAnna, kEntityTatiana, kAction236060709); + + getScenes()->loadSceneFromPosition(kCarBaggage, 97, 1); + + setCallback(3); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case 3: + setup_function78(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(78, Anna, function78) + switch (savepoint.action) { + default: + break; + + case kActionDrawScene: + if ((getEntities()->isInRestaurant(kEntityPlayer) || getEntities()->isInSalon(kEntityPlayer)) && getInventory()->hasItem(kItemFirebird)) { + setup_function80(); + break; + } + + getState()->time = kTimeInvalid2; + + setCallback(getInventory()->get(kItemFirebird)->location == kObjectLocation4 ? 2 : 1); + setup_savegame(kSavegameTypeEvent, getInventory()->get(kItemFirebird)->location == kObjectLocation4 ? kEventKronosHostageAnna : kEventKronosHostageAnnaNoFirebird); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventKronosHostageAnnaNoFirebird); + getLogic()->gameOver(kSavegameTypeEvent2, kEventAugustUnhookCarsBetrayal, kSceneNone, true); + break; + + case 2: + getAction()->playAnimation(kEventKronosHostageAnna); + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + getSound()->playSound(kEntityAnna, "Mus024", SoundManager::kFlagDefault); + setup_function79(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(79, Anna, function79) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + getState()->time = kTime5933; + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); + break; + + case kActionDrawScene: + if (getEntities()->isInRestaurant(kEntityPlayer) && getInventory()->hasItem(kItemFirebird)) { + setup_function80(); + break; + } + + if (getEntities()->isInSalon(kEntityPlayer) && !getEvent(kEventKahinaPunch)) { + getState()->time = kTime5933; + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEntities()->isInSalon(kEntityPlayer)) + getAction()->playAnimation(kEventKahinaPunchSalon); + else if (getEntities()->isInRestaurant(kEntityPlayer)) + getAction()->playAnimation(kEventKahinaPunchRestaurant); + else if (getEntities()->isInKitchen(kEntityPlayer)) + getAction()->playAnimation(kEventKahinaPunchKitchen); + else if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) + getAction()->playAnimation(kEventKahinaPunchBaggageCarEntrance); + else if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarBaggage)) + getAction()->playAnimation(kEventKahinaPunchBaggageCar); + break; + + case 2: + getAction()->playAnimation(kEventKahinaPunchSalon); + break; + } + + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(80, Anna, function80) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->timeTicks, 450); + + getSound()->playSound(kEntityPlayer, "Kro5001", SoundManager::kFlagDefault); + break; + + case kActionEndSound: + getSound()->playSound(kEntityPlayer, "Kro5002", SoundManager::kFlagDefault); + getState()->time = kTime4923000; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosBringFirebird); + break; + + case kActionDefault: + getState()->time = kTime4929300; + + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getSound()->isBuffered(kEntityAnna)) + getSound()->processEntry(kEntityAnna); + + getAction()->playAnimation(kEventKronosBringFirebird); + getScenes()->loadSceneFromItem(kItemFirebird); + getSound()->playSound(kEntityAnna, "Mus025", SoundManager::kFlagDefault); + break; + + case 2: + getAction()->playAnimation(kEventKahinaPunch); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + + case 3: + getProgress().isEggOpen = true; + + if (getSound()->isBuffered(kEntityAnna)) + getSound()->processEntry(kEntityAnna); + + getAction()->playAnimation(kEventKronosOpenFirebird); + getScenes()->loadSceneFromPosition(kCarRestaurant, 3); + + setup_finalSequence(); + break; + } + break; + + case kAction205294778: + getState()->time = kTime4929300; + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventKronosOpenFirebird); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(81, Anna, finalSequence) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->timeTicks, 180); + + getSound()->playSound(kEntityTrain, "LIB069"); + getLogic()->gameOver(kSavegameTypeIndex, 2, kSceneNone, true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventCathCloseEggNoBackground); + getAction()->playAnimation(kEventKronosGiveFirebird); + + if (getInventory()->hasItem(kItemWhistle)) + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverTrainExplosion, true); + else if (getInventory()->get(kItemWhistle)->location == kObjectLocation1) + getLogic()->gameOver(kSavegameTypeEvent2, kEventAnnaDialogGoToJerusalem, kSceneNone, true); + else + getLogic()->gameOver(kSavegameTypeEvent2, kEventAugustUnhookCarsBetrayal, kSceneGameOverTrainExplosion2, true); + break; + + case 2: + getInventory()->removeItem(kItemWhistle); + getLogic()->playFinalSequence(); + break; + } + break; + + case kAction224309120: + getProgress().isEggOpen = false; + getState()->time = kTimeCityConstantinople; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosGiveFirebird); + break; + + case kActionUseWhistle: + getProgress().isEggOpen = false; + setGlobalTimer(0); + getState()->time = kTimeCityConstantinople; + + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventFinalSequence); + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/anna.h b/engines/lastexpress/entities/anna.h new file mode 100644 index 0000000000..4712f4b262 --- /dev/null +++ b/engines/lastexpress/entities/anna.h @@ -0,0 +1,252 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ANNA_H +#define LASTEXPRESS_ANNA_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Anna : public Entity { +public: + Anna(LastExpressEngine *engine); + ~Anna() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + DECLARE_FUNCTION(function12) + + /** + * Draws the entity along with another one + * + * @param sequence1 The sequence to draw + * @param sequence2 The sequence to draw for the second entity + * @param entity The EntityIndex of the second entity + */ + DECLARE_FUNCTION_3(draw2, const char* sequence1, const char* sequence2, EntityIndex entity) + + /** + * Updates parameter 2 using ticks value + * + * @param ticks The number of ticks to add + */ + DECLARE_FUNCTION_1(updateFromTicks, uint32 ticks) + + DECLARE_FUNCTION_2(function15, TimeValue timeValue, const char *sequence) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION_2(function17, uint32, uint32) + + DECLARE_FUNCTION_1(function18, TimeValue timeValue) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + DECLARE_FUNCTION(function30) + DECLARE_FUNCTION(function31) + DECLARE_FUNCTION(function32) + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + DECLARE_FUNCTION(function36) + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + DECLARE_FUNCTION_2(function39, CarIndex car, EntityPosition entityPosition) + DECLARE_FUNCTION(function40) + DECLARE_FUNCTION(function41) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + DECLARE_FUNCTION_1(function45, bool useAction1) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + DECLARE_FUNCTION(function47) + DECLARE_FUNCTION(function48) + DECLARE_FUNCTION(leaveTableWithAugust) + DECLARE_FUNCTION(function50) + DECLARE_FUNCTION(function51) + DECLARE_FUNCTION(function52) + DECLARE_FUNCTION(function53) + DECLARE_FUNCTION(function54) + DECLARE_FUNCTION(function55) + DECLARE_FUNCTION(function56) + DECLARE_FUNCTION(function57) + DECLARE_FUNCTION(function58) + DECLARE_FUNCTION(function59) + DECLARE_FUNCTION(function60) + DECLARE_FUNCTION(function61) + DECLARE_FUNCTION(function62) + DECLARE_FUNCTION(function63) + DECLARE_FUNCTION(baggage) + DECLARE_FUNCTION(function65) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function68) + DECLARE_FUNCTION(function69) + DECLARE_FUNCTION(function70) + DECLARE_FUNCTION(function71) + DECLARE_FUNCTION_2(function72, CarIndex car, EntityPosition entityPosition) + DECLARE_FUNCTION(function73) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + DECLARE_FUNCTION(function76) + DECLARE_FUNCTION(function77) + DECLARE_FUNCTION(function78) + DECLARE_FUNCTION(function79) + DECLARE_FUNCTION(function80) + DECLARE_FUNCTION(finalSequence) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ANNA_H diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp new file mode 100644 index 0000000000..419d716ced --- /dev/null +++ b/engines/lastexpress/entities/august.cpp @@ -0,0 +1,2804 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/august.h" + +#include "lastexpress/entities/alexei.h" +#include "lastexpress/entities/salko.h" +#include "lastexpress/entities/verges.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +August::August(LastExpressEngine *engine) : Entity(engine, kEntityAugust) { + ADD_CALLBACK_FUNCTION(August, reset); + ADD_CALLBACK_FUNCTION(August, updateFromTime); + ADD_CALLBACK_FUNCTION(August, draw); + ADD_CALLBACK_FUNCTION(August, updatePosition); + ADD_CALLBACK_FUNCTION(August, enterExitCompartment); + ADD_CALLBACK_FUNCTION(August, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(August, enterExitCompartment3); + ADD_CALLBACK_FUNCTION(August, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(August, callSavepoint); + ADD_CALLBACK_FUNCTION(August, callSavepointNoDrawing); + ADD_CALLBACK_FUNCTION(August, draw2); + ADD_CALLBACK_FUNCTION(August, playSound); + ADD_CALLBACK_FUNCTION(August, playSound16); + ADD_CALLBACK_FUNCTION(August, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(August, savegame); + ADD_CALLBACK_FUNCTION(August, updateEntity); + ADD_CALLBACK_FUNCTION(August, function17); + ADD_CALLBACK_FUNCTION(August, updateEntity2); + ADD_CALLBACK_FUNCTION(August, function19); + ADD_CALLBACK_FUNCTION(August, function20); + ADD_CALLBACK_FUNCTION(August, function21); + ADD_CALLBACK_FUNCTION(August, chapter1); + ADD_CALLBACK_FUNCTION(August, function23); + ADD_CALLBACK_FUNCTION(August, dinner); + ADD_CALLBACK_FUNCTION(August, chapter1Handler); + ADD_CALLBACK_FUNCTION(August, function26); + ADD_CALLBACK_FUNCTION(August, function27); + ADD_CALLBACK_FUNCTION(August, function28); + ADD_CALLBACK_FUNCTION(August, function29); + ADD_CALLBACK_FUNCTION(August, restaurant); + ADD_CALLBACK_FUNCTION(August, function31); + ADD_CALLBACK_FUNCTION(August, function32); + ADD_CALLBACK_FUNCTION(August, function33); + ADD_CALLBACK_FUNCTION(August, function34); + ADD_CALLBACK_FUNCTION(August, chapter2); + ADD_CALLBACK_FUNCTION(August, chapter2Handler); + ADD_CALLBACK_FUNCTION(August, function37); + ADD_CALLBACK_FUNCTION(August, function38); + ADD_CALLBACK_FUNCTION(August, function39); + ADD_CALLBACK_FUNCTION(August, chapter3); + ADD_CALLBACK_FUNCTION(August, function41); + ADD_CALLBACK_FUNCTION(August, function42); + ADD_CALLBACK_FUNCTION(August, chapter3Handler); + ADD_CALLBACK_FUNCTION(August, function44); + ADD_CALLBACK_FUNCTION(August, function45); + ADD_CALLBACK_FUNCTION(August, function46); + ADD_CALLBACK_FUNCTION(August, function47); + ADD_CALLBACK_FUNCTION(August, function48); + ADD_CALLBACK_FUNCTION(August, function49); + ADD_CALLBACK_FUNCTION(August, function50); + ADD_CALLBACK_FUNCTION(August, function51); + ADD_CALLBACK_FUNCTION(August, function52); + ADD_CALLBACK_FUNCTION(August, function53); + ADD_CALLBACK_FUNCTION(August, function54); + ADD_CALLBACK_FUNCTION(August, function55); + ADD_CALLBACK_FUNCTION(August, function56); + ADD_CALLBACK_FUNCTION(August, chapter4); + ADD_CALLBACK_FUNCTION(August, chapter4Handler); + ADD_CALLBACK_FUNCTION(August, function59); + ADD_CALLBACK_FUNCTION(August, function60); + ADD_CALLBACK_FUNCTION(August, function61); + ADD_CALLBACK_FUNCTION(August, function62); + ADD_CALLBACK_FUNCTION(August, function63); + ADD_CALLBACK_FUNCTION(August, function64); + ADD_CALLBACK_FUNCTION(August, function65); + ADD_CALLBACK_FUNCTION(August, chapter5); + ADD_CALLBACK_FUNCTION(August, chapter5Handler); + ADD_CALLBACK_FUNCTION(August, function68); + ADD_CALLBACK_FUNCTION(August, unhookCars); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, August, reset) + Entity::reset(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(2, August, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, August, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(4, August, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(5, August, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(6, August, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_6470, kPosition_6130, kCarGreenSleeping, kObjectCompartment3, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(7, August, enterExitCompartment3, ObjectIndex) + if (savepoint.action == kAction4) { + getEntities()->exitCompartment(kEntityAugust, (ObjectIndex)params->param4); + CALLBACK_ACTION(); + return; + } + + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, August, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(9, August, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IIS(10, August, callSavepointNoDrawing, EntityIndex, ActionIndex) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + if (!params->param6) + getSavePoints()->call(kEntityAugust, (EntityIndex)params->param1, (ActionIndex)params->param2, (char *)¶ms->seq); + + CALLBACK_ACTION(); + break; + + case kAction10: + if (!params->param6) { + getSavePoints()->call(kEntityAugust, (EntityIndex)params->param1, (ActionIndex)params->param2, (char *)¶ms->seq); + params->param6 = 1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SSI(11, August, draw2, EntityIndex) + Entity::draw2(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(12, August, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(13, August, playSound16) + Entity::playSound(savepoint, false, SoundManager::kFlagDefault); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, August, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(15, August, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(16, August, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + getProgress().eventMetAugust ? getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1002A" : "CAT1002") : getSound()->excuseMeCath(); + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(17, August, function17, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 < getState()->time && !params->param2) { + params->param2 = 1; + CALLBACK_ACTION(); + break; + } + + if (getEntities()->isPlayerInCar(kCarGreenSleeping) || getEntities()->isPlayerInCar(kCarRedSleeping)) { + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { + setCallback(2); + setup_updateEntity2(kCarGreenSleeping, kPosition_540); + } else { + setCallback(3); + setup_updateEntity2(kCarRedSleeping, kPosition_9460); + } + } + break; + + case kActionDefault: + ENTITY_PARAM(0, 1) = 0; + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_540); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (ENTITY_PARAM(0, 1)) { + CALLBACK_ACTION(); + break; + } + + getEntities()->clearSequences(kEntityAugust); + break; + + case 2: + case 3: + if (ENTITY_PARAM(0, 1)) { + CALLBACK_ACTION(); + break; + } + + getEntities()->clearSequences(kEntityAugust); + + setCallback(4); + setup_updateFromTime(450); + break; + + case 4: + setCallback(5); + setup_updateEntity2(kCarRedSleeping, kPosition_540); + break; + + case 5: + if (ENTITY_PARAM(0, 1)) { + CALLBACK_ACTION(); + break; + } + + getEntities()->clearSequences(kEntityAugust); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(18, August, updateEntity2, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + } else if (getEntities()->isDistanceBetweenEntities(kEntityAugust, kEntityPlayer, 1000) + && !getEntities()->isInGreenCarEntrance(kEntityPlayer) + && !getEntities()->isInsideCompartments(kEntityPlayer) + && !getEntities()->checkFields10(kEntityPlayer)) { + + if (getData()->car == kCarGreenSleeping || getData()->car == kCarRedSleeping) { + ENTITY_PARAM(0, 1) = 1; + CALLBACK_ACTION(); + } + } + break; + + case kActionDefault: + if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(19, August, function19, bool, bool) + error("August: callback function 19 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(20, August, function20, bool) + // Expose parameters as ISSI and ignore the default exposed parameters + EntityData::EntityParametersISSI *parameters = (EntityData::EntityParametersISSI*)_data->getCurrentParameters(); + + switch (savepoint.action) { + default: + break; + + case kActionDefault: + switch (getProgress().chapter) { + default: + break; + + case kChapter1: + strcpy((char *)¶meters->seq1, "626"); + break; + + case kChapter2: + case kChapter3: + if (getData()->clothes != kClothes2) { + strcpy((char *)¶meters->seq1, "666"); + break; + } + // Fallback to next case + + case kChapter4: + case kChapter5: + strcpy((char *)¶meters->seq1, "696"); + break; + } + + if (params->param1) { + strcpy((char *)¶meters->seq2, Common::String::printf("%s%s", (char *)¶meters->seq1, "Gc").c_str()); + + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + } else { + strcpy((char *)¶meters->seq2, Common::String::printf("%s%s", (char *)¶meters->seq1, "Ec").c_str()); + } + + setCallback(1); + setup_enterExitCompartment((char *)¶meters->seq2, kObjectCompartment3); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: { + getData()->location = kLocationOutsideCompartment; + + Common::String sequence2 = Common::String::printf("%s%s", (char *)¶meters->seq2, "Pc"); + strcpy((char *)¶meters->seq2, (char *)¶meters->seq1); + + getEntities()->drawSequenceLeft(kEntityAugust, sequence2.c_str()); + getEntities()->enterCompartment(kEntityAugust, kObjectCompartment3, true); + + if (getProgress().chapter != kChapter3 || getState()->time >= kTime1998000) { + setCallback(3); + setup_playSound("AUG2095"); + } else { + setCallback(2); + setup_playSound("AUG2094"); + } + } + break; + + case 2: + case 3: + getSavePoints()->push(kEntityAugust, kEntityMertens, kAction269436673); + strcpy((char *)¶meters->seq2, Common::String::printf("%s%s", (char *)¶meters->seq1, "Qc").c_str()); + + getEntities()->drawSequenceLeft(kEntityAugust, (char *)¶meters->seq2); + break; + } + break; + + case kAction69239528: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->exitCompartment(kEntityAugust, kObjectCompartment3, true); + + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(21, August, function21, TimeValue) + error("August: callback function 21 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, August, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject11, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_4691; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + + getProgress().eventMetAugust = false; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(23, August, function23, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().field_14 == 29 || getProgress().field_14 == 3) { + if (params->param3) { + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_enterExitCompartment("626Ea", kObjectCompartment1); + } else { + getEntities()->exitCompartment(kEntityAugust, kObjectCompartment1, true); + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + CALLBACK_ACTION(); + } + break; + } + + if (!params->param2) { + + if (!CURRENT_PARAMS(1, 3)) + CURRENT_PARAMS(1, 3) = getState()->timeTicks + 45; + + if (CURRENT_PARAMS(1, 3) >= getState()->timeTicks) + break; + + if (!params->param5) { + setCallback(8); + setup_playSound("AUG1002B"); + break; + } + +label_callback_8: + UPDATE_PARAM_PROC(CURRENT_PARAMS(1, 4), getState()->timeTicks, 75) + getEntities()->exitCompartment(kEntityAugust, kObjectCompartment1, true); + + if (getProgress().eventCorpseMovedFromFloor) { + setCallback(9); + setup_enterExitCompartment("626Da", kObjectCompartment1); + } else if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { + setCallback(10); + setup_enterExitCompartment3("626Da", kObjectCompartment1); + } else { + getScenes()->loadSceneFromPosition(kCarNone, 1); + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + setCallback(11); + setup_savegame(kSavegameTypeEvent, kEventAugustFindCorpse); + } + break; + UPDATE_PARAM_PROC_END + +label_callback_9: + if (params->param3 && params->param1 < getState()->time && !CURRENT_PARAMS(1, 5)) { + CURRENT_PARAMS(1, 5) = 1; + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(12); + setup_enterExitCompartment("626Ea", kObjectCompartment1); + } + break; + } + + if (!CURRENT_PARAMS(1, 1)) + CURRENT_PARAMS(1, 1) = getState()->timeTicks + 45; + + if (CURRENT_PARAMS(1, 1) >= getState()->timeTicks) + break; + + if (getObjects()->get(kObjectCompartment1).location == kObjectLocation1) { + UPDATE_PARAM(CURRENT_PARAMS(1, 2), getState()->timeTicks, 75); + + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + params->param6++; + + switch (params->param6) { + default: + break; + + case 1: + setCallback(5); + setup_playSound("LIB013"); + return; + + case 2: + setCallback(7); + setup_playSound("LIB012"); + return; + + case 3: + params->param8++; + + if (params->param8 >= 3) { + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorHandKnock, kCursorHand); + CALLBACK_ACTION(); + break; + } + + params->param6 = 0; + } + + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, params->param4 ? kCursorNormal : kCursorTalk, kCursorHand); + CURRENT_PARAMS(1, 2) = 0; + } else { + + if (getProgress().eventCorpseMovedFromFloor && getProgress().jacket != kJacketBlood) { + params->param7 = (getObjects()->get(kObjectCompartment1).location2 == kObjectLocation1) ? 8 : 7; + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventMeetAugustTylerCompartment); + } else { + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventAugustFindCorpse); + } + } + break; + + case kActionKnock: + if (params->param3) { + getObjects()->update(kObjectCompartment1, kEntityAugust, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(15); + setup_playSound("LIB012"); + } else if (!params->param4) { + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + setCallback(17); + setup_playSound("AUG1002A"); + } + break; + + case kActionOpenDoor: + if (getProgress().eventCorpseMovedFromFloor && getProgress().jacket != kJacketBlood) { + if (params->param3) { + getData()->location = kLocationInsideCompartment; + + params->param7 = (getObjects()->get(kObjectCompartment1).location2 == kObjectLocation1) ? kEventMeetAugustHisCompartmentBed : kEventMeetAugustHisCompartment; + } else { + params->param7 = (getObjects()->get(kObjectCompartment1).location2 == kObjectLocation1) ? kEventMeetAugustTylerCompartmentBed : kEventMeetAugustTylerCompartment; + } + + setCallback(14); + setup_savegame(kSavegameTypeEvent, kEventMeetAugustTylerCompartment); + } else { + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + setCallback(13); + setup_savegame(kSavegameTypeEvent, kEventAugustFindCorpse); + } + break; + + case kActionDefault: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_8200) + || getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_7850) + || getEntities()->isOutsideAlexeiWindow()) { + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + if (getEntities()->isOutsideAlexeiWindow()) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + getSound()->playSound(kEntityPlayer, "LIB012"); + + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, kCursorTalk, kCursorHand); + + params->param2 = 1; + } else { + setCallback(1); + setup_enterExitCompartment("626Aa", kObjectCompartment1); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityAugust, "626Ba"); + getEntities()->enterCompartment(kEntityAugust, kObjectCompartment1, true); + break; + + case 2: + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + CALLBACK_ACTION(); + break; + + case 3: + getSound()->playSound(kEntityPlayer, "LIB014"); + getAction()->playAnimation(kEventAugustFindCorpse); + if (getEvent(kEventDinerAugustOriginalJacket)) + getLogic()->gameOver(kSavegameTypeEvent2, kEventDinerAugustOriginalJacket, getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, true); + else if (getProgress().eventCorpseMovedFromFloor) + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + else + getLogic()->gameOver(kSavegameTypeIndex, 1, getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, true); + break; + + case 4: + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getSound()->playSound(kEntityPlayer, "LIB014"); + getEntities()->clearSequences(kEntityAugust); + getData()->location = kLocationInsideCompartment; + + getAction()->playAnimation((EventIndex)params->param7); + getSound()->playSound(kEntityPlayer, "LIB015"); + getProgress().eventMetAugust = true; + getData()->location = kLocationOutsideCompartment; + + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + + case 5: + setCallback(6); + setup_playSound16("AUG1002B"); + break; + + case 6: + case 7: + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, params->param4 ? kCursorNormal : kCursorTalk, kCursorHand); + ENTITY_PARAM(1, 2) = 0; + break; + + case 8: + params->param5 = 1; + goto label_callback_8; + + case 9: + params->param3 = 1; + getEntities()->clearSequences(kEntityAugust); + getData()->location = kLocationInsideCompartment; + getObjects()->update(kObjectCompartment1, kEntityAugust, kObjectLocationNone, kCursorHandKnock, kCursorHand); + goto label_callback_9; + + case 10: + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + setCallback(11); + setup_savegame(kSavegameTypeEvent, kEventAugustFindCorpse); + break; + + case 11: + getAction()->playAnimation(kEventAugustFindCorpse); + + getLogic()->gameOver(getEvent(kEventDinerAugustOriginalJacket) ? kSavegameTypeEvent2 : kSavegameTypeIndex, + getEvent(kEventDinerAugustOriginalJacket) ? kEventDinerAugustOriginalJacket : 1, + getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, + true); + break; + + case 12: + getData()->location = kLocationOutsideCompartment; + CALLBACK_ACTION(); + break; + + case 13: + getSound()->playSound(kEntityPlayer, getObjects()->get(kObjectCompartment1).location == kObjectLocation1 ? "LIB032" : "LIB014"); + getAction()->playAnimation(kEventAugustFindCorpse); + + if (getEvent(kEventDinerAugustOriginalJacket)) + getLogic()->gameOver(kSavegameTypeEvent2, kEventDinerAugustOriginalJacket, getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, true); + else if (getProgress().eventCorpseMovedFromFloor) + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + else + getLogic()->gameOver(kSavegameTypeIndex, 1, getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, true); + break; + + case 14: + if (!params->param2) + getSound()->playSound(kEntityPlayer, getObjects()->get(kObjectCompartment1).location == kObjectLocation1 ? "LIB032" : "LIB014"); + + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getAction()->playAnimation((EventIndex)params->param7); + getProgress().eventMetAugust = true; + getData()->location = kLocationOutsideCompartment; + + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + + case 15: + setCallback(16); + setup_playSound("AUG1128A"); + break; + + case 16: + getObjects()->update(kObjectCompartment1, kEntityAugust, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + + case 17: + params->param4 = 1; + getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, August, dinner) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventDinerAugust); + break; + + case kActionCallback: + if (getCallback() == 1) { + + getAction()->playAnimation(getEntities()->isInRestaurant(kEntityAlexei) ? kEventDinerAugustAlexeiBackground : kEventDinerAugust); + getProgress().eventMetAugust = true; + + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, August, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1 && getProgress().eventCorpseFound) { + getSavePoints()->push(kEntityAugust, kEntityPascale, kAction239072064); + params->param1 = 1; + } + + if (getState()->time > kTime1080000 && !params->param3) { + params->param3 = 1; + + if (!params->param1) { + getSavePoints()->push(kEntityAugust, kEntityPascale, kAction239072064); + params->param1 = 1; + } + } + + if (getState()->time > kTime1093500 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_callSavepoint("010J", kEntityTables3, kActionDrawTablesWithChairs, "010K"); + } + break; + + case kAction1: + params->param2 = 0; + getData()->inventoryItem = kItemNone; + getSavePoints()->push(kEntityAugust, kEntityPascale, kAction191604416); + + if (getProgress().jacket == kJacketGreen) { + setCallback(3); + setup_dinner(); + } else { + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventDinerAugustOriginalJacket); + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityAugust, kEntityTables3, kAction136455232); + getEntities()->drawSequenceLeft(kEntityAugust, "010B"); + + if (!getProgress().eventMetAugust) + params->param2 = kItemInvalid; + + getData()->inventoryItem = (InventoryItem)params->param2; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction204704037); + getEntities()->drawSequenceRight(kEntityAugust, "803DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + setup_function26(); + break; + + case 3: + setup_function28(); + break; + + case 4: + getSavePoints()->push(kEntityAugust, kEntityAlexei, kAction225182640); + getAction()->playAnimation(kEventDinerAugustOriginalJacket); + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocation3, kCursorNormal, kCursorNormal); + + getData()->location = kLocationOutsideCompartment; + + getSavePoints()->push(kEntityAugust, kEntityTables3, kActionDrawTablesWithChairs, "010K"); + getEntities()->drawSequenceRight(kEntityAugust, "010P"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + + setCallback(5); + setup_callbackActionOnDirection(); + break; + + case 5: + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction204704037); + getEntities()->drawSequenceRight(kEntityAugust, "803DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(6); + setup_callbackActionOnDirection(); + break; + + case 6: + getProgress().field_14 = 2; + + setCallback(7); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case 7: + setCallback(8); + setup_function23(kTimeNone); + break; + + case 8: + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true); + break; + } + break; + + case kAction168046720: + getData()->inventoryItem = kItemNone; + break; + + case kAction168627977: + getData()->inventoryItem = (InventoryItem)params->param2; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, August, function26) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getProgress().eventMetAugust || getProgress().field_14) { + setCallback(5); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + } else { + getProgress().field_14 = 2; + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function23((TimeValue)(getState()->time + 13500)); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case 3: + setCallback(4); + setup_function19(false, false); + break; + + case 4: + if (getProgress().field_14 == 2) + getProgress().field_14 = 0; + + setCallback(7); + setup_function21((TimeValue)(getState()->time + 900)); + break; + + case 5: + setCallback(6); + setup_function19(false, false); + break; + + case 6: + setCallback(7); + setup_function21((TimeValue)(getState()->time + 900)); + break; + + case 7: + setup_function27(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, August, function27) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(false); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("803US"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityAugust, "010A"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(5); + setup_callSavepointNoDrawing(kEntityTables3, kAction136455232, "BOGUS"); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + setup_function28(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, August, function28) + switch (savepoint.action) { + default: + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + params->param1 = 0; + + setCallback(3); + setup_dinner(); + break; + + case kActionDefault: + if (!getProgress().eventMetAugust && getProgress().jacket == kJacketGreen) + params->param1 = kItemInvalid; + + getEntities()->drawSequenceLeft(kEntityAugust, "010B"); + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction304061224); + getData()->inventoryItem = (InventoryItem)params->param1; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction203859488); + getData()->inventoryItem = (InventoryItem)params->param1; + getEntities()->drawSequenceLeft(kEntityAugust, "010B"); + break; + + case 2: + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction136702400); + getEntities()->drawSequenceLeft(kEntityAugust, "010B"); + setup_function29(); + break; + } + break; + + case kAction168046720: + getData()->inventoryItem = kItemNone; + break; + + case kAction168627977: + getData()->inventoryItem = (InventoryItem)params->param1; + break; + + case kAction170016384: + getData()->inventoryItem = kItemNone; + getEntities()->drawSequenceLeft(kEntityServers0, "BLANK"); + getEntities()->drawSequenceLeft(kEntityAugust, "010G"); + + setCallback(2); + setup_playSound("AUG1053"); + break; + + case kAction268773672: + getData()->inventoryItem = kItemNone; + getEntities()->drawSequenceLeft(kEntityAugust, "010D"); + + setCallback(1); + setup_playSound("AUG1052"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, August, function29) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getProgress().field_28 || (params->param2 && params->param3 == kTimeInvalid)) + break; + + if (getState()->time < kTime1134000) { + + if (!getEntities()->isInRestaurant(kEntityPlayer) + || getSound()->isBuffered("MRB1076") || getSound()->isBuffered("MRB1078") || getSound()->isBuffered("MRB1078A")) + params->param3 = getState()->time + 225; + + if (params->param3 > getState()->time) + break; + } + + params->param3 = kTimeInvalid; + getData()->inventoryItem = kItemNone; + getProgress().field_28 = 0; + + setup_restaurant(); + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + params->param1 = kItemNone; + + setCallback(1); + setup_dinner(); + break; + + case kActionDefault: + if (!getProgress().eventMetAugust && getProgress().jacket == kJacketGreen) + params->param1 = kItemInvalid; + + getData()->inventoryItem = (InventoryItem)LOBYTE(params->param1); + + getEntities()->drawSequenceLeft(kEntityAugust, "010H"); + break; + + case kAction168046720: + getData()->inventoryItem = kItemNone; + break; + + case kAction168627977: + getData()->inventoryItem = (InventoryItem)LOBYTE(params->param1); + break; + + case kAction189426612: + params->param2 = 1; + break; + + case kAction235257824: + params->param2 = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, August, restaurant) + error("August: callback function 30 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, August, function31) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function19(false, false); + break; + + case 2: + setCallback(2); + setup_function21(kTime1161000); + break; + + case 3: + case 4: + if (getProgress().field_14 == 29) { + setCallback(4); + setup_function21((TimeValue)(getState()->time + 900)); + } else { + setup_function32(); + } + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, August, function32) + error("August: callback function 32 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, August, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(getProgress().eventMetAugust ? 1 : 2); + setup_function21(getProgress().eventMetAugust ? (TimeValue)(getState()->time + 9000) : kTimeBedTime); + break; + + case kActionCallback: + if (getCallback() == 1 || getCallback() == 2) + setup_function34(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, August, function34) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getSound()->isBuffered(kEntityAugust) && getProgress().field_18 != 4) + getSound()->playSound(kEntityAugust, "AUG1057"); // August snoring + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityAugust); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, August, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAugust); + + getData()->entityPosition = kPosition_3970; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject11, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, August, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_SAVEPOINT(kTime1755000, params->param2, kEntityAugust, kEntityServers0, kAction252568704); + + if (getState()->time > kTime1773000 && params->param1 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->inventoryItem = kItemNone; + getData()->location = kLocationOutsideCompartment; + getEntities()->updatePositionEnter(kEntityAugust, kCarRestaurant, 62); + + setCallback(2); + setup_callSavepoint("016C", kEntityTables0, kActionDrawTablesWithChairs, "016D"); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAugustGoodMorning); + break; + + case kActionDefault: + if (!getEvent(kEventAugustGoodMorning)) + getData()->inventoryItem = kItemInvalid; + + getSavePoints()->push(kEntityAugust, kEntityTables0, kAction136455232); + getEntities()->drawSequenceLeft(kEntityAugust, "016B"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAugustGoodMorning); + getScenes()->loadSceneFromPosition(kCarRestaurant, 61); + break; + + case 2: + getEntities()->updatePositionExit(kEntityAugust, kCarRestaurant, 62); + getEntities()->drawSequenceRight(kEntityAugust, "803ES"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction286534136); + + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case 4: + setCallback(5); + setup_function19(true, false); + break; + + case 5: + setup_function37(); + break; + + case 6: + if (!getEvent(kEventAugustGoodMorning)) + getData()->inventoryItem = kItemInvalid; + + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction219522616); + getEntities()->drawSequenceLeft(kEntityAugust, "016B"); + params->param1 = 1; + break; + } + break; + + case kAction123712592: + getEntities()->drawSequenceLeft(kEntityAugust, "016A"); + getData()->inventoryItem = kItemNone; + + setCallback(6); + setup_playSound("AUG2113"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, August, function37) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_1(kTime1791000, params->param2, 5, setup_function20, true); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getEntities()->drawSequenceLeft(kEntityAugust, "506A2"); + break; + + case kActionDrawScene: + if (getState()->time > kTime1786500 && getEntities()->isPlayerPosition(kCarGreenSleeping, 43)) { + if (params->param1) { + setCallback(2); + setup_draw("506C2"); + } else { + params->param1 = 1; + + setCallback(1); + setup_draw("506B2"); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 16); + break; + + case 2: + setCallback(3); + setup_function20(true); + break; + + case 3: + case 5: + setCallback(getCallback() == 3 ? 4 : 6); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 4: + case 6: + setup_function38(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, August, function38) + error("August: callback function 38 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, August, function39) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (!ENTITY_PARAM(0, 1)) + getSound()->playSound(kEntityPlayer, "BUMP"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAugustArrivalInMunich); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAugustArrivalInMunich); + getSavePoints()->push(kEntityAugust, kEntityChapters, kActionChapter3); + getEntities()->clearSequences(kEntityAugust); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, August, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAugust); + + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(41, August, function41, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 && getEntities()->isDistanceBetweenEntities(kEntityAugust, kEntityPlayer, 2000)) + getData()->inventoryItem = kItemInvalid; + else + getData()->inventoryItem = kItemNone; + + if (getEntities()->updateEntity(kEntityAugust, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + + if (!getEvent(kEventAugustMerchandise) + && getEntities()->isDistanceBetweenEntities(kEntityAugust, kEntityPlayer, 1000) + && !getEntities()->isInsideCompartments(kEntityPlayer) + && !getEntities()->checkFields10(kEntityPlayer)) { + if (getData()->car == kCarGreenSleeping || getData()->car == kCarGreenSleeping) { + getAction()->playAnimation(kEventAugustMerchandise); + + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + } + } + break; + + case kAction1: + params->param3 = kItemNone; + getData()->inventoryItem = kItemNone; + + getAction()->playAnimation((getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition) ? kEventAugustTalkGoldDay : kEventAugustTalkGold); + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); + break; + + case kActionExcuseMeCath: + if (getProgress().eventMetAugust) + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1002" : "CAT1002A"); + else + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntityAugust); + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityAugust, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + + if (getEvent(kEventAugustMerchandise) && !getEvent(kEventAugustTalkGold) && !getEvent(kEventAugustTalkGoldDay)) + params->param3 = kItemInvalid; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_III(42, August, function42, CarIndex, EntityPosition, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param4 && getEntities()->isDistanceBetweenEntities(kEntityAugust, kEntityPlayer, 2000)) + getData()->inventoryItem = kItemInvalid; + else + getData()->inventoryItem = kItemNone; + + if (getEntities()->updateEntity(kEntityAugust, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + + CALLBACK_ACTION(); + } + break; + + case kAction1: + params->param4 = 0; + getData()->inventoryItem = kItemNone; + + getSound()->playSound(kEntityPlayer, "CAT1002"); + getSound()->playSound(kEntityAugust, getEvent(kEventAugustBringBriefcase) ? "AUG3103" : "AUG3100", SoundManager::kFlagInvalid, 15); + break; + + case kActionExcuseMe: + if (!getSound()->isBuffered(kEntityAugust)) + getSound()->excuseMe(kEntityAugust); + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityAugust, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + + if (params->param3) { + params->param4 = 128; + + if (!getEvent(kEventAugustBringBriefcase)) + params->param4 = 147; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, August, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_SAVEPOINT(kTime1953000, params->param2, kEntityAugust, kEntityAnna, kAction291662081); + + // Set as same position as Anna + if (params->param1) { + getData()->entityPosition = getEntityData(kEntityAnna)->entityPosition; + getData()->car = getEntityData(kEntityAnna)->car; + } + + if (getState()->time > kTime2016000 && !params->param1) { + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->inventoryItem = kItemNone; + setup_function44(); + } + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventAugustLunch); + break; + + case kActionDefault: + setCallback(1); + setup_function20(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function41(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("803VS"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityAugust, "010A2"); + + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(5); + setup_callSavepointNoDrawing(kEntityTables3, kAction136455232, "BOGUS"); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAugust, "010B2"); + + if (!getEvent(kEventAugustLunch)) + getData()->inventoryItem = kItemInvalid; + break; + + case 6: + getAction()->playAnimation(kEventAugustLunch); + getScenes()->processScene(); + break; + } + break; + + case kAction122288808: + params->param1 = 0; + getData()->inventoryItem = kItemNone; + getData()->location = kLocationInsideCompartment; + + getEntities()->drawSequenceLeft(kEntityAugust, "112G"); + break; + + case kAction122358304: + params->param1 = 1; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, August, function44) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updatePosition("122H", kCarRestaurant, 57); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEvent(kEventAugustMerchandise)) { + setCallback(4); + setup_function41(kCarGreenSleeping, kPosition_6470); + } else { + setCallback(2); + setup_function17(kTime2043000); + } + break; + + case 2: + if (!ENTITY_PARAM(0, 1)) { + setCallback(4); + setup_function41(kCarGreenSleeping, kPosition_6470); + } else { + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventAugustMerchandise); + } + break; + + case 3: + getAction()->playAnimation(kEventAugustMerchandise); + if (getData()->car == kCarGreenSleeping && getEntities()->checkDistanceFromPosition(kEntityAugust, kPosition_6470, 500)) + getData()->entityPosition = kPosition_5970; + + getEntities()->updateEntity(kEntityAugust, kCarGreenSleeping, kPosition_6470); + + getEntities()->loadSceneFromEntityPosition(getData()->car, + (EntityPosition)(getData()->entityPosition + 750 * (getData()->direction == kDirectionUp ? -1 : 1)), + getData()->direction == kDirectionUp); + + setCallback(4); + setup_function41(kCarGreenSleeping, kPosition_6470); + break; + + case 4: + setCallback(5); + setup_function19(true, false); + break; + + case 5: + setup_function45(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, August, function45) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2061000 && !params->param1) { + params->param1 = 1; + getData()->inventoryItem = kItemNone; + + setup_function46(); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + getSound()->playSound(kEntityPlayer, "CAT1002"); + getSound()->playSound(kEntityAugust, "AUG3102", SoundManager::kFlagInvalid, 15); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getEntities()->drawSequenceLeft(kEntityAugust, "506A2"); + getData()->inventoryItem = kItem146; // TODO which item is that? + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, August, function46) + switch (savepoint.action) { + default: + TIME_CHECK_CALLBACK(kTime2088000, params->param1, 1, setup_function47); + break; + + case kActionNone: + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 43)) { + setCallback(2); + setup_draw("507B2"); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setup_function48(); + break; + + case 2: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 43)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 34); + + getEntities()->clearSequences(kEntityAugust); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, August, function47) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function41(kCarGreenSleeping, kPosition_9460); + break; + + case 2: + getEntities()->clearSequences(kEntityAugust); + setCallback(3); + setup_updateFromTime(2700); + break; + + case 3: + setCallback(4); + setup_function41(kCarGreenSleeping, kPosition_6470); + break; + + case 4: + setCallback(5); + setup_function19(false, false); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, August, function48) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTimeCityLinz, params->param1, setup_function49); + break; + + case kActionKnock: + case kActionOpenDoor: + if (!getEvent(kEventAugustTalkCompartmentDoor) && !getEvent(kEventAugustTalkCompartmentDoorBlueRedingote) + && !getEvent(kEventAugustBringEgg) && !getEvent(kEventAugustBringBriefcase)) { + + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAugustTalkCompartmentDoor); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityAugust, kObjectLocation1, kCursorHandKnock, kCursorHand); + getData()->clothes = kClothes2; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventAugustTalkCompartmentDoor); + getScenes()->processScene(); + + setCallback(2); + setup_function21(kTimeCityLinz); + break; + + case 2: + setup_function49(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(49, August, function49) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(false); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarKronos, kPosition_9270); + break; + + case 2: + setup_function50(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(50, August, function50) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->clearSequences(kEntityAugust); + + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarKronos; + break; + + case kAction191668032: + setup_function51(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(51, August, function51) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_850; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_function42(kCarGreenSleeping, kPosition_5790, false); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityAugust, kEntityTatiana, kAction191668032); + + setCallback(2); + setup_function42(kCarRedSleeping, kPosition_540, true); + break; + + case 2: + getEntities()->clearSequences(kEntityAugust); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + getSavePoints()->push(kEntityAugust, kEntityAnna, kAction123712592); + break; + } + break; + + case kAction122288808: + setup_function52(); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + break; + + case kAction169032608: + setCallback(3); + setup_function42(kCarRedSleeping, kPosition_3820, true); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(52, August, function52) + switch (savepoint.action) { + default: + break; + + case kActionKnock: + case kActionOpenDoor: + if (getInventory()->hasItem(kItemBriefcase)) { + getData()->location = kLocationInsideCompartment; + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventAugustBringBriefcase); + break; + } + + if (getInventory()->hasItem(kItemFirebird) && !getEvent(kEventAugustBringEgg)) { + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventAugustBringEgg); + break; + } + + if (!getEvent(kEventAugustTalkCompartmentDoorBlueRedingote) && !getEvent(kEventAugustBringEgg) && !getEvent(kEventAugustBringBriefcase)) { + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventAugustBringEgg); + break; + } + + getObjects()->update(kObjectCompartment3, kEntityAugust, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 6 : 7); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + setCallback(1); + setup_function42(kCarGreenSleeping, kPosition_6470, true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function19(false, true); + break; + + case 2: + getObjects()->update(kObjectCompartment3, kEntityAugust, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getSavePoints()->push(kEntityAugust, kEntityKahina, kAction134611040); + break; + + case 3: + getAction()->playAnimation(kEventAugustBringBriefcase); + getSound()->playSound(kEntityPlayer, "LIB015"); + RESET_ENTITY_STATE(kEntitySalko, Salko, setup_function17); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 13); + + setup_function53(); + break; + + case 4: + getAction()->playAnimation(kEventAugustBringEgg); + getScenes()->processScene(); + break; + + case 5: + getAction()->playAnimation(kEventAugustTalkCompartmentDoorBlueRedingote); + getScenes()->processScene(); + break; + + case 6: + case 7: + setCallback(8); + setup_playSound("AUG1128F"); + break; + + case 8: + getObjects()->update(kObjectCompartment3, kEntityAugust, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(53, August, function53) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateFromTime(2700); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function20(false); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setup_function54(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(54, August, function54) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param4 || params->param2 || getProgress().field_44) + getData()->inventoryItem = kItemNone; + else + getData()->inventoryItem = kItemInvalid; + + if (!params->param2 && params->param1) { + UPDATE_PARAM(params->param5, getState()->time, params->param1); + + getData()->inventoryItem = kItemNone; + setup_function55(); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventAugustTalkCigar); + break; + + case kActionExitCompartment: + getEntities()->updatePositionExit(kEntityAugust, kCarRestaurant, 57); + getEntities()->drawSequenceLeft(kEntityAugust, "105B3"); + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionDrawScene: + if (!getEntities()->isPlayerPosition(kCarRestaurant, 60) || params->param3) { + if (!params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 57)) + getScenes()->loadSceneFromPosition(kCarRestaurant, 50); + } else if (!params->param2) { + getEntities()->updatePositionEnter(kEntityAugust, kCarRestaurant, 57); + getEntities()->drawSequenceRight(kEntityAugust, "105C3"); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updatePosition("105A3", kCarRestaurant, 57); + break; + + case 2: + getData()->location = kLocationInsideCompartment; + getSavePoints()->push(kEntityAugust, kEntityAbbot, kAction123712592); + getEntities()->drawSequenceLeft(kEntityAugust, "105B3"); + params->param4 = 1; + break; + + case 3: + getAction()->playAnimation(kEventAugustTalkCigar); + getEntities()->drawSequenceLeft(kEntityAugust, params->param3 ? "122B" : "105B3"); + getScenes()->processScene(); + + params->param1 = 9000; + params->param4 = 0; + break; + } + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityAugust, "122B"); + params->param2 = 0; + + if (getEvent(kEventAugustTalkCigar)) + params->param1 = 9000; + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + params->param2 = 1; + params->param3 = 1; + break; + + case kAction136196244: + params->param2 = 1; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(55, August, function55) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updatePosition("105D3", kCarRestaurant, 57); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case 3: + setCallback(4); + setup_function19(true, false); + break; + + case 4: + setup_function56(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(56, August, function56) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getEntities()->drawSequenceLeft(kEntityAugust, "507A3"); + break; + + case kActionDrawScene: + if (!params->param1 && getEntities()->isPlayerPosition(kCarGreenSleeping, 43)) { + setCallback(1); + setup_draw("507B3"); + } + break; + + case kActionCallback: + if (getCallback() == 1) { + params->param1 = 1; + getEntities()->drawSequenceLeft(kEntityAugust, "507A3"); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(57, August, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAugust); + + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothes2; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(58, August, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(false); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("803WS"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityAugust, "010A3"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(5); + setup_callSavepointNoDrawing(kEntityTables3, kAction136455232, "BOGUS"); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + setup_function59(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(59, August, function59) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAugust, "010B3"); + getSavePoints()->push(kEntityAugust, kEntityPascale, kAction190605184); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + break; + + case kAction123793792: + setup_function60(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(60, August, function60) + switch (savepoint.action) { + default: + break; + + case kActionNone: { + bool pushSavepoint = false; + if (!params->param2) { + pushSavepoint = true; + params->param2 = getState()->time + 450; + } + + if (params->param2 < getState()->time) { + pushSavepoint = true; + params->param2 = kTimeInvalid; + } + + if (pushSavepoint) + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction207330561); + + if (!params->param1) + break; + + UPDATE_PARAM(params->param3, getState()->time, 9000); + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAugust, "010B3"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_callSavepoint("010J3", kEntityTables3, kActionDrawTablesWithChairs, "010M"); + break; + + case 2: + getSavePoints()->push(kEntityAugust, kEntityServers0, kAction286403504); + setup_function61(); + break; + } + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityAugust, "010B3"); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + break; + + case kAction201964801: + getEntities()->drawSequenceLeft(kEntityAugust, "010H3"); + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(61, August, function61) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + getEntities()->drawSequenceRight(kEntityAugust, "803FS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityAugust); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case 2: + setCallback(3); + setup_function19(false, false); + break; + + case 3: + setCallback(4); + setup_function21((TimeValue)(getState()->time + 4500)); + break; + + case 4: + setup_function62(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(62, August, function62) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->time, 900); + + getSound()->playSound(kEntityAugust, "Aug4003A"); + + setCallback(5); + setup_updatePosition("122C", kCarRestaurant, 57); + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_enterExitCompartment("696Ec", kObjectCompartment3); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRestaurant, 57)) + getScenes()->loadSceneFromPosition(kCarRestaurant, 50); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_updatePosition("122A", kCarRestaurant, 57); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAugust, "122B"); + break; + + case 5: + getEntities()->drawSequenceLeft(kEntityAugust, "122B"); + getSavePoints()->push(kEntityAugust, kEntityServers1, kAction291721418); + break; + } + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + break; + + case kAction125826561: + setup_function63(); + break; + + case kAction134486752: + getEntities()->drawSequenceLeft(kEntityAugust, "122B"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(63, August, function63) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(params->param3, getState()->time, 1800) + getData()->inventoryItem = kItemInvalid; + UPDATE_PARAM_PROC_END + + if (getState()->time > kTime2488500 && !params->param4) { + params->param4 = 1; + getData()->inventoryItem = kItemNone; + setup_function64(); + break; + } + + UPDATE_PARAM(params->param5, getState()->timeTicks, params->param1); + + params->param2 = (params->param6 < 1 ? 1 : 0); + + getEntities()->drawSequenceLeft(kEntityAugust, params->param2 ? "122H" : "122F"); + + params->param1 = 5 * (3 * rnd(20) + 15); + params->param5 = 0; + break; + + case kAction1: + if (getEntities()->isInSalon(kEntityAlexei)) + RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_function44); + + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAugustDrink); + break; + + case kActionDefault: + params->param1 = 5 * (3 * rnd(20) + 15); + getEntities()->drawSequenceLeft(kEntityAugust, "122F"); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRestaurant, 57)) + getScenes()->loadSceneFromPosition(kCarRestaurant, 50); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventAugustDrink); + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + + setup_function64(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(64, August, function64) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) + params->param1 = getState()->time + 1800; + + if (params->param1 >= getState()->time) + break; + + if (getState()->time > kTime2430000 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updatePosition("122J", kCarRestaurant, 57); + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityAugust, "122H"); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRestaurant, 57)) + getScenes()->loadSceneFromPosition(kCarRestaurant, 50); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment2("696Dc", kObjectCompartment3); + break; + + case 3: + getEntities()->clearSequences(kEntityAugust); + setup_function65(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(65, August, function65) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + getSound()->playSound(kEntityAugust, "AUG1057"); // August snoring + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityAugust); + + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + if (!getSound()->isBuffered(kEntityAugust)) + getSound()->playSound(kEntityAugust, "AUG1057"); // August snoring + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(66, August, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityAugust); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes2; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(67, August, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function68(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(68, August, function68) + error("August: callback function 68 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(69, August, unhookCars) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getSavePoints()->pushAll(kEntityAugust, kAction135800432); + setup_nullfunction(); + break; + + case kActionDefault: + getSound()->processEntries(); + if (getSound()->isBuffered("ARRIVE")) + getSound()->removeFromQueue("ARRIVE"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAugustUnhookCarsBetrayal); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(getProgress().field_C ? kEventAugustUnhookCarsBetrayal : kEventAugustUnhookCars); + getEntities()->clearSequences(kEntityAugust); + getSound()->resetState(); + getSound()->playSound(kEntityPlayer, "MUS050"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 85, 1); + getSavePoints()->pushAll(kEntityAugust, kActionProceedChapter5); + + RESET_ENTITY_STATE(kEntityVerges, Verges, setup_function42) + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(70, August) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/august.h b/engines/lastexpress/entities/august.h new file mode 100644 index 0000000000..e684fc0361 --- /dev/null +++ b/engines/lastexpress/entities/august.h @@ -0,0 +1,275 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_AUGUST_H +#define LASTEXPRESS_AUGUST_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class August : public Entity { +public: + August(LastExpressEngine *engine); + ~August() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment3, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Call a savepoint + * + * @param param1 The entity + * @param param2 The action + * @param seq The sequence name for the savepoint + */ + DECLARE_FUNCTION_3(callSavepointNoDrawing, EntityIndex entity, ActionIndex action, const char* sequence) + + /** + * Draws the entity along with another one + * + * @param sequence1 The sequence to draw + * @param sequence2 The sequence to draw for the second entity + * @param entity The EntityIndex of the second entity + */ + DECLARE_FUNCTION_3(draw2, const char* sequence1, const char* sequence2, EntityIndex entity) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound16, const char* filename) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_1(function17, TimeValue timeValue) + + /** + * Updates the entity + * + * @param param1 The car + * @param param2 The entity position + */ + DECLARE_FUNCTION_2(updateEntity2, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_2(function19, bool, bool) + + DECLARE_FUNCTION_1(function20, bool) + DECLARE_FUNCTION_1(function21, TimeValue timeValue) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION_1(function23, TimeValue timeValue) + DECLARE_FUNCTION(dinner) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + DECLARE_FUNCTION(restaurant) + DECLARE_FUNCTION(function31) + DECLARE_FUNCTION(function32) + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + DECLARE_FUNCTION(function39) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + DECLARE_FUNCTION_2(function41, CarIndex car, EntityPosition entityPosition) + DECLARE_FUNCTION_3(function42, CarIndex car, EntityPosition entityPosition, bool) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function44) + DECLARE_FUNCTION(function45) + DECLARE_FUNCTION(function46) + DECLARE_FUNCTION(function47) + DECLARE_FUNCTION(function48) + DECLARE_FUNCTION(function49) + DECLARE_FUNCTION(function50) + DECLARE_FUNCTION(function51) + DECLARE_FUNCTION(function52) + DECLARE_FUNCTION(function53) + DECLARE_FUNCTION(function54) + DECLARE_FUNCTION(function55) + DECLARE_FUNCTION(function56) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function59) + DECLARE_FUNCTION(function60) + DECLARE_FUNCTION(function61) + DECLARE_FUNCTION(function62) + DECLARE_FUNCTION(function63) + DECLARE_FUNCTION(function64) + DECLARE_FUNCTION(function65) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function68) + DECLARE_FUNCTION(unhookCars) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_AUGUST_H diff --git a/engines/lastexpress/entities/boutarel.cpp b/engines/lastexpress/entities/boutarel.cpp new file mode 100644 index 0000000000..411456c5c8 --- /dev/null +++ b/engines/lastexpress/entities/boutarel.cpp @@ -0,0 +1,1260 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/boutarel.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Boutarel::Boutarel(LastExpressEngine *engine) : Entity(engine, kEntityBoutarel) { + ADD_CALLBACK_FUNCTION(Boutarel, reset); + ADD_CALLBACK_FUNCTION(Boutarel, playSound); + ADD_CALLBACK_FUNCTION(Boutarel, draw); + ADD_CALLBACK_FUNCTION(Boutarel, updateFromTime); + ADD_CALLBACK_FUNCTION(Boutarel, updatePosition); + ADD_CALLBACK_FUNCTION(Boutarel, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Boutarel, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Boutarel, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Boutarel, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Boutarel, updateEntity); + ADD_CALLBACK_FUNCTION(Boutarel, function11); + ADD_CALLBACK_FUNCTION(Boutarel, enterTableWithMmeBoutarel); + ADD_CALLBACK_FUNCTION(Boutarel, leaveTableWithMmeBoutarel); + ADD_CALLBACK_FUNCTION(Boutarel, function14); + ADD_CALLBACK_FUNCTION(Boutarel, function15); + ADD_CALLBACK_FUNCTION(Boutarel, function16); + ADD_CALLBACK_FUNCTION(Boutarel, function17); + ADD_CALLBACK_FUNCTION(Boutarel, function18); + ADD_CALLBACK_FUNCTION(Boutarel, chapter1); + ADD_CALLBACK_FUNCTION(Boutarel, function20); + ADD_CALLBACK_FUNCTION(Boutarel, chapter1Handler); + ADD_CALLBACK_FUNCTION(Boutarel, function22); + ADD_CALLBACK_FUNCTION(Boutarel, chapter2); + ADD_CALLBACK_FUNCTION(Boutarel, chapter2Handler); + ADD_CALLBACK_FUNCTION(Boutarel, function25); + ADD_CALLBACK_FUNCTION(Boutarel, chapter3); + ADD_CALLBACK_FUNCTION(Boutarel, chapter3Handler); + ADD_CALLBACK_FUNCTION(Boutarel, function28); + ADD_CALLBACK_FUNCTION(Boutarel, function29); + ADD_CALLBACK_FUNCTION(Boutarel, function30); + ADD_CALLBACK_FUNCTION(Boutarel, chapter4); + ADD_CALLBACK_FUNCTION(Boutarel, chapter4Handler); + ADD_CALLBACK_FUNCTION(Boutarel, function33); + ADD_CALLBACK_FUNCTION(Boutarel, function34); + ADD_CALLBACK_FUNCTION(Boutarel, function35); + ADD_CALLBACK_FUNCTION(Boutarel, chapter5); + ADD_CALLBACK_FUNCTION(Boutarel, chapter5Handler); + ADD_CALLBACK_FUNCTION(Boutarel, function38); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Boutarel, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Boutarel, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Boutarel, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(4, Boutarel, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(5, Boutarel, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(6, Boutarel, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(7, Boutarel, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_6470, kPosition_6130, kCarRedSleeping, kObjectCompartmentC, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Boutarel, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Boutarel, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Boutarel, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + + if (getInventory()->hasItem(kItemPassengerList) && getState()->time > kTime1089000) + getSound()->playSound(kEntityPlayer, "CAT1022"); + else + getSound()->excuseMeCath(); + + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(11, Boutarel, function11, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(0, 1) && ENTITY_PARAM(0, 2)) { + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 1) = 0; + + setCallback(5); + setup_callbackActionRestaurantOrSalon(); + } + break; + + case kActionDefault: + if (params->param1) { + if (getProgress().chapter == kChapter4) { + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_enterExitCompartment("607Hc", kObjectCompartmentC); + } else { + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(2); + setup_enterExitCompartment("607Dc", kObjectCompartmentC); + } + } else { + setCallback(3); + setup_enterExitCompartment("607Bc", kObjectCompartmentC); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 2: + case 3: + if (getCallback() == 2) + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + else + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + // Fallback to next case + + case 1: + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityBoutarel, kEntityFrancois, kAction101107728); + + setCallback(4); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 4: + getEntities()->clearSequences(kEntityBoutarel); + break; + + case 5: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(6); + setup_draw("812US"); + break; + + case 6: + switch (getProgress().chapter) { + default: + break; + + case kChapter1: + getSound()->playSound(kEntityBoutarel, "MRB1075", SoundManager::kFlagInvalid, 60); + break; + + case kChapter3: + getSound()->playSound(kEntityBoutarel, "MRB3101"); + break; + } + + setCallback(7); + setup_enterTableWithMmeBoutarel(); + break; + + case 7: + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Boutarel, enterTableWithMmeBoutarel) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->clearSequences(kEntityMmeBoutarel); + getSavePoints()->push(kEntityBoutarel, kEntityTables2, kAction136455232); + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityTables2, "008A3"); + getEntities()->drawSequenceRight(kEntityMmeBoutarel, "008A2"); + getEntities()->drawSequenceRight(kEntityBoutarel, "008A1"); + + if (getEntities()->isInSalon(kEntityPlayer)) { + getEntities()->updateFrame(kEntityBoutarel); + getEntityData(kEntityMmeBoutarel)->location = getData()->location; + getEntityData(kEntityTables2)->location = getData()->location; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Boutarel, leaveTableWithMmeBoutarel) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getSavePoints()->push(kEntityBoutarel, kEntityTables2, kActionDrawTablesWithChairs, "008F"); + getEntities()->clearSequences(kEntityMmeBoutarel); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityTables2, "008E3"); + getEntities()->drawSequenceRight(kEntityMmeBoutarel, "008E2"); + getEntities()->drawSequenceRight(kEntityBoutarel, "008E1"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(14, Boutarel, function14, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getSound()->playSound(kEntityBoutarel, "MRB1079"); + + setCallback(2); + setup_leaveTableWithMmeBoutarel(); + break; + + case 2: + getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction326144276); + getEntities()->drawSequenceRight(kEntityBoutarel, "812DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityBoutarel); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + getEntityData(kEntityFrancois)->entityPosition = kPosition_540; + getEntityData(kEntityMmeBoutarel)->entityPosition = kPosition_540; + getData()->entityPosition = kPosition_540; + + getEntityData(kEntityFrancois)->location = kLocationOutsideCompartment; + getEntityData(kEntityMmeBoutarel)->location = kLocationOutsideCompartment; + + getEntities()->clearSequences(kEntityBoutarel); + getSavePoints()->push(kEntityBoutarel, kEntityMmeBoutarel, kAction100901266); + + setCallback(4); + setup_updateFromTime(450); + break; + + case 4: + getSavePoints()->push(kEntityBoutarel, kEntityFrancois, kAction100901266); + + setCallback(5); + setup_updateFromTime(450); + break; + + case 5: + setCallback(6); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 6: + setCallback(params->param1 ? 7: 8); + setup_enterExitCompartment2(params->param1 ? "607Gc" : "607Ac", kObjectCompartmentC); + break; + + case 7: + case 8: + getEntities()->clearSequences(kEntityBoutarel); + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IS(15, Boutarel, function15, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (params->param1) + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(params->param1 ? 1 : 2); + setup_enterExitCompartment(params->param1 ? "607Dc" : "607Bc", kObjectCompartmentC); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(3); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_updatePosition(params->seq, kCarRestaurant, 52); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// Parameters: +// bool +// const char * +IMPLEMENT_FUNCTION_IS(16, Boutarel, function16, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updatePosition((const char *)¶ms->seq, kCarRestaurant, 52); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 3: + setCallback(params->param1 ? 4 : 5); + setup_enterExitCompartment2(params->param1 ? "607Gc" : "607Ac", kObjectCompartmentC); + break; + + case 4: + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityBoutarel); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IS(17, Boutarel, function17, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_ACTION(params->param1, params->param6); + + if (params->param5) { + UPDATE_PARAM(params->param7, getState()->timeTicks, 90) + getScenes()->loadSceneFromPosition(kCarRestaurant, 51); + } else { + params->param7 = 0; + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityBoutarel, (char *)¶ms->seq); + break; + + case kActionDrawScene: + params->param5 = (getEntities()->isPlayerPosition(kCarRestaurant, 52) ? 1 : 0); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(18, Boutarel, function18, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 < getState()->time && !params->param4) { + params->param4 = 1; + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + + if (params->param2) { + UPDATE_PARAM(params->param5, getState()->timeTicks, 75); + + params->param2 = 0; + params->param3 = 1; + + getObjects()->update(kObjectCompartmentC, kEntityBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param5 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentC, kEntityBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (params->param2) { + if (savepoint.param.intValue == 50) { + setCallback(4); + setup_playSound(getSound()->justAMinuteCath()); + } else if (getInventory()->hasItem(kItemPassengerList)) { + setCallback(5); + setup_playSound(rnd(2) ? "CAT1511" : getSound()->wrongDoorCath()); + } else { + setCallback(6); + setup_playSound(getSound()->wrongDoorCath()); + } + } else { + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentC, kEntityBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param3 || params->param2) { + getObjects()->update(kObjectCompartmentC, kEntityBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param2 = 0; + params->param3 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound(rnd(2) ? "MRB1001" : "MRB1001A"); + break; + + case 3: + getObjects()->update(kObjectCompartmentC, kEntityBoutarel, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObject50, kEntityBoutarel, kObjectLocation1, kCursorTalk, kCursorNormal); + + params->param2 = 1; + break; + + case 4: + case 5: + case 6: + params->param2 = 0; + params->param3 = 1; + break; + + case 7: + getSavePoints()->push(kEntityBoutarel, kEntityCoudert, kAction123199584); + break; + + } + break; + + case kAction122865568: + getSavePoints()->push(kEntityBoutarel, kEntityCoudert, kAction88652208); + break; + + case kAction221683008: + setCallback(7); + setup_playSound("MRB1001"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Boutarel, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityBoutarel, kAction203520448, 0); + getSavePoints()->addData(kEntityBoutarel, kAction237889408, 1); + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject42, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_1750; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Boutarel, function20) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) + break; + + if (!params->param2) { + UPDATE_PARAM_PROC(params->param3, getState()->time, 4500) + setCallback(3); + setup_playSound("MRB1078A"); + break; + UPDATE_PARAM_PROC_END + } + + TIME_CHECK_CALLBACK_1(kTime1138500, params->param4, 4, setup_function14, false); + break; + + case kActionDefault: + setCallback(1); + setup_function11(false); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityBoutarel, "008B"); + + setCallback(2); + setup_playSound("MRB1076"); + break; + + case 2: + getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction256200848); + break; + + case 3: + TIME_CHECK_CALLBACK_1(kTime1138500, params->param4, 4, setup_function14, false); + break; + + case 4: + getSavePoints()->push(kEntityBoutarel, kEntityCooks, kAction224849280); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction134466544: + params->param2 = 0; + break; + + case kAction135854206: + params->param2 = 1; + break; + + case kAction168717392: + params->param1 = 1; + getEntities()->drawSequenceLeft(kEntityBoutarel, "008D"); + + if (!params->param2) { + setCallback(5); + setup_playSound("MRB1078"); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Boutarel, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function17(kTime1071000, "101A"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function16(false, "101B"); + break; + + case 2: + setCallback(3); + setup_function18(kTime1102500); + break; + + case 3: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 54) || getEntities()->isPlayerPosition(kCarRedSleeping, 44)) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 10); + + getEntities()->updatePositionExit(kEntityBoutarel, kCarRedSleeping, 54); + getEntities()->updatePositionExit(kEntityBoutarel, kCarRedSleeping, 44); + + setCallback(4); + setup_playSound("MRB1074"); + break; + + case 4: + getEntities()->updatePositionExit(kEntityBoutarel, kCarRedSleeping, 54); + getEntities()->updatePositionExit(kEntityBoutarel, kCarRedSleeping, 44); + + setCallback(5); + setup_function20(); + break; + + case 5: + setCallback(6); + setup_function18(kTimeEnterChalons); + break; + + case 6: + setCallback(7); + setup_function15(false, "102A"); + break; + + case 7: + setCallback(8); + setup_function17(kTime1183500, "102B"); + break; + + case 8: + setCallback(9); + setup_function16(false, "102C"); + break; + + case 9: + setCallback(10); + setup_function18(kTime1215000); + break; + + case 10: + setup_function22(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Boutarel, function22) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getEntities()->clearSequences(kEntityBoutarel); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Boutarel, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityBoutarel); + + getData()->entityPosition = kPosition_4689; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Boutarel, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_1(kTime1759500, params->param2, 1, setup_function14, false); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityBoutarel, "008D"); + break; + + case kActionDrawScene: + if (getEntities()->isInRestaurant(kEntityPlayer) && !params->param1) { + getSound()->playSound(kEntityBoutarel, "MRB2001"); + params->param1 = 1; + } + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function25(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Boutarel, function25) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getEntities()->drawSequenceLeft(kEntityBoutarel, "510"); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Boutarel, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityBoutarel); + + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Boutarel, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getEntities()->drawSequenceLeft(kEntityBoutarel, "510"); + break; + + case kAction122288808: + setup_function28(); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityBoutarel, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Boutarel, function28) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function11(true); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function29(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Boutarel, function29) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(params->param2, getState()->time, 450) + getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction256200848); + UPDATE_PARAM_PROC_END + + if (!params->param1) + break; + + if (getEntities()->isInRestaurant(kEntityAnna) + && getEntities()->isInRestaurant(kEntityAugust) + && !getSound()->isBuffered(kEntityBoutarel) + && params->param3 != kTimeInvalid) { + + if (getState()->time <= kTime1998000) + if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param3) + params->param3 = getState()->time + 450; + + if (params->param3 < getState()->time || getState()->time > kTime1998000) { + params->param3 = kTimeInvalid; + + setCallback(1); + setup_playSound("MRB3102"); + break; + } + } + + TIME_CHECK_CALLBACK_1(kTime2002500, params->param4, 1, setup_function14, true); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityBoutarel, "008B"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + TIME_CHECK_CALLBACK_1(kTime2002500, params->param4, 1, setup_function14, true); + break; + + case 2: + setup_function30(); + break; + } + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityBoutarel, "008D"); + params->param1 = 1; + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityBoutarel, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Boutarel, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getEntities()->drawSequenceLeft(kEntityBoutarel, "510"); + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityBoutarel, "510"); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityBoutarel, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Boutarel, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityBoutarel); + + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Boutarel, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime2367000, params->param1, setup_function33); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getEntities()->drawSequenceLeft(kEntityBoutarel, "510"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Boutarel, function33) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) + TIME_CHECK_CALLBACK_1(kTime2389500, params->param2, 3, setup_function14, false); + break; + + case kActionDefault: + setCallback(1); + setup_function11(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityBoutarel, "008B"); + + setCallback(2); + setup_updateFromTime(450); + break; + + case 2: + getSavePoints()->push(kEntityBoutarel, kEntityServers1, kAction256200848); + break; + + case 3: + setup_function34(); + break; + } + break; + + case kAction122288808: + params->param1 = 1; + getEntities()->drawSequenceLeft(kEntityBoutarel, "008D"); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityBoutarel, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Boutarel, function34) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime2470500, params->param1, setup_function35); + + if (getState()->time > kTime2457000 && getEvent(kEventAugustDrink)) { + getSavePoints()->push(kEntityBoutarel, kEntityAbbot, kAction159003408); + + setCallback(1); + setup_function15(false, "102A"); + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityBoutarel, kEntityAbbot, kAction101687594); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function17(kTime2479500, "102B"); + break; + + case 2: + setCallback(3); + setup_function16(false, "102C"); + break; + + case 3: + case 7: + setup_function35(); + break; + + case 4: + case 8: + if (getState()->time >= kTime2470500) { + setup_function35(); + break; + } + + if (getEvent(kEventAugustDrink)) { + setCallback(5); + setup_function15(false, "102A"); + } else { + setCallback(8); + setup_function18((TimeValue)(getState()->time + 900)); + } + break; + + case 5: + setCallback(6); + setup_function17(kTime2479500, "102B"); + break; + + case 6: + setCallback(7); + setup_function16(false, "102C"); + break; + + case 9: + getSavePoints()->push(kEntityBoutarel, kEntityCoudert, kAction123199584); + break; + } + break; + + case kAction122865568: + getSavePoints()->push(kEntityBoutarel, kEntityCoudert, kAction88652208); + break; + + case kAction125039808: + setCallback(4); + setup_function18(kTime2457000); + break; + + case kAction221683008: + setCallback(9); + setup_playSound("Mrb1001"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Boutarel, function35) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityBoutarel); + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Boutarel, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityBoutarel); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Boutarel, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function38(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Boutarel, function38) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + + case kAction135800432: + setup_nullfunction(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(39, Boutarel) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/boutarel.h b/engines/lastexpress/entities/boutarel.h new file mode 100644 index 0000000000..22f8e62b62 --- /dev/null +++ b/engines/lastexpress/entities/boutarel.h @@ -0,0 +1,188 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_BOUTAREL_H +#define LASTEXPRESS_BOUTAREL_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Boutarel : public Entity { +public: + Boutarel(LastExpressEngine *engine); + ~Boutarel() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_1(function11, bool) + DECLARE_FUNCTION(enterTableWithMmeBoutarel) + DECLARE_FUNCTION(leaveTableWithMmeBoutarel) + DECLARE_FUNCTION_1(function14, bool) + DECLARE_FUNCTION_2(function15, bool, const char *sequence) + DECLARE_FUNCTION_2(function16, bool, const char *sequence) + DECLARE_FUNCTION_2(function17, TimeValue timeValue, const char *sequence) + DECLARE_FUNCTION_1(function18, TimeValue timeValue) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + DECLARE_FUNCTION(function20) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function22) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function25) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + DECLARE_FUNCTION(function30) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function38) + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_BOUTAREL_H diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp new file mode 100644 index 0000000000..1bf3ee3f71 --- /dev/null +++ b/engines/lastexpress/entities/chapters.cpp @@ -0,0 +1,1810 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/chapters.h" + +#include "lastexpress/entities/abbot.h" +#include "lastexpress/entities/alexei.h" +#include "lastexpress/entities/alouan.h" +#include "lastexpress/entities/anna.h" +#include "lastexpress/entities/august.h" +#include "lastexpress/entities/boutarel.h" +#include "lastexpress/entities/coudert.h" +#include "lastexpress/entities/cooks.h" +#include "lastexpress/entities/francois.h" +#include "lastexpress/entities/gendarmes.h" +#include "lastexpress/entities/hadija.h" +#include "lastexpress/entities/ivo.h" +#include "lastexpress/entities/kahina.h" +#include "lastexpress/entities/kronos.h" +#include "lastexpress/entities/mahmud.h" +#include "lastexpress/entities/max.h" +#include "lastexpress/entities/mertens.h" +#include "lastexpress/entities/milos.h" +#include "lastexpress/entities/mmeboutarel.h" +#include "lastexpress/entities/pascale.h" +#include "lastexpress/entities/rebecca.h" +#include "lastexpress/entities/salko.h" +#include "lastexpress/entities/servers0.h" +#include "lastexpress/entities/servers1.h" +#include "lastexpress/entities/sophie.h" +#include "lastexpress/entities/tatiana.h" +#include "lastexpress/entities/vassili.h" +#include "lastexpress/entities/verges.h" +#include "lastexpress/entities/vesna.h" +#include "lastexpress/entities/yasmin.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/menu.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +Chapters::Chapters(LastExpressEngine *engine) : Entity(engine, kEntityChapters) { + ADD_CALLBACK_FUNCTION(Chapters, savegame); + ADD_CALLBACK_FUNCTION(Chapters, enterStation); + ADD_CALLBACK_FUNCTION(Chapters, exitStation); + ADD_CALLBACK_FUNCTION(Chapters, chapter1); + ADD_CALLBACK_FUNCTION(Chapters, resetMainEntities); + ADD_CALLBACK_FUNCTION(Chapters, chapter1End); + ADD_CALLBACK_FUNCTION(Chapters, chapter1Init); + ADD_CALLBACK_FUNCTION(Chapters, chapter1Handler); + ADD_CALLBACK_FUNCTION(Chapters, chapter1Next); + ADD_CALLBACK_FUNCTION(Chapters, chapter2); + ADD_CALLBACK_FUNCTION(Chapters, chapter2Init); + ADD_CALLBACK_FUNCTION(Chapters, chapter2Handler); + ADD_CALLBACK_FUNCTION(Chapters, chapter3); + ADD_CALLBACK_FUNCTION(Chapters, chapter3Init); + ADD_CALLBACK_FUNCTION(Chapters, chapter3Handler); + ADD_CALLBACK_FUNCTION(Chapters, viennaEvents); + ADD_CALLBACK_FUNCTION(Chapters, chapter4); + ADD_CALLBACK_FUNCTION(Chapters, chapter4Init); + ADD_CALLBACK_FUNCTION(Chapters, chapter4Handler); + ADD_CALLBACK_FUNCTION(Chapters, chapter5); + ADD_CALLBACK_FUNCTION(Chapters, chapter4Init); + ADD_CALLBACK_FUNCTION(Chapters, chapter4Handler); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(1, Chapters, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(2, Chapters, enterStation, CityIndex) + enterExitStation(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Chapters, exitStation) + enterExitStation(savepoint, false); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Chapters, chapter1) + if (savepoint.action == kActionDefault) { + getSavePoints()->addData(kEntityChapters, kAction171843264, 0); + setup_chapter1Init(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Chapters, resetMainEntities) + if (savepoint.action != kActionDefault) + return; + + RESET_ENTITY_STATE(kEntityAbbot, Abbot, setup_reset); + RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_reset); + RESET_ENTITY_STATE(kEntityAlouan, Alouan, setup_reset); + RESET_ENTITY_STATE(kEntityAnna, Anna, setup_reset); + RESET_ENTITY_STATE(kEntityAugust, August, setup_reset); + RESET_ENTITY_STATE(kEntityMertens, Mertens, setup_reset); + RESET_ENTITY_STATE(kEntityCoudert, Coudert, setup_reset); + RESET_ENTITY_STATE(kEntityFrancois, Francois, setup_reset); + RESET_ENTITY_STATE(kEntityHadija, Hadija, setup_reset); + RESET_ENTITY_STATE(kEntityIvo, Ivo, setup_reset); + RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_reset); + RESET_ENTITY_STATE(kEntityMmeBoutarel, MmeBoutarel, setup_reset); + RESET_ENTITY_STATE(kEntityMahmud, Mahmud, setup_reset); + RESET_ENTITY_STATE(kEntityMax, Max, setup_reset); + RESET_ENTITY_STATE(kEntityMilos, Milos, setup_reset); + RESET_ENTITY_STATE(kEntityBoutarel, Boutarel, setup_reset); + RESET_ENTITY_STATE(kEntityGendarmes, Gendarmes, setup_reset); + RESET_ENTITY_STATE(kEntityRebecca, Rebecca, setup_reset); + RESET_ENTITY_STATE(kEntitySalko, Salko, setup_reset); + RESET_ENTITY_STATE(kEntitySophie, Sophie, setup_reset); + RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_reset); + RESET_ENTITY_STATE(kEntityVerges, Verges, setup_reset); + RESET_ENTITY_STATE(kEntityVassili, Vassili, setup_reset); + RESET_ENTITY_STATE(kEntityVesna, Vesna, setup_reset); + RESET_ENTITY_STATE(kEntityYasmin, Yasmin, setup_reset); + + CALLBACK_ACTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6,Chapters, chapter1End) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + getSound()->playSound(kEntityChapters, "MUS0009", SoundManager::kFlagDefault); + break; + + case kActionKnock: + if (!getSound()->isBuffered("LIB012", true)) + getSound()->playSound(kEntityPlayer, "LIB012"); + break; + + case kActionOpenDoor: + if (params->param1) { + getEntities()->clearSequences(kEntityChapters); + getSound()->processEntry(kEntityChapters); + getSound()->playSound(kEntityPlayer, "LIB014"); + getSound()->resetState(); + + ENTITY_PARAM(0, 4) = 7; + + getSound()->playSteam(kCityPolice); + + getAction()->playAnimation(kEventCathDream); + + getState()->timeDelta = 3; + getProgress().field_18 = 1; + getProgress().field_84 = 0; + + getObjects()->update(kObject63, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + } else { + getSound()->playSound(kEntityPlayer, "LIB014"); + getSound()->playSound(kEntityPlayer, "LIB015", SoundManager::kFlagDefault, 15); + + if (!getSound()->isBuffered(kEntityChapters)) + getSound()->playSound(kEntityChapters, "MUS009", SoundManager::kFlagDefault); + + getScenes()->loadSceneFromPosition(kCarLocomotive, 38); + + getObjects()->update(kObject63, kEntityChapters, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + params->param1 = 1; + } + break; + + case kActionDefault: + RESET_ENTITY_STATE(kEntityPascale, Pascale, setup_function19); + RESET_ENTITY_STATE(kEntityServers0, Servers0, setup_function22); + RESET_ENTITY_STATE(kEntityServers1, Servers1, setup_function16); + RESET_ENTITY_STATE(kEntityCooks, Cooks, setup_function7); + + RESET_ENTITY_STATE(kEntityMertens, Mertens, setup_function42); + RESET_ENTITY_STATE(kEntityCoudert, Coudert, setup_chapter1Handler); + RESET_ENTITY_STATE(kEntityVerges, Verges, setup_chapter1Handler); + + getSavePoints()->push(kEntityChapters, kEntityMertens, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityCoudert, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityVerges, kAction201431954); + + RESET_ENTITY_STATE(kEntityKronos, Kronos, setup_function10); + RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_function13); + RESET_ENTITY_STATE(kEntityAnna, Anna, setup_function34); + RESET_ENTITY_STATE(kEntityAugust, August, setup_function34); + RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_function24); + RESET_ENTITY_STATE(kEntityVassili, Vassili, setup_function7); + RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_function26); + RESET_ENTITY_STATE(kEntityMilos, Milos, setup_function18); + RESET_ENTITY_STATE(kEntityVesna, Vesna, setup_function15); + RESET_ENTITY_STATE(kEntityIvo, Ivo, setup_function17); + RESET_ENTITY_STATE(kEntitySalko, Salko, setup_function11); + RESET_ENTITY_STATE(kEntityFrancois, Francois, setup_function20); + RESET_ENTITY_STATE(kEntityMmeBoutarel, MmeBoutarel, setup_function16); + RESET_ENTITY_STATE(kEntityBoutarel, Boutarel, setup_function22); + RESET_ENTITY_STATE(kEntityRebecca, Rebecca, setup_function27); + RESET_ENTITY_STATE(kEntitySophie, Sophie, setup_function5); + RESET_ENTITY_STATE(kEntityMahmud, Mahmud, setup_resetChapter); + RESET_ENTITY_STATE(kEntityYasmin, Yasmin, setup_function10); + RESET_ENTITY_STATE(kEntityHadija, Hadija, setup_function12); + RESET_ENTITY_STATE(kEntityHadija, Alouan, setup_function12); + + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + getSound()->processEntries(); + + if (getSound()->isBuffered("CON1505")) + getSound()->processEntry("CON1505"); + + if (getSound()->isBuffered("AUG1057")) + getSound()->processEntry("AUG1057"); + + if (getSound()->isBuffered("ZFX1005")) + getSound()->processEntry("ZFX1005"); + + if (getSound()->isBuffered("ZFX1006")) + getSound()->processEntry("ZFX1006"); + + if (getSound()->isBuffered("ZFX1007")) + getSound()->processEntry("ZFX1007"); + + if (getSound()->isBuffered("ZFX1007A")) + getSound()->processEntry("ZFX1007A"); + + if (getSound()->isBuffered("ZFX1007B")) + getSound()->processEntry("ZFX1007B"); + + + getSound()->playSound(kEntityPlayer, "MUS008", SoundManager::kFlagDefault); + getInventory()->unselectItem(); + + // FIXME add event pump ? + while (getSound()->isBuffered("MUS008")) + getSound()->updateQueue(); + + getProgress().field_84 = true; + + getScenes()->loadSceneFromPosition(kCarLocomotive, 75); + getInventory()->show(); + + getState()->time = kTime1492200; + getProgress().field_18 = 4; + getState()->timeDelta = 0; + + getObjects()->update(kObject63, kEntityChapters, kObjectLocationNone, kCursorNormal, kCursorHand); + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStopRunning); + + getProgress().isTrainRunning = false; + + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kAction225358684: + params->param2++; + + if (params->param2 >= 3) { + + if (!getSound()->isBuffered("LIB031", true)) + getSound()->playSound(kEntityPlayer, "LIB031"); + + if (params->param2 == 3) { + getData()->car = kCarGreenSleeping; + getEntities()->drawSequenceLeft(kEntityChapters, "JUGL"); + } + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Chapters, chapter1Init) + if (savepoint.action != kActionDefault) + return; + + getProgress().chapter = kChapter1; + getSound()->resetState(); + + getState()->time = kTimeChapter1; + getState()->timeDelta = 0; + getProgress().isTrainRunning = true; + getProgress().portrait = kPortraitOriginal; + getProgress().field_18 = 1; + + // Setup inventory & items location + getInventory()->addItem(kItemTelegram); + getInventory()->addItem(kItemArticle); + + getInventory()->setLocationAndProcess(kItemScarf, kObjectLocation1); + getInventory()->setLocationAndProcess(kItemParchemin, kObjectLocation1); + getInventory()->setLocationAndProcess(kItemGreenJacket, kObjectLocation1); + getInventory()->setLocationAndProcess(kItemCorpse, kObjectLocation1); + getInventory()->setLocationAndProcess(kItemPassengerList, kObjectLocation1); + getInventory()->setLocationAndProcess(kItem5, kObjectLocation1); + getInventory()->setLocationAndProcess(kItem7, kObjectLocation1); + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + getInventory()->setLocationAndProcess(kItemMatch, kObjectLocation1); + getInventory()->setLocationAndProcess(kItem22, kObjectLocation1); + getInventory()->setLocationAndProcess(kItemPaper, kObjectLocation1); + + getProgress().field_7C = 1; + + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + for (uint i = kObjectCompartment1; i <= kObjectCompartment8; i++) { + getObjects()->updateLocation2((ObjectIndex)i, kObjectLocation2); + } + + for (uint i = kObjectCompartmentA; i <= kObjectCompartmentH; i++) { + getObjects()->updateLocation2((ObjectIndex)i, kObjectLocation2); + } + + params->param1 = 40; + + getObjects()->updateLocation2(kObject25, kObjectLocation1); + getObjects()->updateLocation2(kObjectTrainTimeTable, kObjectLocation1); + getObjects()->updateLocation2(kObject98, kObjectLocation1); + getObjects()->updateLocation2(kObjectRestaurantCar, kObjectLocation1); + + getObjects()->update(kObject25, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObjectTrainTimeTable, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObjectRedSleepingCar, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject28, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject56, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject54, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObjectRestaurantCar, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject59, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject66, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject64, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject65, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject69, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObject98, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHandKnock); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHandKnock); + getObjects()->update(kObject101, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setup_chapter1Handler(); +} + +////////////////////////////////////////////////////////////////////////// +#define PLAY_STEAM() { \ + getSound()->resetState(); \ + getSound()->playSteam((CityIndex)ENTITY_PARAM(0, 4)); \ + ENTITY_PARAM(0, 2) = 0; \ + } + +IMPLEMENT_FUNCTION(8, Chapters, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getProgress().isTrainRunning || getState()->time >= kTime1458000) + goto label_processStations; + + UPDATE_PARAM_PROC(params->param6, getState()->timeTicks, params->param2) + // Play sound FX + getSound()->playLocomotiveSound(); + + params->param2 = 225 * (4 * rnd(5) + 20); + params->param6 = 0; + UPDATE_PARAM_PROC_END + +label_processStations: + // Process stations + TIME_CHECK_SAVEGAME(kTime1039500, params->param7, 1, kSavegameTypeTime, kTimeNone); + +label_enter_epernay: + // Entering Epernay station + TIME_CHECK_ENTERSTATION(kTimeEnterEpernay, params->param8, 1, "Epernay", kCityEpernay); + +label_exit_epernay: + // Exiting Epernay station + TIME_CHECK_EXITSTATION_2(kTimeExitEpernay, CURRENT_PARAMS(1, 1), params->param4, 3, "Epernay"); + +label_epernay_police: + TIME_CHECK_EXITSTATION_0(params->param5, ENTITY_PARAM(0, 2), 4, "Unschedu"); + +label_enter_chalons: + if (getState()->time > kTimeEnterChalons && !CURRENT_PARAMS(1, 2)) { + CURRENT_PARAMS(1, 2) = 1; + getProgress().field_18 = 2; + } + + // Skip to callback 18 checks + if (params->param1) + goto label_exit_strasbourg; + + // Entering Chalons station + TIME_CHECK_ENTERSTATION(kTimeEnterChalons, CURRENT_PARAMS(1, 3), 5, "Chalons", kCityChalons); + +label_exit_chalons: + // Exiting Chalons station + TIME_CHECK_EXITSTATION(kTimeExitChalons, CURRENT_PARAMS(1, 4), 6, "Chalons"); + +label_enter_barleduc: + // Entering Bar-Le-Duc station + TIME_CHECK_ENTERSTATION(kTimeCityBarLeDuc, CURRENT_PARAMS(1, 5), 7, "BarLeDuc", kCityBarleduc); + +label_exit_barleduc: + // Exiting Bar-Le-Duc station + TIME_CHECK_EXITSTATION(kTimeExitBarLeDuc, CURRENT_PARAMS(1, 6), 8, "BarLeDuc"); + +label_enter_nancy: + if (getState()->time > kTime1260000 && !CURRENT_PARAMS(1, 7)) { + CURRENT_PARAMS(1, 7) = 1; + getState()->timeDelta = 1; + } + + // Entering Nancy station + TIME_CHECK_ENTERSTATION(kTimeCityNancy, CURRENT_PARAMS(1, 8), 9, "Nancy", kCityNancy); + +label_exit_nancy: + // Exiting Nancy station + TIME_CHECK_EXITSTATION(kTimeExitNancy, CURRENT_PARAMS(2, 1), 10, "Nancy"); + +label_enter_luneville: + // Entering Luneville station + TIME_CHECK_ENTERSTATION(kTimeCityLuneville, CURRENT_PARAMS(2, 2), 11, "Luneville", kCityLuneville); + +label_exit_luneville: + // Exiting Luneville station + TIME_CHECK_EXITSTATION(kTimeExitLuneville, CURRENT_PARAMS(2, 3), 12, "Luneville"); + +label_enter_avricourt: + // Entering Avricourt station + TIME_CHECK_ENTERSTATION(kTimeCityAvricourt, CURRENT_PARAMS(2, 4), 13, "Avricourt", kCityAvricourt); + +label_exit_avricourt: + // Exiting Avricourt station + TIME_CHECK_EXITSTATION(kTimeExitAvricourt, CURRENT_PARAMS(2, 5), 14, "Avricourt"); + +label_enter_deutschavricourt: + // Entering Deutsch-Avricourt station + TIME_CHECK_ENTERSTATION(kTimeCityDeutschAvricourt, CURRENT_PARAMS(2, 6), 15, "DeutschA", kCityDeutschAvricourt); + +label_exit_deutschavricourt: + // Exiting Avricourt station + TIME_CHECK_EXITSTATION(kTimeExitDeutschAvricourt, CURRENT_PARAMS(2, 7), 16, "DeutschA"); + +label_enter_strasbourg: + TIME_CHECK_SAVEGAME(kTimeCityStrasbourg, CURRENT_PARAMS(2, 8), 17, kSavegameTypeTime, kTimeNone); + +label_exit_strasbourg: + // Exiting Strasbourg station + TIME_CHECK_EXITSTATION(kTimeExitStrasbourg, CURRENT_PARAMS(3, 1), 19, "Strasbou"); + +label_enter_badenoos: + // Entering Baden Oos station + TIME_CHECK_ENTERSTATION(kTimeCityBadenOos, CURRENT_PARAMS(3, 2), 20, "BadenOos", kCityBadenOos); + +label_exit_badenoos: + // Exiting Baden Oos station + TIME_CHECK_EXITSTATION(kTimeExitBadenOos, CURRENT_PARAMS(3, 3), 21, "BadenOos"); + +label_chapter1_next: + if (getState()->time > kTimeChapter1End3 && ! CURRENT_PARAMS(3, 4)) { + CURRENT_PARAMS(3, 4) = 1; + setup_chapter1Next(); + } + break; + + case kActionEndSound: + if (ENTITY_PARAM(0, 2)) { + + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStopRunning); + + if (getEntityData(kEntityPlayer)->location != kLocationOutsideTrain) { + PLAY_STEAM(); + break; + } + + if (getEntities()->isOutsideAlexeiWindow()) { + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + PLAY_STEAM(); + break; + } + + if (getEntities()->isOutsideAnnaWindow()) { + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + PLAY_STEAM(); + break; + } + + CarIndex car = getEntityData(kEntityPlayer)->car; + if (car < kCarRedSleeping || car > kCarCoalTender) { + if (car < kCarBaggageRear || car > kCarGreenSleeping) { + PLAY_STEAM(); + break; + } + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 98)) { + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 71); + PLAY_STEAM(); + break; + } + + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 82); + PLAY_STEAM(); + break; + } + + getScenes()->loadSceneFromPosition(kCarRestaurant, 82); + PLAY_STEAM(); + break; + } + + if (ENTITY_PARAM(0, 3)) { + getSound()->resetState(); + ENTITY_PARAM(0, 3) = 0; + + if (params->param4) { + getSavePoints()->push(kEntityChapters, getProgress().field_24 ? kEntityVerges : kEntityMertens, getProgress().field_24 ? kAction168187490 : kAction224122407); + params->param4 = 0; + } + } + break; + + case kActionDefault: + params->param2 = 225 * (4 * rnd(5) + 20); + break; + + case kActionDrawScene: + if (!params->param3) { + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { + getState()->time = kTimeChapter1; + getState()->timeDelta = 3; + params->param3 = 1; + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_enter_epernay; + + case 2: + goto label_exit_epernay; + + case 3: + goto label_epernay_police; + + case 4: + params->param5 = 0; + goto label_enter_chalons; + + case 5: + goto label_exit_chalons; + + case 6: + goto label_enter_barleduc; + + case 7: + goto label_exit_barleduc; + + case 8: + goto label_enter_nancy; + + case 9: + goto label_exit_nancy; + + case 10: + goto label_enter_luneville; + + case 11: + goto label_exit_luneville; + + case 12: + goto label_enter_avricourt; + + case 13: + goto label_exit_avricourt; + + case 14: + goto label_enter_deutschavricourt; + + case 15: + goto label_exit_deutschavricourt; + + case 16: + getState()->time = kTimeEnterStrasbourg; + goto label_enter_strasbourg; + + case 17: + getProgress().field_18 = 1; + setCallback(18); + setup_enterStation("Strasbou", kCityStrasbourg); + break; + + case 18: + goto label_exit_strasbourg; + + case 19: + getState()->timeDelta = 1; + goto label_enter_badenoos; + + case 20: + goto label_exit_badenoos; + + case 21: + goto label_chapter1_next; + + case 22: + params->param5 = 1; + break; + + case 23: + params->param1 = 1; + break; + } + break; + + case kAction169629818: + setCallback(22); + setup_enterStation("Unschedu", kCityPolice); + break; + + case kActionEndChapter: + getProgress().field_18 = 3; + + if (getState()->time >= kTimeChapter1End) { + setup_chapter1Next(); + } else { + setCallback(23); + setup_chapter1End(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Chapters, chapter1Next) + if (savepoint.action == kActionDefault) { + // Reset sound cache + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + getSound()->playSound(kEntityPlayer, "MUS008", SoundManager::kFlagDefault); + getInventory()->unselectItem(); + + while (getSound()->isBuffered("MUS008")) + getSound()->updateQueue(); + + setup_chapter2(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Chapters, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + // Setup for chapter 2 in case it hasn't been done before + if (getProgress().chapter != kChapter2) { + getProgress().chapter = kChapter2; + getEntities()->setupChapter(kChapter2); + } + + // Set game time & delta + getState()->time = kTimeChapter2; + getState()->timeDelta = 5; + + // Save game + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (!_engine->getResourceManager()->loadArchive(kArchiveCd2)) { + getMenu()->show(false, kSavegameTypeIndex, 0); + return; + } + + // Load scene data + getScenes()->loadSceneDataFile(kArchiveCd2); + setup_chapter2Init(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Chapters, chapter2Init) + if (savepoint.action != kActionDefault) + return; + + getProgress().eventCorpseMovedFromFloor = true; + getProgress().field_18 = 1; + getProgress().isTrainRunning = true; + getProgress().eventCorpseFound = true; + + // Switch to green jacket/portrait + getProgress().jacket = kJacketGreen; + getProgress().portrait = kPortraitGreen; + + // Setup inventory & items location + getInventory()->addItem(kItemGreenJacket); + + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + + getInventory()->setLocationAndProcess(kItemBeetle, kObjectLocation3); + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + + for (uint i = 1; i < 9; i++) { + getObjects()->updateLocation2((ObjectIndex)i, kObjectLocation2); + } + + for (uint i = 33; i < 40; i++) { + getObjects()->updateLocation2((ObjectIndex)i, kObjectLocation2); + } + + params->param1 = 40; + + getSavePoints()->push(kEntityChapters, kEntityTables0, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables1, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables2, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables3, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables4, kActionDrawTablesWithChairs); + + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + // Reset sound cache + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + getAction()->playAnimation(kEventTrainPassing); + + if (getInventory()->hasItem(kItemScarf)) + getScenes()->loadScene(kScene41); + else + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 79); + + setup_chapter2Handler(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Chapters, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getProgress().isTrainRunning) + break; + + UPDATE_PARAM(params->param2, getState()->timeTicks, params->param1); + + getSound()->playLocomotiveSound(); + + params->param1 = 225 * (4 * rnd(5) + 20); + params->param2 = 0; + break; + + case kActionDefault: + params->param1 = 225 * (4 * rnd(5) + 20); + break; + + case kActionChapter3: + setup_chapter3(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Chapters, chapter3) + if (savepoint.action == kActionDefault) { + // Setup for chapter 3 in case it hasn't been done before + if (getProgress().chapter != kChapter3) { + getProgress().chapter = kChapter3; + getEntities()->setupChapter(kChapter3); + } + + // Set game time & delta + getState()->time = kTimeChapter3; + getState()->timeDelta = 5; + + setup_chapter3Init(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Chapters, chapter3Init) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityChapters, kEntityTables0, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables1, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables2, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables3, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables4, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables5, kActionDrawTablesWithChairs); + + getProgress().isTrainRunning = true; + + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getInventory()->setLocationAndProcess(kItemBriefcase, kObjectLocation1); + getInventory()->setLocationAndProcess(kItem3, kObjectLocation1); + getObjects()->updateLocation2(kObjectCompartment1, kObjectLocation2); + getObjects()->update(kObject107, kEntityPlayer, kObjectLocation3, kCursorKeepValue, kCursorKeepValue); + + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + getScenes()->loadSceneFromPosition(kCarRestaurant, 60); + getInventory()->show(); + + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_chapter3Handler(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Chapters, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().isTrainRunning) { + UPDATE_PARAM_PROC(params->param4, getState()->timeTicks, params->param1) + getSound()->playLocomotiveSound(); + + params->param1 = 225 * (4 * rnd(5) + 20); + params->param4 = 0; + UPDATE_PARAM_PROC_END + } + + UPDATE_PARAM_PROC(params->param5, getState()->timeTicks, params->param2) + switch (rnd(2)) { + default: + break; + + case 0: + getSound()->playSound(kEntityPlayer, "ZFX1008", (SoundManager::FlagType)(rnd(15) + 2)); + break; + + case 1: + getSound()->playSound(kEntityPlayer, "ZFX1009", (SoundManager::FlagType)(rnd(15) + 2)); + break; + } + + params->param2 = 225 * (4 * rnd(6) + 8); + params->param5 = 0; + UPDATE_PARAM_PROC_END + + TIME_CHECK_ENTERSTATION(kTimeEnterSalzbourg, params->param6, 1, "Salzburg", kCitySalzbourg); + +label_callback_1: + TIME_CHECK_EXITSTATION(kTimeExitSalzbourg, params->param7, 2, "Salzburg"); + +label_callback_2: + TIME_CHECK_ENTERSTATION(kTimeEnterAttnangPuchheim, params->param8, 3, "Attnang", kCityAttnangPuchheim); + +label_callback_3: + TIME_CHECK_EXITSTATION(kTimeExitAttnangPuchheim, CURRENT_PARAMS(1, 1), 4, "Attnang"); + +label_callback_4: + TIME_CHECK_ENTERSTATION(kTimeEnterWels, CURRENT_PARAMS(1, 2), 5, "Wels", kCityWels); + +label_callback_5: + TIME_CHECK_EXITSTATION(kTimeEnterWels, CURRENT_PARAMS(1, 3), 6, "Wels"); + +label_callback_6: + TIME_CHECK_ENTERSTATION(kTimeEnterLinz, CURRENT_PARAMS(1, 4), 7, "Linz", kCityLinz); + +label_callback_7: + TIME_CHECK_EXITSTATION(kTimeCityLinz, CURRENT_PARAMS(1, 5), 8, "Linz"); + +label_callback_8: + if (getState()->time > kTime2187000 && !CURRENT_PARAMS(1, 6)) { + CURRENT_PARAMS(1, 6) = 1; + getState()->timeDelta = 5; + } + + TIME_CHECK_ENTERSTATION(kTimeCityVienna, CURRENT_PARAMS(1, 7), 9, "Vienna", kCityVienna); + break; + + case kActionEndSound: + if (ENTITY_PARAM(0, 2)) { + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStopRunning); + + if (getEntityData(kEntityPlayer)->location == kLocationOutsideTrain) { + + if (getEntities()->isOutsideAlexeiWindow()) { + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + } else if (getEntities()->isOutsideAnnaWindow()) { + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + } else { + CarIndex car = getEntityData(kEntityPlayer)->car; + + if (car < kCarRedSleeping || car > kCarCoalTender) { + if (car >= kCarBaggageRear && car <= kCarGreenSleeping) { + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 98)) { + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 71); + } else { + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 82); + } + } + } else { + getScenes()->loadSceneFromPosition(kCarRestaurant, 82); + } + } + } + + getSound()->resetState(); + getSound()->playSteam((CityIndex)ENTITY_PARAM(0, 4)); + + ENTITY_PARAM(0, 2) = 0; + if (params->param1) + setup_viennaEvents(); + + break; + } + + if (ENTITY_PARAM(0, 3)) { + getSound()->resetState(); + ENTITY_PARAM(0, 3) = 0; + } + break; + + case kActionDefault: + params->param1 = 225 * (4 * rnd(5) + 20); + params->param2 = 225 * (4 * rnd(6) + 8); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + + case 9: + params->param3 = 1; + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Chapters, viennaEvents) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventViennaAugustUnloadGuns); + if (getEvent(kEventConcertLeaveWithBriefcase)) + getLogic()->gameOver(kSavegameTypeTime, kTime2187000, kSceneNone, true); + else if (getEvent(kEventCathJumpDownCeiling)) + getLogic()->gameOver(kSavegameTypeEvent, kEventCathJumpDownCeiling, kSceneNone, true); + else + getLogic()->gameOver(kSavegameTypeTime, kTime2155500, kSceneNone, true); + break; + + case 2: + getAction()->playAnimation(kEventViennaKronosFirebird); + if (getEvent(kEventKronosBringEggCeiling)) + getLogic()->gameOver(kSavegameTypeEvent2, kEventKronosBringEggCeiling, kSceneGameOverVienna1, true); + else if (getEvent(kEventKronosBringEgg)) { + if (getEvent(kEventKronosBringEggCeiling)) + getLogic()->gameOver(kSavegameTypeEvent2, kEventKronosBringEggCeiling, kSceneGameOverVienna1, true); + else + getLogic()->gameOver(kSavegameTypeTime, kTime2155500, kSceneGameOverVienna1, true); + } else { + if (getProgress().field_C0) { + if (getEvent(kEventKronosReturnBriefcase)) + getLogic()->gameOver(kSavegameTypeTime, getProgress().field_C0, kSceneGameOverVienna2, true); + else + getLogic()->gameOver(kSavegameTypeTime, kTime2155500, kSceneGameOverVienna2, true); + } else { + if (getEvent(kEventKronosReturnBriefcase)) + getLogic()->gameOver(kSavegameTypeEvent, kEventKronosReturnBriefcase, kSceneGameOverVienna, true); + else + getLogic()->gameOver(kSavegameTypeTime, kTime2155500, kSceneGameOverVienna, true); + } + } + break; + + case 3: + getAction()->playAnimation(kEventVergesAnnaDead); + getLogic()->gameOver(kSavegameTypeTime, kTime2250000, kSceneGameOverAnnaDied, true); + break; + + case 4: + getAction()->playAnimation(kEventViennaContinueGame); + setup_chapter4(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Chapters, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + // Setup for chapter 4 in case it hasn't been done before + if (getProgress().chapter != kChapter4) { + getProgress().chapter = kChapter4; + getEntities()->setupChapter(kChapter4); + } + + // Set game time & delta + getState()->time = kTimeChapter4; + getState()->timeDelta = 5; + + // Save game + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (!_engine->getResourceManager()->loadArchive(kArchiveCd3)) { + getMenu()->show(false, kSavegameTypeIndex, 0); + return; + } + + // Load scene data + getScenes()->loadSceneDataFile(kArchiveCd3); + setup_chapter4Init(); + } + break; + + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Chapters, chapter4Init) + if (savepoint.action != kActionDefault) + return; + + getSound()->processEntries(); + getSound()->resetState(); + + getProgress().isTrainRunning = true; + + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStartRunning); + getSavePoints()->push(kEntityChapters, kEntityTables0, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables1, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables2, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables3, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables4, kActionDrawTablesWithChairs); + getSavePoints()->push(kEntityChapters, kEntityTables5, kActionDrawTablesWithChairs); + + getScenes()->loadSceneFromItemPosition(kItem3); + + getInventory()->setLocationAndProcess(kItemBomb, kObjectLocation1); + + if (getInventory()->get(kItemBeetle)->location == kObjectLocation3) + getScenes()->loadSceneFromItemPosition(kItemBeetle); + + getObjects()->updateLocation2(kObject25, kObjectLocation2); + getObjects()->update(kObject107, kEntityPlayer, kObjectLocation3, kCursorKeepValue, kCursorKeepValue); + + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + if (getInventory()->hasItem(kItemFirebird)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 76); + else + getScenes()->loadSceneFromPosition(kCarRestaurant, 69); + + getInventory()->show(); + setup_chapter4Handler(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Chapters, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().isTrainRunning) { + UPDATE_PARAM_PROC(params->param6, getState()->timeTicks, params->param4); + getSound()->playLocomotiveSound(); + + params->param4 = 225 * (4 * rnd(5) + 20); + params->param6 = 0; + UPDATE_PARAM_PROC_END + } + + UPDATE_PARAM_PROC(params->param7, getState()->timeTicks, params->param5) + switch (rnd(2)) { + default: + break; + + case 0: + getSound()->playSound(kEntityPlayer, "ZFX1008", (SoundManager::FlagType)(rnd(15) + 2)); + break; + + case 1: + getSound()->playSound(kEntityPlayer, "ZFX1009", (SoundManager::FlagType)(rnd(15) + 2)); + break; + } + + params->param5 = 225 * (4 * rnd(6) + 8); + params->param7 = 0; + UPDATE_PARAM_PROC_END + + TIME_CHECK_ENTERSTATION(kTimeEnterPoszony, params->param8, 1, "Pozsony", kCityPoszony); + +label_exitPozsony: + TIME_CHECK_EXITSTATION(kTimeExitPoszony, CURRENT_PARAMS(1, 1), 2, "Pozsony"); + +label_enterGalanta: + if (getObjects()->get(kObjectCompartment1).location2 == kObjectLocation1) { + if (getState()->time > kTime2403000 && !CURRENT_PARAMS(1, 2)) { + CURRENT_PARAMS(1, 2) = 1; + getProgress().field_18 = 2; + } + } + + if (params->param1) + goto label_callback_4; + + TIME_CHECK_ENTERSTATION(kTimeEnterGalanta, CURRENT_PARAMS(1, 3), 3, "Galanta", kCityGalanta); + +label_exitGalanta: + TIME_CHECK_EXITSTATION(kTimeExitGalanta, CURRENT_PARAMS(1, 4), 4, "Galanta"); + +label_callback_4: + if (getState()->time > kTime2470500 && !CURRENT_PARAMS(1, 5)) { + CURRENT_PARAMS(1, 5) = 1; + + if (getProgress().field_18 == 2) + getState()->timeDelta = 1; + } + + if (getState()->time > kTime2506500 && !CURRENT_PARAMS(1, 6)) { + CURRENT_PARAMS(1, 6) = 1; + + if (getProgress().field_18 == 2) + getProgress().field_18 = 1; + } + + if (getState()->time > kTime2520000 && !CURRENT_PARAMS(1, 7)) { + CURRENT_PARAMS(1, 7) = 1; + + if (!params->param2 && !params->param3) { + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventTrainExplosionBridge); + } + } + break; + + case kActionEndSound: + if (ENTITY_PARAM(0, 2)) { + + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStopRunning); + + if (getEntityData(kEntityPlayer)->location != kLocationOutsideTrain) { + PLAY_STEAM(); + break; + } + + if (getEntities()->isOutsideAlexeiWindow()) { + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + PLAY_STEAM(); + break; + } + + if (getEntities()->isOutsideAnnaWindow()) { + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + PLAY_STEAM(); + break; + } + + CarIndex car = getEntityData(kEntityPlayer)->car; + if (car < kCarRedSleeping || car > kCarCoalTender) { + if (car < kCarBaggageRear || car > kCarGreenSleeping) { + PLAY_STEAM(); + break; + } + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 98)) { + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 71); + PLAY_STEAM(); + break; + } + + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 82); + PLAY_STEAM(); + break; + } + + getScenes()->loadSceneFromPosition(kCarRestaurant, 82); + PLAY_STEAM(); + break; + } + + if (ENTITY_PARAM(0, 3)) { + getSound()->resetState(); + ENTITY_PARAM(0, 3) = 0; + } else if (!params->param2 && !params->param3) { + getSound()->playSound(kEntityChapters, "ZFX1001"); + } + break; + + case kActionExitCompartment: + getEntities()->clearSequences(kEntityChapters); + + setCallback(11); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionDefault: + params->param4 = 225 * (4 * rnd(5) + 20); + params->param5 = 225 * (4 * rnd(6) + 8); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_exitPozsony; + + case 2: + goto label_enterGalanta; + + case 3: + goto label_exitGalanta; + + case 4: + goto label_callback_4; + + case 5: + if (getSound()->isBuffered(kEntityChapters)) + getSound()->removeFromQueue(kEntityChapters); + + getAction()->playAnimation(kEventTrainExplosionBridge); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + + case 6: + getSound()->processEntries(); + getAction()->playAnimation(kEventTylerCastleDream); + getSound()->resetState(); + + getProgress().field_18 = 1; + + getScenes()->loadScene(kScene41); + getSavePoints()->push(kEntityChapters, kEntityTatiana, kAction169360385); + + getState()->timeDelta = 1; + getState()->time = kTime2511900; + + getInventory()->setLocationAndProcess(kItem2, kObjectLocation1); + getScenes()->loadSceneFromItemPosition(kItem22); + + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationInsideCompartment; + + getSound()->playSound(kEntityChapters, "ZFX1001"); + break; + + case 7: + getAction()->playAnimation(kEventTrainExplosionBridge); + getLogic()->gameOver(kSavegameTypeTime, kTime2430000, kSceneNone, true); + break; + + case 8: + getSound()->playSound(kEntityPlayer, "MUS022"); + + if (getState()->time < kTime2517300) + getState()->time = kTime2517300; + break; + + case 9: + getAction()->playAnimation(kEventCathDefusingBomb); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 73); + break; + + case 10: + getAction()->playAnimation(kEventDefuseBomb); + RESET_ENTITY_STATE(kEntityAbbot, Abbot, setup_function48); + getSavePoints()->push(kEntityChapters, kEntityAnna, kAction191001984); + getSavePoints()->push(kEntityChapters, kEntityCoudert, kAction191001984); + getScenes()->loadSceneFromItemPosition(kItem2); + + getInventory()->get(kItem2)->location = kObjectLocationNone; + params->param2 = 1; + + getScenes()->loadSceneFromPosition(kCarRedSleeping, 2); + break; + + case 11: + getScenes()->loadSceneFromPosition(kCarRedSleeping, 74); + getSound()->playSound(kEntityTrain, "ZFX4001", SoundManager::kFlagDefault); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + } + break; + + case kActionChapter5: + setup_chapter5(); + break; + + case kAction156435676: + getSavePoints()->push(kEntityChapters, kEntityTatiana, kAction169360385); + getSavePoints()->push(kEntityChapters, kEntityCoudert, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityVerges, kAction201431954); + + getState()->timeDelta = 1; + getState()->time = kTime2511900; + + getInventory()->setLocationAndProcess(kItem2, kObjectLocation1); + + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationInsideCompartment; + + getSound()->playSound(kEntityChapters, "ZFX1001"); + break; + + case kAction158610240: + setCallback(8); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kAction169300225: + if (getState()->time < kTime2519100) + getState()->time = kTime2519100; + + params->param3 = 1; + + getEntities()->drawSequenceRight(kEntityChapters, "BOMB"); + break; + + case kAction190346110: + getProgress().field_18 = 3; + + params->param1 = 1; + + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + getSound()->playSound(kEntityPlayer, "MUS008", SoundManager::kFlagDefault); + getInventory()->unselectItem(); + + while (getSound()->isBuffered("MUS008")) + getSound()->updateQueue(); + + if (getInventory()->hasItem(kItemBomb)) { + RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_function47); + RESET_ENTITY_STATE(kEntityAnna, Anna, setup_function68); + RESET_ENTITY_STATE(kEntityAugust, August, setup_function65); + RESET_ENTITY_STATE(kEntityMertens, Mertens, setup_function48); + RESET_ENTITY_STATE(kEntityCoudert, Coudert, setup_function53); + RESET_ENTITY_STATE(kEntityServers0, Servers0, setup_chapter4Handler); + RESET_ENTITY_STATE(kEntityServers1, Servers1, setup_chapter4Handler); + RESET_ENTITY_STATE(kEntityPascale, Pascale, setup_chapter4Handler); + RESET_ENTITY_STATE(kEntityVerges, Verges, setup_chapter4Handler); + RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_function49); + RESET_ENTITY_STATE(kEntityAbbot, Abbot, setup_function44); + RESET_ENTITY_STATE(kEntityMilos, Milos, setup_function32); + RESET_ENTITY_STATE(kEntityVesna, Vesna, setup_function27); + RESET_ENTITY_STATE(kEntityIvo, Ivo, setup_function29); + RESET_ENTITY_STATE(kEntitySalko, Salko, setup_function22); + RESET_ENTITY_STATE(kEntityMmeBoutarel, MmeBoutarel, setup_function25); + RESET_ENTITY_STATE(kEntityBoutarel, Boutarel, setup_function35); + RESET_ENTITY_STATE(kEntityRebecca, Rebecca, setup_function45); + RESET_ENTITY_STATE(kEntitySophie, Sophie, setup_function9); + RESET_ENTITY_STATE(kEntityYasmin, Yasmin, setup_function17); + RESET_ENTITY_STATE(kEntityHadija, Hadija, setup_function19); + RESET_ENTITY_STATE(kEntityAlouan, Alouan, setup_function19); + RESET_ENTITY_STATE(kEntityMax, Max, setup_chapter4Handler); + getSavePoints()->push(kEntityChapters, kEntityAnna, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityMertens, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityCoudert, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityServers0, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityServers1, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityPascale, kAction201431954); + getSavePoints()->push(kEntityChapters, kEntityVerges, kAction201431954); + + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventTylerCastleDream); + } else { + getState()->time = kTime2520000; + + setCallback(7); + setup_savegame(kSavegameTypeEvent, kEventTrainExplosionBridge); + } + break; + + case kAction191001984: + getState()->time = kTime2520000; + + if (getSound()->isBuffered(kEntityChapters)) + getSound()->removeFromQueue(kEntityChapters); + + getEntities()->clearSequences(kEntityChapters); + getInventory()->removeItem(kItemTelegram); + + getState()->timeDelta = 5; + + setCallback(10); + setup_savegame(kSavegameTypeEvent, kEventDefuseBomb); + break; + + case kAction201959744: + if (getSound()->isBuffered(kEntityChapters)) + getSound()->removeFromQueue(kEntityChapters); + + getSound()->playSound(kEntityTrain, "ZFX4001", SoundManager::kFlagDefault); + + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true); + break; + + case kAction225367984: + setCallback(9); + setup_savegame(kSavegameTypeEvent, kEventCathDefusingBomb); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Chapters, chapter5) + if (savepoint.action == kActionDefault) { + // Setup for chapter 5 in case it hasn't been done before + if (getProgress().chapter != kChapter5) { + getProgress().chapter = kChapter5; + getEntities()->setupChapter(kChapter5); + } + + // Set game time & delta + getState()->time = kTimeChapter5; + getState()->timeDelta = 2; + + setup_chapter5Init(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Chapters, chapter5Init) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTables0); + getEntities()->clearSequences(kEntityTables1); + getEntities()->clearSequences(kEntityTables2); + getEntities()->clearSequences(kEntityTables3); + getEntities()->clearSequences(kEntityTables4); + getEntities()->clearSequences(kEntityTables5); + + getProgress().isTrainRunning = true; + + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment5, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectKitchen, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject20, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject21, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject22, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject48, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getProgress().field_18 = 1; + getProgress().field_84 = 1; + getProgress().portrait = kCursorPortraitYellow; + + getInventory()->unselectItem(); + + getInventory()->removeItem(kItemKey); + getInventory()->removeItem(kItemBomb); + getInventory()->removeItem(kItemMatch); + + if (getInventory()->hasItem(kItemFirebird)) { + getInventory()->removeItem(kItemFirebird); + getInventory()->setLocationAndProcess(kItemFirebird, kObjectLocation3); + + if (getInventory()->hasItem(kItemWhistle)) { + getInventory()->removeItem(kItemWhistle); + getInventory()->setLocationAndProcess(kItemWhistle, kObjectLocation3); + } + } + + getObjects()->update(kObject93, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject94, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject101, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getObjects()->updateLocation2(kObject98, kObjectLocation2); + getObjects()->updateLocation2(kObjectRestaurantCar, kObjectLocation2); + + if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { + getSound()->removeFromQueue(kEntityChapters); + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + } + + getScenes()->loadSceneFromPosition(kCarBaggageRear, 95); + getInventory()->show(); + + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_chapter5Handler(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2907000 && !params->param2) { + params->param2 = 1; + + if (!getProgress().isNightTime) { + getSound()->playSound(kEntityChapters, "ARRIVE", SoundManager::kFlag8); + getSound()->processEntries(); + } + } + + if (getState()->time > kTimeTrainStopped2 && !params->param3) { + params->param3 = 1; + + if (!getEvent(kEventLocomotiveMilos) && !getEvent(kEventLocomotiveMilosNight)) { + getSound()->playSound(kEntityChapters, "ARRIVE", SoundManager::kFlag8); + getSound()->processEntries(); + } + } + break; + + case kActionEndSound: + if (getState()->time <= kTimeTrainStopped2) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventTrainStopped); + } else { + getLogic()->gameOver(kSavegameTypeTime, kTimeTrainStopped2, kSceneGameOverTrainStopped, true); + } + break; + + case kActionDefault: + params->param1 = 225 * (4 * rnd(10) + 20); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventTrainStopped); + getLogic()->gameOver(kSavegameTypeTime, kTimeTrainStopped, kSceneGameOverTrainStopped, true); + } + break; + + case kAction135800432: + getProgress().isNightTime = true; + getState()->time = kTime2916000; + + if (getSound()->isBuffered(kEntityChapters)) + getSound()->removeFromQueue(kEntityChapters); + break; + } +} + + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Chapters::enterExitStation(const SavePoint &savepoint, bool isEnteringStation) { + if (savepoint.action == kActionDefault) { + if (!ENTITY_PARAM(0, 2) && !ENTITY_PARAM(0, 3)) { + enterExitHelper(isEnteringStation); + return; + } + + getSound()->removeFromQueue(kEntityChapters); + + if (!ENTITY_PARAM(0, 2)) { + if (ENTITY_PARAM(0, 3)) + ENTITY_PARAM(0, 3) = 0; + + enterExitHelper(isEnteringStation); + return; + } + + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStopRunning); + + if (getEntityData(kEntityPlayer)->location != kLocationOutsideTrain) { + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + return; + } + + // Green sleeping car + if (getEntities()->isOutsideAlexeiWindow()) { + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + return; + } + + // Red sleeping car + if (getEntities()->isOutsideAnnaWindow()) { + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + return; + } + + // Other cars + if (getEntityData(kEntityPlayer)->car < kCarRedSleeping || getEntityData(kEntityPlayer)->car > kCarCoalTender) { + + if (getEntityData(kEntityPlayer)->car < kCarBaggageRear || getEntityData(kEntityPlayer)->car > kCarGreenSleeping) { + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + return; + } + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 98)) { + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 71); + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + return; + } + + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 82); + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + return; + } + + getScenes()->loadSceneFromPosition(kCarRestaurant, 82); + ENTITY_PARAM(0, 2) = 0; + enterExitHelper(isEnteringStation); + } +} + +////////////////////////////////////////////////////////////////////////// +void Chapters::enterExitHelper(bool isEnteringStation) { + EXPOSE_PARAMS(EntityData::EntityParametersSIIS); + + getSound()->playSound(kEntityChapters, isEnteringStation ? "ARRIVE" : "DEPART", SoundManager::kFlag8); + getSound()->processEntries(); + + getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, isEnteringStation ? kCursorNormal : kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, isEnteringStation ? kCursorNormal : kCursorHand); + + getProgress().isTrainRunning = isEnteringStation ? false : true; + + if (isEnteringStation) { + ENTITY_PARAM(0, 2) = 1; + ENTITY_PARAM(0, 4) = params->param4; + } else { + getSavePoints()->push(kEntityChapters, kEntityTrain, kActionTrainStartRunning); + ENTITY_PARAM(0, 3) = 1; + } + + CALLBACK_ACTION(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/chapters.h b/engines/lastexpress/entities/chapters.h new file mode 100644 index 0000000000..845fe8b727 --- /dev/null +++ b/engines/lastexpress/entities/chapters.h @@ -0,0 +1,166 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_CHAPTERS_H +#define LASTEXPRESS_CHAPTERS_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Chapters : public Entity { +public: + Chapters(LastExpressEngine *engine); + ~Chapters() {}; + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Exit a train station + * + * @param stationName The name of the train station + * @param index The index of the train station + */ + DECLARE_FUNCTION_2(enterStation, const char *stationName, CityIndex index) + + /** + * Exit a train station + * + * @param stationName The name of the train station + */ + DECLARE_FUNCTION_1(exitStation, const char *stationName) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Reset main entities + */ + DECLARE_FUNCTION(resetMainEntities) + + /** + * Handle end of Chapter 1 events + */ + DECLARE_FUNCTION(chapter1End) + + /** + * Init Chapter 1 data + */ + DECLARE_FUNCTION(chapter1Init) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + /** + * Handle switching to Chapter 2 after the end of Chapter 1 + */ + DECLARE_FUNCTION(chapter1Next) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Init Chapter 2 data + */ + DECLARE_FUNCTION(chapter2Init) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Init Chapter 3 data + */ + DECLARE_FUNCTION(chapter3Init) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Handle Vienna events + */ + DECLARE_FUNCTION(viennaEvents) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Init Chapter 4 data + */ + DECLARE_FUNCTION(chapter4Init) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Init Chapter 5 data + */ + DECLARE_FUNCTION(chapter5Init) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + +private: + void enterExitStation(const SavePoint &savepoint, bool isEnteringStation); + void enterExitHelper(bool isEnteringStation); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_CHAPTERS_H diff --git a/engines/lastexpress/entities/cooks.cpp b/engines/lastexpress/entities/cooks.cpp new file mode 100644 index 0000000000..2bc787b495 --- /dev/null +++ b/engines/lastexpress/entities/cooks.cpp @@ -0,0 +1,571 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/cooks.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Cooks::Cooks(LastExpressEngine *engine) : Entity(engine, kEntityCooks) { + ADD_CALLBACK_FUNCTION(Cooks, draw); + ADD_CALLBACK_FUNCTION(Cooks, playSound); + ADD_CALLBACK_FUNCTION(Cooks, function3); + ADD_CALLBACK_FUNCTION(Cooks, function4); + ADD_CALLBACK_FUNCTION(Cooks, chapter1); + ADD_CALLBACK_FUNCTION(Cooks, chapter1Handler); + ADD_CALLBACK_FUNCTION(Cooks, function7); + ADD_CALLBACK_FUNCTION(Cooks, chapter2); + ADD_CALLBACK_FUNCTION(Cooks, chapter2Handler); + ADD_CALLBACK_FUNCTION(Cooks, chapter3); + ADD_CALLBACK_FUNCTION(Cooks, chapter3Handler); + ADD_CALLBACK_FUNCTION(Cooks, chapter4); + ADD_CALLBACK_FUNCTION(Cooks, chapter4Handler); + ADD_CALLBACK_FUNCTION(Cooks, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(1, Cooks, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Cooks, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Cooks, function3) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityCooks, "308A"); + getEntities()->updatePositionEnter(kEntityCooks, kCarRestaurant, 75); + getEntities()->updatePositionEnter(kEntityCooks, kCarRestaurant, 78); + + switch (getProgress().chapter) { + default: + getSound()->playSound(kEntityCooks, "KIT1011"); + setCallback(3); + setup_draw("308B"); + break; + + case kChapter1: + setCallback(1); + setup_playSound("KIT1010"); + break; + + case kChapter3: + setCallback(2); + setup_playSound("KIT1012"); + break; + } + break; + + case kActionDrawScene: + if (!getEntities()->isInKitchen(kEntityPlayer)) { + getEntities()->clearSequences(kEntityCooks); + CALLBACK_ACTION(); + break; + } + + if (getEntities()->isPlayerPosition(kCarRestaurant, 46)) { + getEntities()->drawSequenceLeft(kEntityCooks, "308D"); + + if (!getSound()->isBuffered(kEntityCooks)) { + if (params->param1) { + if (!getEntities()->hasValidFrame(kEntityCooks)) { + getSound()->playSound(kEntityCooks, "LIB015"); + getEntities()->clearSequences(kEntityCooks); + CALLBACK_ACTION(); + } + break; + } + + // Kitchen apprentice getting a lesson :D + getSound()->playSound(kEntityCooks, "KIT1011A"); + params->param1 = 1; + } + } + + if (params->param1 && !getEntities()->hasValidFrame(kEntityCooks)) { + getSound()->playSound(kEntityCooks, "LIB015"); + getEntities()->clearSequences(kEntityCooks); + CALLBACK_ACTION(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + getSound()->playSound(kEntityCooks, "KIT1011"); + setCallback(3); + setup_draw("308B"); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCooks, "308C"); + getEntities()->updatePositionExit(kEntityCooks, kCarRestaurant, 75); + getEntities()->updatePositionExit(kEntityCooks, kCarRestaurant, 78); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Cooks, function4) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityCooks, "308A"); + getEntities()->updatePositionEnter(kEntityCooks, kCarRestaurant, 75); + getEntities()->updatePositionEnter(kEntityCooks, kCarRestaurant, 78); + + switch (getProgress().chapter) { + default: + break; + + case kChapter1: + setCallback(2); + setup_playSound("ZFX1011"); + break; + + case kChapter3: + setCallback(2); + setup_playSound("ZFX1011"); + break; + } + + getSound()->playSound(kEntityCooks, "KIT1011"); + setCallback(3); + setup_draw("308B"); + break; + + case kActionDrawScene: + if (!getEntities()->isInKitchen(kEntityPlayer)) { + getEntities()->clearSequences(kEntityCooks); + CALLBACK_ACTION(); + break; + } + + if (getEntities()->isPlayerPosition(kCarRestaurant, 80)) { + getEntities()->drawSequenceLeft(kEntityCooks, "308D"); + + if (!getSound()->isBuffered(kEntityCooks)) { + if (params->param1) { + if (!getEntities()->hasValidFrame(kEntityCooks)) { + getSound()->playSound(kEntityCooks, "LIB015"); + getEntities()->clearSequences(kEntityCooks); + CALLBACK_ACTION(); + } + break; + } + + // Kitchen apprentice getting a lesson :D + getSound()->playSound(kEntityCooks, "KIT1011A"); + params->param1 = 1; + } + } + + if (params->param1 && !getEntities()->hasValidFrame(kEntityCooks)) { + getSound()->playSound(kEntityCooks, "LIB015"); + getEntities()->clearSequences(kEntityCooks); + CALLBACK_ACTION(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + getSound()->playSound(kEntityCooks, "KIT1011"); + setCallback(3); + setup_draw("308B"); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCooks, "308C"); + getEntities()->updatePositionExit(kEntityCooks, kCarRestaurant, 75); + getEntities()->updatePositionEnter(kEntityCooks, kCarRestaurant, 78); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Cooks, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + + getProgress().field_4C = 0; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Cooks, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param4, getState()->time, params->param2); + + // Broken plate sound + getSound()->playSound(kEntityPlayer, "LIB122", getSound()->getSoundFlag(kEntityCooks)); + params->param2 = 225 * (4 * rnd(30) + 120); + params->param4 = 0; + break; + + case kActionDefault: + params->param1 = 1; + params->param2 = 225 * (4 * rnd(30) + 120); + break; + + case kActionDrawScene: + if (!getEntities()->isInKitchen(kEntityPlayer)) + break; + + if (params->param1) { + if (getEntities()->isPlayerPosition(kCarRestaurant, 73)) { + setCallback(1); + setup_function3(); + } + } else { + if (params->param3) { + setCallback(2); + setup_playSound("ZFX1011"); + } else { + setCallback(3); + setup_playSound("ZFX1012"); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 0; + break; + + case 2: + case 3: + params->param3 = !params->param3; + break; + } + break; + + case kAction101632192: + setup_function7(); + break; + + case kAction224849280: + getProgress().field_4C = 1; + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Cooks, function7) + switch (savepoint.action) { + default: + break; + + case kActionNone: + // Snoring... + setCallback(1); + setup_playSound("WAT1200"); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_3650; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + + getEntities()->clearSequences(kEntityCooks); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Cooks, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCooks); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + getProgress().field_4C = 1; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Cooks, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param3, getState()->time, params->param1); + + // Broken plate sound + getSound()->playSound(kEntityPlayer, "LIB122", getSound()->getSoundFlag(kEntityCooks)); + params->param1 = 225 * (4 * rnd(30) + 120); + params->param3 = 0; + break; + + case kActionDefault: + params->param1 = 225 * (4 * rnd(30) + 120); + break; + + case kActionDrawScene: + if (params->param2) { + setCallback(1); + setup_playSound("ZFX1011"); + } else { + setCallback(2); + setup_playSound("ZFX1012"); + } + break; + + case kActionCallback: + if (getCallback() == 1 || getCallback() == 2) + params->param2 = !params->param2; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Cooks, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCooks); + + getData()->entityPosition = kPosition_5900; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + getProgress().field_4C = 0; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Cooks, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(params->param4, getState()->time, params->param2) + // Broken plate sound + getSound()->playSound(kEntityPlayer, "LIB122", getSound()->getSoundFlag(kEntityCooks)); + params->param2 = 225 * (4 * rnd(30) + 120); + params->param4 = 0; + UPDATE_PARAM_PROC_END + + if (getState()->time > kTime2079000 && !params->param5) { + params->param1 = 0; + params->param5 = 1; + } + break; + + case kActionDefault: + params->param1 = 1; + params->param2 = 225 * (4 * rnd(30) + 120); + break; + + case kActionDrawScene: + if (!getEntities()->isInKitchen(kEntityPlayer)) + break; + + if (params->param1) { + if (getEntities()->isPlayerPosition(kCarRestaurant, 80)) { + setCallback(1); + setup_function4(); + } + } else { + if (params->param3) { + setCallback(2); + setup_playSound("ZFX1011"); + } else { + setCallback(3); + setup_playSound("ZFX1012"); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 0; + break; + + case 2: + case 3: + params->param3 = !params->param3; + break; + } + break; + + case kAction236976550: + getProgress().field_4C = 1; + break; + + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Cooks, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCooks); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + getProgress().field_4C = 1; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Cooks, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param3, getState()->time, params->param1) + + // Broken plate sound + getSound()->playSound(kEntityPlayer, "LIB122", getSound()->getSoundFlag(kEntityCooks)); + params->param1 = 225 * (4 * rnd(30) + 120); + params->param3 = 0; + break; + + case kActionDefault: + params->param1 = 225 * (4 * rnd(30) + 120); + break; + + case kActionDrawScene: + if (!getEntities()->isInKitchen(kEntityPlayer)) + break; + + // Kitchen background sound + if (params->param2) { + setCallback(1); + setup_playSound("ZFX1011"); + } else { + setCallback(2); + setup_playSound("ZFX1012"); + } + break; + + + case kActionCallback: + // Play the next part of background sound + if (getCallback() == 1 || getCallback() == 2) { + params->param2 = !params->param2; + } + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Cooks, chapter5) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityCooks); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/cooks.h b/engines/lastexpress/entities/cooks.h new file mode 100644 index 0000000000..7f1a70fb8a --- /dev/null +++ b/engines/lastexpress/entities/cooks.h @@ -0,0 +1,109 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_COOKS_H +#define LASTEXPRESS_COOKS_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Cooks : public Entity { +public: + Cooks(LastExpressEngine *engine); + ~Cooks() {}; + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + DECLARE_FUNCTION(function3) + + DECLARE_FUNCTION(function4) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function7) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_COOKS_H diff --git a/engines/lastexpress/entities/coudert.cpp b/engines/lastexpress/entities/coudert.cpp new file mode 100644 index 0000000000..6249ea5487 --- /dev/null +++ b/engines/lastexpress/entities/coudert.cpp @@ -0,0 +1,3611 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/coudert.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +#define SAVEGAME_BLOOD_JACKET() \ + if (getProgress().jacket == kJacketBlood \ + && getEntities()->isDistanceBetweenEntities(kEntityCoudert, kEntityPlayer, 1000) \ + && !getEntities()->isInsideCompartments(kEntityPlayer) \ + && !getEntities()->checkFields10(kEntityPlayer)) { \ + setCallback(1); \ + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); \ + } + +Coudert::Coudert(LastExpressEngine *engine) : Entity(engine, kEntityCoudert) { + ADD_CALLBACK_FUNCTION(Coudert, reset); + ADD_CALLBACK_FUNCTION(Coudert, bloodJacket); + ADD_CALLBACK_FUNCTION(Coudert, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Coudert, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Coudert, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Coudert, playSound); + ADD_CALLBACK_FUNCTION(Coudert, playSound16); + ADD_CALLBACK_FUNCTION(Coudert, savegame); + ADD_CALLBACK_FUNCTION(Coudert, updateEntity); + ADD_CALLBACK_FUNCTION(Coudert, updateFromTime); + ADD_CALLBACK_FUNCTION(Coudert, updateFromTicks); + ADD_CALLBACK_FUNCTION(Coudert, excuseMe); + ADD_CALLBACK_FUNCTION(Coudert, function13); + ADD_CALLBACK_FUNCTION(Coudert, function14); + ADD_CALLBACK_FUNCTION(Coudert, function15); + ADD_CALLBACK_FUNCTION(Coudert, function16); + ADD_CALLBACK_FUNCTION(Coudert, function17); + ADD_CALLBACK_FUNCTION(Coudert, function18); + ADD_CALLBACK_FUNCTION(Coudert, function19); + ADD_CALLBACK_FUNCTION(Coudert, function20); + ADD_CALLBACK_FUNCTION(Coudert, function21); + ADD_CALLBACK_FUNCTION(Coudert, function22); + ADD_CALLBACK_FUNCTION(Coudert, function23); + ADD_CALLBACK_FUNCTION(Coudert, visitCompartmentF); + ADD_CALLBACK_FUNCTION(Coudert, function25); + ADD_CALLBACK_FUNCTION(Coudert, function26); + ADD_CALLBACK_FUNCTION(Coudert, function27); + ADD_CALLBACK_FUNCTION(Coudert, visitCompartmentB); + ADD_CALLBACK_FUNCTION(Coudert, visitCompartmentA); + ADD_CALLBACK_FUNCTION(Coudert, function30); + ADD_CALLBACK_FUNCTION(Coudert, function31); + ADD_CALLBACK_FUNCTION(Coudert, function32); + ADD_CALLBACK_FUNCTION(Coudert, function33); + ADD_CALLBACK_FUNCTION(Coudert, function34); + ADD_CALLBACK_FUNCTION(Coudert, function35); + ADD_CALLBACK_FUNCTION(Coudert, chapter1); + ADD_CALLBACK_FUNCTION(Coudert, function37); + ADD_CALLBACK_FUNCTION(Coudert, function38); + ADD_CALLBACK_FUNCTION(Coudert, function39); + ADD_CALLBACK_FUNCTION(Coudert, chapter1Handler); + ADD_CALLBACK_FUNCTION(Coudert, function41); + ADD_CALLBACK_FUNCTION(Coudert, chapter2); + ADD_CALLBACK_FUNCTION(Coudert, function43); + ADD_CALLBACK_FUNCTION(Coudert, chapter3); + ADD_CALLBACK_FUNCTION(Coudert, function45); + ADD_CALLBACK_FUNCTION(Coudert, function46); + ADD_CALLBACK_FUNCTION(Coudert, function47); + ADD_CALLBACK_FUNCTION(Coudert, function48); + ADD_CALLBACK_FUNCTION(Coudert, function49); + ADD_CALLBACK_FUNCTION(Coudert, function50); + ADD_CALLBACK_FUNCTION(Coudert, function51); + ADD_CALLBACK_FUNCTION(Coudert, chapter4); + ADD_CALLBACK_FUNCTION(Coudert, function53); + ADD_CALLBACK_FUNCTION(Coudert, function54); + ADD_CALLBACK_FUNCTION(Coudert, function55); + ADD_CALLBACK_FUNCTION(Coudert, function56); + ADD_CALLBACK_FUNCTION(Coudert, chapter5); + ADD_CALLBACK_FUNCTION(Coudert, chapter5Handler); + ADD_CALLBACK_FUNCTION(Coudert, function59); + ADD_CALLBACK_FUNCTION(Coudert, function60); + ADD_CALLBACK_FUNCTION(Coudert, function61); + ADD_CALLBACK_FUNCTION(Coudert, function62); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Coudert, reset) + Entity::reset(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Coudert, bloodJacket) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityCoudert, (char *)¶ms->seq1); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Coudert, enterExitCompartment, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + return; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + return; + } + + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Coudert, callbackActionOnDirection) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getData()->direction != kDirectionRight) { + CALLBACK_ACTION(); + break; + } + + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIII(5, Coudert, enterExitCompartment2, ObjectIndex, EntityPosition, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + return; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + return; + } + + Entity::enterExitCompartment(savepoint, (EntityPosition)params->param5, (EntityPosition)params->param6, kCarRedSleeping, (ObjectIndex)params->param4, false); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Coudert, playSound) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionEndSound: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getSound()->playSound(kEntityCoudert, (char *)¶ms->seq1); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(7, Coudert, playSound16) + EXPOSE_PARAMS(EntityData::EntityParametersSIIS); + + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionEndSound: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getSound()->playSound(kEntityCoudert, (char *)¶ms->seq1, SoundManager::kFlagDefault); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Coudert, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(9, Coudert, updateEntity, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 && getEntities()->isDistanceBetweenEntities(kEntityCoudert, kEntityPlayer, 2000)) + getData()->inventoryItem = kItemInvalid; + else + getData()->inventoryItem = kItemNone; + + if (getProgress().jacket != kJacketBlood + || !getEntities()->isDistanceBetweenEntities(kEntityCoudert, kEntityPlayer, 1000) + || getEntities()->isInsideCompartments(kEntityPlayer) + || getEntities()->checkFields10(kEntityPlayer)) { + if (getEntities()->updateEntity(kEntityCoudert, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + + CALLBACK_ACTION(); + } + break; + } + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + + case kAction1: + params->param3 = 0; + getData()->inventoryItem = kItemNone; + + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventCoudertAskTylerCompartment); + break; + + case kActionExcuseMeCath: + if (getData()->clothes == kClothes1) + getSound()->playSound(kEntityPlayer, "ZFX1003", getSound()->getSoundFlag(kEntityCoudert)); + else if (!getSound()->isBuffered(kEntityCoudert)) + getSound()->playSound(kEntityPlayer, "JAC1112", getSound()->getSoundFlag(kEntityCoudert)); + break; + + case kActionExcuseMe: + if (getData()->clothes == kClothes1) + getSound()->playSound(kEntityPlayer, "ZFX1003", getSound()->getSoundFlag(kEntityCoudert)); + else + getSound()->excuseMe(kEntityCoudert); + break; + + case kActionDefault: + if (!getProgress().eventCorpseFound && !getEvent(kEventCoudertAskTylerCompartment)) + params->param3 = kItemInvalid; + + if (getEntities()->updateEntity(kEntityCoudert, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 2: + getAction()->playAnimation(kEventCoudertAskTylerCompartment); + + if (getData()->direction != kDirectionUp) + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750)); + else + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition - 750), true); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(10, Coudert, updateFromTime, uint32) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + + UPDATE_PARAM(params->param2, getState()->time, params->param1); + + CALLBACK_ACTION(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(11, Coudert, updateFromTicks, uint32) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + + UPDATE_PARAM(params->param2, getState()->timeTicks, params->param1); + + CALLBACK_ACTION(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// Parameters +// - EntityIndex +IMPLEMENT_FUNCTION_I(12, Coudert, excuseMe, EntityIndex) + if (savepoint.action != kActionDefault) + return; + + if (getSound()->isBuffered(kEntityCoudert)) { + CALLBACK_ACTION(); + return; + } + + if (isNight()) { + if (Entities::isFemale((EntityIndex)params->param1)) { + getSound()->playSound(kEntityCoudert, Entities::isMarried((EntityIndex)params->param1) ? "JAC1112C" : "JAC1112F"); + } else { + if (!params->param1 && getProgress().field_18 == 2) { + switch (rnd(4)) { + default: + break; + + case 0: + getSound()->playSound(kEntityCoudert, "JAC1013"); + break; + + case 1: + getSound()->playSound(kEntityCoudert, "JAC1013A"); + break; + + case 2: + getSound()->playSound(kEntityCoudert, "JAC1113"); + break; + + case 3: + getSound()->playSound(kEntityCoudert, "JAC1113A"); + break; + } + } else { + getSound()->playSound(kEntityCoudert, "JAC1112D"); + } + } + } else { + if (Entities::isFemale((EntityIndex)params->param1)) + getSound()->playSound(kEntityCoudert, Entities::isMarried((EntityIndex)params->param1) ? "JAC1112B" : "JAC1112G"); + else + getSound()->playSound(kEntityCoudert, "JAC1112E"); + } + + CALLBACK_ACTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(13, Coudert, function13, bool, EntityIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + + if (!params->param2 && !params->param3) { + + if (!params->param4) { + params->param4 = getState()->timeTicks + 75; + + if (!params->param4) { + getData()->inventoryItem = kItemNone; + setCallback(4); + setup_function19(true); + break; + } + } + + if (params->param4 < getState()->timeTicks) { + params->param4 = kTimeInvalid; + + getData()->inventoryItem = kItemNone; + setCallback(4); + setup_function19(true); + break; + } + } + + UPDATE_PARAM(params->param5, getState()->timeTicks, 225); + + getData()->inventoryItem = kItemNone; + setCallback(5); + setup_function19(true); + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(9); + setup_savegame(kSavegameTypeEvent, kEventCoudertAskTylerCompartment); + break; + + case kAction11: + ++params->param3; + + setCallback(8); + setup_excuseMe(savepoint.entity2); + break; + + case kActionDefault: + if (params->param2) + params->param3 = 1; + + setCallback(1); + setup_excuseMe((EntityIndex)params->param2); + break; + + case kAction16: + --params->param3; + + if (params->param2 && !params->param3) { + getData()->inventoryItem = kItemNone; + setCallback(7); + setup_function19(true); + } + break; + + case kActionDrawScene: + if (!params->param3) { + getData()->inventoryItem = kItemNone; + setCallback(6); + setup_function19(true); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function17(true); + break; + + case 2: + if (getProgress().chapter == kChapter1 && !getProgress().eventCorpseFound && !getEvent(kEventCoudertAskTylerCompartment)) + getData()->inventoryItem = kItemInvalid; + + getEntities()->drawSequenceLeft(kEntityCoudert, params->param1 ? "667I" : "667H"); + break; + + case 3: + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + // BUG: the original game continues executing code here + break; + + case 4: + case 5: + case 6: + case 7: + CALLBACK_ACTION(); + break; + + case 9: + getAction()->playAnimation(kEventCoudertAskTylerCompartment); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 25); + break; + } + break; + + case kAction201439712: + getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(14, Coudert, function14, EntityIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionDefault: + if (ENTITY_PARAM(2, 1)) { + ENTITY_PARAM(2, 1) = 0; + + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_1500); + } else { + setCallback(1); + setup_updateFromTime(15); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityCoudert, (EntityIndex)params->param1, kAction202558662); + + setCallback(2); + setup_function17(false); + break; + + case 2: + getSavePoints()->push(kEntityCoudert, (EntityIndex)params->param1, kAction155853632); + getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); + break; + + case 3: + getSavePoints()->push(kEntityCoudert, (EntityIndex)params->param1, kAction202558662); + getSavePoints()->push(kEntityCoudert, (EntityIndex)params->param1, kAction155853632); + getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); + getScenes()->loadSceneFromItemPosition(kItem5); + break; + + case 4: + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + + case kAction125499160: + switch (params->param1) { + default: + break; + + case kEntityVerges: + ENTITY_PARAM(0, 3) = 0; + break; + + case kEntityMmeBoutarel: + ENTITY_PARAM(0, 4) = 0; + break; + + case kEntityMertens: + ENTITY_PARAM(0, 5) = 0; + break; + } + + setCallback(5); + setup_function19(false); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(15, Coudert, function15, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + ENTITY_PARAM(0, 8) = 0; + ENTITY_PARAM(1, 1) = 0; + + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_7500); + break; + + case 2: + if (params->param1) + getSound()->playSound(kEntityCoudert, "Tat3163"); + else + getSound()->playSound(kEntityCoudert, (getProgress().chapter != kChapter3 || getState()->time > kTime1449000) ? "Tat3162A" : "Tat3161A"); + + setCallback(3); + setup_enterExitCompartment("627Xb", kObjectCompartmentB); + break; + + case 3: + getSavePoints()->push(kEntityCoudert, kEntityTatiana, kAction69239528); + getData()->entityPosition = kPosition_7250; + + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 4: + setCallback(5); + setup_function18(); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Coudert, function16) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(2, 1)) { + ENTITY_PARAM(2, 1) = 0; + getInventory()->setLocationAndProcess(kItem5, kObjectLocation1); + + CALLBACK_ACTION(); + break; + } + + setCallback(ENTITY_PARAM(0, 2) ? 1 : 2); + setup_bloodJacket(ENTITY_PARAM(0, 2) ? "627C" : "627F"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + getInventory()->setLocationAndProcess(kItem5, kObjectLocation1); + if (!getEntities()->isPlayerPosition(kCarRedSleeping, 2)) + getData()->entityPosition = kPosition_2088; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(17, Coudert, function17, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getScenes()->loadSceneFromItemPosition(kItem5); + + if (ENTITY_PARAM(2, 1)) { + ENTITY_PARAM(2, 1) = 0; + CALLBACK_ACTION(); + break; + } + + if (params->param1) { + setCallback(1); + setup_bloodJacket("627H"); + break; + } + + if (params->param2) { + setCallback(2); + setup_bloodJacket("627C"); + break; + } + + setCallback(3); + setup_bloodJacket("627F"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + case 3: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Coudert, function18) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(0, 6) || ENTITY_PARAM(0, 8) + || ENTITY_PARAM(1, 1) || ENTITY_PARAM(1, 2) || ENTITY_PARAM(1, 3) || ENTITY_PARAM(1, 5) || ENTITY_PARAM(1, 6) || ENTITY_PARAM(1, 7) || ENTITY_PARAM(1, 8) + || ENTITY_PARAM(2, 4) || ENTITY_PARAM(2, 6)) { + getInventory()->setLocationAndProcess(kItem5, kObjectLocation1); + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_540); + break; + } + + if (ENTITY_PARAM(0, 3) || ENTITY_PARAM(0, 5) || ENTITY_PARAM(0, 4)) { + getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); + getScenes()->loadSceneFromItemPosition(kItem5); + + CALLBACK_ACTION(); + break; + } + + getEntities()->drawSequenceRight(kEntityCoudert, ENTITY_PARAM(0, 2) ? "627A" : "627D"); + getScenes()->loadSceneFromItemPosition(kItem5); + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 68)) { + if (!getSound()->isBuffered(kEntityCoudert)) + getSound()->playSound(kEntityCoudert, "JAC1111"); + + getScenes()->loadSceneFromPosition(kCarRedSleeping, 25); + } + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityCoudert); + ENTITY_PARAM(2, 1) = 1; + + setCallback(2); + setup_updateFromTime(75); + break; + + case 2: + CALLBACK_ACTION(); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCoudert, ENTITY_PARAM(0, 2) ? "627B" : "627E"); + ENTITY_PARAM(0, 1) = 0; + getSavePoints()->push(kEntityCoudert, kEntityCoudert, kActionDrawScene); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(19, Coudert, function19, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(0, 6) || ENTITY_PARAM(0, 8) + || ENTITY_PARAM(1, 1) || ENTITY_PARAM(1, 2) || ENTITY_PARAM(1, 3) || ENTITY_PARAM(1, 5) || ENTITY_PARAM(1, 6) || ENTITY_PARAM(1, 7) || ENTITY_PARAM(1, 8) + || ENTITY_PARAM(2, 4) || ENTITY_PARAM(2, 6)) { + getInventory()->setLocationAndProcess(kItem5, kObjectLocation1); + ENTITY_PARAM(2, 1) = 1; + CALLBACK_ACTION(); + break; + } + + if (ENTITY_PARAM(0, 3) || ENTITY_PARAM(0, 5) || ENTITY_PARAM(0, 4)) { + getScenes()->loadSceneFromItemPosition(kItem5); + ENTITY_PARAM(2, 1) = 1; + CALLBACK_ACTION(); + break; + } + + if (params->param1) + getEntities()->drawSequenceRight(kEntityCoudert, "697H"); + else + getEntities()->drawSequenceRight(kEntityCoudert, ENTITY_PARAM(0, 2) ? "627A" : "627D"); + + getScenes()->loadSceneFromItemPosition(kItem5); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->drawSequenceLeft(kEntityCoudert, ENTITY_PARAM(0, 2) ? "627B" : "627E"); + ENTITY_PARAM(0, 1) = 0; + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(20, Coudert, function20, ObjectIndex, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(CURRENT_PARAMS(1, 3), getState()->time, 300) + getSound()->playSound(kEntityPlayer, "ZFX1004", getSound()->getSoundFlag(kEntityCoudert)); + UPDATE_PARAM_PROC_END + + UPDATE_PARAM(CURRENT_PARAMS(1, 4), getState()->time, 900); + + getObjects()->updateLocation2((ObjectIndex)params->param1, kObjectLocation1); + + if (params->param4 != kObjectLocation2) + getObjects()->update((ObjectIndex)params->param1, (EntityIndex)params->param3, (ObjectLocation)params->param4, (CursorStyle)params->param5, (CursorStyle)params->param6); + + if (params->param2) + getObjects()->update((ObjectIndex)params->param2, (EntityIndex)params->param7, (ObjectLocation)params->param8, (CursorStyle)CURRENT_PARAMS(1, 1), (CursorStyle)CURRENT_PARAMS(1, 2)); + + CALLBACK_ACTION(); + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update((ObjectIndex)params->param1, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorNormal); + if (params->param2) + getObjects()->update((ObjectIndex)params->param2, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + params->param3 = getObjects()->get((ObjectIndex)params->param1).entity; + params->param4 = getObjects()->get((ObjectIndex)params->param1).location; + params->param5 = getObjects()->get((ObjectIndex)params->param1).cursor; + params->param6 = getObjects()->get((ObjectIndex)params->param1).cursor2; + + if (params->param2) { + params->param7 = getObjects()->get((ObjectIndex)params->param2).entity; + params->param8 = getObjects()->get((ObjectIndex)params->param2).location; + CURRENT_PARAMS(1, 1) = getObjects()->get((ObjectIndex)params->param2).cursor; + CURRENT_PARAMS(1, 2) = getObjects()->get((ObjectIndex)params->param2).cursor2; + + getObjects()->update((ObjectIndex)params->param2, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + + if (params->param4 != kObjectLocation2) + getObjects()->update((ObjectIndex)params->param1, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + if (params->param1 == kObjectCompartmentA || params->param1 == kObjectCompartmentC + || params->param1 == kObjectCompartmentG || params->param1 == kObjectCompartmentH) { + setCallback(3); + setup_playSound("Jac1001B"); + } else { + setCallback(4); + setup_playSound("Jac1001A"); + } + break; + + case 3: + case 4: + getObjects()->update((ObjectIndex)params->param1, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + + if (params->param2) + getObjects()->update((ObjectIndex)params->param2, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Coudert, function21) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + UPDATE_PARAM(params->param2, getState()->timeTicks, 75); + + setCallback(3); + setup_enterExitCompartment("627Zh", kObjectCompartmentH); + } + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("627Vh", kObjectCompartmentH); + break; + + case 2: + getSavePoints()->push(kEntityCoudert, kEntityIvo, kAction221683008); + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wh"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentH, true); + break; + + case 3: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentH, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(4); + setup_function20(kObjectCompartmentH, kObjectNone); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("697Ah", kObjectCompartmentH); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + CALLBACK_ACTION(); + break; + + case 6: + getSavePoints()->push(kEntityCoudert, kEntityIvo, kAction122865568); + break; + + case 7: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentH, true); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(8); + setup_function20(kObjectCompartmentH, kObjectNone); + break; + + case 8: + getSound()->playSound(kEntityCoudert, "JAC1013A"); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(9); + setup_enterExitCompartment("667Uh", kObjectCompartmentH); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityCoudert, kEntityIvo, kAction123852928); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction88652208: + setCallback(7); + setup_enterExitCompartment("667Th", kObjectCompartmentH); + break; + + case kAction123199584: + params->param1 = 1; + + setCallback(6); + setup_playSound("JAC1012"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Coudert, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + UPDATE_PARAM(params->param2, getState()->timeTicks, 75); + + setCallback(3); + setup_enterExitCompartment("627Rg", kObjectCompartmentG); + } + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_3050); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("627Mg", kObjectCompartmentG); + break; + + case 2: + getSavePoints()->push(kEntityCoudert, kEntityMilos, kAction221683008); + getEntities()->drawSequenceLeft(kEntityCoudert, "627Ng"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentG, true); + break; + + case 3: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentG, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(4); + setup_function20(kObjectCompartmentG, kObjectNone); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("627Sg", kObjectCompartmentG); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + CALLBACK_ACTION(); + break; + + case 6: + getSavePoints()->push(kEntityCoudert, kEntityMilos, kAction122865568); + break; + + case 7: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentG, true); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(8); + setup_function20(kObjectCompartmentG, kObjectNone); + break; + + case 8: + getSound()->playSound(kEntityCoudert, "JAC1013A"); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(9); + setup_enterExitCompartment("627Ug", kObjectCompartmentG); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityCoudert, kEntityMilos, kAction123852928); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction88652208: + setCallback(7); + setup_enterExitCompartment("627Tg", kObjectCompartmentG); + break; + + case kAction123199584: + params->param1 = 1; + + setCallback(6); + setup_playSound("JAC1030"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Coudert, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("627Vf", kObjectCompartmentF); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wf"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentF, true); + getSavePoints()->push(kEntityCoudert, kEntityMax, kAction158007856); + + setCallback(3); + setup_updateFromTime(150); + break; + + case 3: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentF, true); + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Coudert, visitCompartmentF) + visitCompartment(savepoint, kPosition_4070, "627Vf", kObjectCompartmentF, "627Wf", "627Zf", kPosition_4455, kObject53, "697Af"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Coudert, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("627Me", kObjectCompartmentE); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Ne"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentE, true); + + setCallback(3); + setup_updateFromTime(45); + break; + + case 3: + getSavePoints()->push(kEntityCoudert, kEntityRebecca, kAction254915200); + + setCallback(4); + setup_updateFromTime(450); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment2("627Re", kObjectCompartmentE, kPosition_4840, kPosition_4455); + break; + + case 5: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentE, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(6); + setup_function20(kObjectCompartmentE, kObject52); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("627Se", kObjectCompartmentE); + break; + + case 7: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityCoudert, kEntityRebecca, kAction123852928); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Coudert, function26) + error("Coudert: callback function 26 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Coudert, function27) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + UPDATE_PARAM(params->param2, getState()->timeTicks, 75); + + setCallback(3); + setup_enterExitCompartment2("627Rc", kObjectCompartmentC, kPosition_6470, kPosition_6130); + } + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("627Mc", kObjectCompartmentC); + break; + + case 2: + getSavePoints()->push(kEntityCoudert, kEntityBoutarel, kAction221683008); + getEntities()->drawSequenceLeft(kEntityCoudert, "627Nc"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentC, true); + break; + + case 3: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentC, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(4); + setup_function20(kObjectCompartmentC, kObject50); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("627Sc", kObjectCompartmentC); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + CALLBACK_ACTION(); + break; + + case 6: + getSavePoints()->push(kEntityCoudert, kEntityBoutarel, kAction122865568); + break; + + case 7: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentC, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(8); + setup_function20(kObjectCompartmentC, kObject50); + break; + + case 8: + getSound()->playSound(kEntityCoudert, "JAC1013"); + + setCallback(9); + setup_enterExitCompartment("627Uc", kObjectCompartmentC); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityCoudert, kEntityBoutarel, kAction123852928); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction88652208: + setCallback(7); + setup_enterExitCompartment2("627Rc", kObjectCompartmentC, kPosition_6470, kPosition_6130); + break; + + case kAction123199584: + params->param1 = 1; + + setCallback(6); + setup_playSound("JAC1012"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Coudert, visitCompartmentB) + visitCompartment(savepoint, kPosition_7500, "627Vb", kObjectCompartmentB, "627Wb", "627Zb", kPosition_7850, kObject49, "697Ab"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Coudert, visitCompartmentA) + visitCompartment(savepoint, kPosition_8200, "627Ma", kObjectCompartmentA, "627Na", "627Ra", kPosition_7850, kObject48, "627Sa"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(30, Coudert, function30, ObjectIndex) + // Expose parameters as IIIIIS and ignore the default exposed parameters + EntityData::EntityParametersI5S *parameters = (EntityData::EntityParametersI5S*)_data->getCurrentParameters(); + EntityData::EntityParametersSIIS *parameters1 = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters(1); + + switch (savepoint.action) { + default: + break; + + case kActionDefault: + switch (parameters->param1) { + default: + CALLBACK_ACTION(); + // Stop processing here + return; + + case kObjectCompartmentA: + parameters->param2 = kPosition_8200; + parameters->param3 = kPosition_7850; + strcpy((char *)¶meters->seq, "627Ma"); + strcpy((char *)¶meters1->seq1, "627Na"); + break; + + case kObjectCompartmentB: + parameters->param2 = kPosition_7500; + parameters->param3 = kPosition_7850; + parameters->param4 = true; + strcpy((char *)¶meters->seq, "627Vb"); + strcpy((char *)¶meters1->seq1, "627Wb"); + break; + + case kObjectCompartmentC: + parameters->param2 = kPosition_6470; + parameters->param3 = kPosition_6130; + strcpy((char *)¶meters->seq, "627Mc"); + strcpy((char *)¶meters1->seq1, "627Nc"); + break; + + case kObjectCompartmentD: + parameters->param2 = kPosition_5790; + parameters->param3 = kPosition_6130; + parameters->param4 = true; + strcpy((char *)¶meters->seq, "627Vd"); + strcpy((char *)¶meters1->seq1, "627Wd"); + break; + + case kObjectCompartmentE: + parameters->param2 = kPosition_4840; + parameters->param3 = kPosition_4455; + parameters->param4 = true; + strcpy((char *)¶meters->seq, "627Me"); + strcpy((char *)¶meters1->seq1, "627Ne"); + break; + + case kObjectCompartmentF: + parameters->param2 = kPosition_4070; + parameters->param3 = kPosition_4455; + parameters->param4 = true; + strcpy((char *)¶meters->seq, "627Vf"); + strcpy((char *)¶meters1->seq1, "627Wf"); + break; + } + + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, (EntityPosition)parameters->param2); + break; + + case 2: + if (getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, (EntityPosition)parameters->param3) + || ((parameters->param1 == kObjectCompartmentE || parameters->param1 == kObjectCompartmentF) && getEntities()->isOutsideAnnaWindow())) { + getObjects()->update((ObjectIndex)parameters->param1, kEntityPlayer, getObjects()->get((ObjectIndex)parameters->param1).location, kCursorNormal, kCursorNormal); + parameters->param5 = true; + } + + setCallback(3); + setup_enterExitCompartment((char *)¶meters->seq, (ObjectIndex)parameters->param1); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCoudert, (char *)¶meters1->seq1); + getEntities()->enterCompartment(kEntityCoudert, (ObjectIndex)parameters->param1, true); + + setCallback(4); + setup_playSound(parameters->param4 ? "JAC3020" : "JAC3021"); + break; + + case 4: + if (parameters->param5) + getObjects()->update((ObjectIndex)parameters->param1, kEntityPlayer, getObjects()->get((ObjectIndex)parameters->param1).location, kCursorHandKnock, kCursorHand); + + getEntities()->exitCompartment(kEntityCoudert, (ObjectIndex)parameters->param1, true); + + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 5: + setCallback(6); + setup_function18(); + break; + + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(31, Coudert, function31, uint32) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + setCallback(3); + setup_function19(true); + break; + + case kActionDefault: + setCallback(1); + setup_bloodJacket("627G"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getSound()->isBuffered(kEntityCoudert)) { + getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); + } else { + setCallback(2); + setup_function19(true); + } + break; + + case 2: + case 3: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Coudert, function32) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 2: + getEntities()->clearSequences(kEntityCoudert); + setCallback(3); + setup_updateFromTime(900); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 4: + setCallback(5); + setup_function18(); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Coudert, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(0, 3) || ENTITY_PARAM(0, 4) || ENTITY_PARAM(0, 5) || ENTITY_PARAM(0, 6) || ENTITY_PARAM(0, 7) + || ENTITY_PARAM(1, 2) || ENTITY_PARAM(1, 7) + || ENTITY_PARAM(2, 2)) { + ENTITY_PARAM(2, 6) = 1; + + if (ENTITY_PARAM(0, 3) || ENTITY_PARAM(0, 4) || ENTITY_PARAM(0, 5)) { + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_1500); + } else { + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_540); + } + } else { + CALLBACK_ACTION(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + ENTITY_PARAM(2, 1) = 1; + if (ENTITY_PARAM(0, 3)) { + setCallback(2); + setup_function14(kEntityVerges); + break; + } + // Fallback to next case + + case 2: + if (ENTITY_PARAM(0, 5)) { + setCallback(3); + setup_function14(kEntityMertens); + break; + } + // Fallback to next case + + case 3: + if (ENTITY_PARAM(0, 4)) { + setCallback(4); + setup_function14(kEntityMmeBoutarel); + break; + } + // Fallback to next case + + case 4: + ENTITY_PARAM(2, 6) = 0; + + CALLBACK_ACTION(); + break; + + case 5: + getEntities()->clearSequences(kEntityCoudert); + + setCallback(6); + setup_updateFromTime(75); + break; + + case 6: + if (ENTITY_PARAM(0, 6) || ENTITY_PARAM(0, 7)) { + setCallback(7); + setup_function37(); + break; + } + // Fallback to next case + + case 7: + if (ENTITY_PARAM(2, 2)) { + setCallback(8); + setup_function39(); + break; + } + // Fallback to next case + + case 8: + if (ENTITY_PARAM(1, 2)) { + setCallback(9); + setup_function55(); + break; + } + // Fallback to next case + + case 9: + if (ENTITY_PARAM(1, 7)) { + setCallback(10); + setup_function34(false); + break; + } + // Fallback to next case + + case 10: + ENTITY_PARAM(2, 6) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(34, Coudert, function34, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + if (!params->param1) { + getSound()->playSound(kEntityCoudert, "Ann3124"); + + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 4) = 0; + + setCallback(7); + setup_function35((bool)params->param1); + } else { + getEntities()->drawSequenceLeft(kEntityCoudert, "627Vf"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentF, true); + + setCallback(3); + setup_playSound("LIB012"); + } + break; + + case 3: + setCallback(4); + setup_playSound("Jac1001"); + break; + + case 4: + getSound()->playSound(kEntityCoudert, "Ann3125"); + + setCallback(5); + setup_enterExitCompartment("629Bf", kObjectCompartmentF); + break; + + case 5: + setCallback(6); + setup_enterExitCompartment("629Ff", kObjectCompartmentF); + break; + + case 6: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentF, true); + + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 4) = 0; + + setCallback(7); + setup_function35((bool)params->param1); + break; + + case 7: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(35, Coudert, function35, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarBaggage)) { + getAction()->playAnimation(kEventCoudertBaggageCar); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + } + + UPDATE_PARAM(params->param2, getState()->time, 2700); + + getSavePoints()->push(kEntityCoudert, kEntityMax, kActionMaxFreeFromCage); + + getData()->clothes = kClothesDefault; + + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case kActionDefault: + if (params->param1) + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction156049968); + + getSavePoints()->push(kEntityCoudert, kEntityMax, kAction122358304); + + getData()->clothes = kClothes1; + getData()->entityPosition = kPosition_4370; + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_8200); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (!getSound()->isBuffered(kEntityCoudert)) + getSound()->playSound(kEntityCoudert, "Ann3124"); + + if (params->param1) + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction123733488); + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 2: + getEntities()->clearSequences(kEntityCoudert); + break; + + case 3: + setCallback(4); + setup_function18(); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Coudert, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTimeChapter1, params->param1, 1, setup_chapter1Handler) + break; + + case kActionDefault: + getSavePoints()->addData(kEntityCoudert, kAction292048641, 7); + getSavePoints()->addData(kEntityCoudert, kAction326348944, 8); + getSavePoints()->addData(kEntityCoudert, kAction171394341, 2); + getSavePoints()->addData(kEntityCoudert, kAction154005632, 4); + getSavePoints()->addData(kEntityCoudert, kAction169557824, 3); + getSavePoints()->addData(kEntityCoudert, kAction226031488, 5); + getSavePoints()->addData(kEntityCoudert, kAction339669520, 6); + getSavePoints()->addData(kEntityCoudert, kAction189750912, 10); + getSavePoints()->addData(kEntityCoudert, kAction185737168, 12); + getSavePoints()->addData(kEntityCoudert, kAction185671840, 13); + getSavePoints()->addData(kEntityCoudert, kAction205033696, 15); + getSavePoints()->addData(kEntityCoudert, kAction157026693, 14); + getSavePoints()->addData(kEntityCoudert, kAction189026624, 11); + getSavePoints()->addData(kEntityCoudert, kAction168254872, 17); + getSavePoints()->addData(kEntityCoudert, kAction201431954, 18); + getSavePoints()->addData(kEntityCoudert, kAction188570113, 19); + + ENTITY_PARAM(0, 1) = 0; + ENTITY_PARAM(0, 2) = 1; + + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->updateLocation2(kObject111, kObjectLocation1); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_chapter1Handler(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Coudert, function37) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getSound()->isBuffered(kEntityCoudert)) + getSound()->processEntry(kEntityCoudert); + + if (ENTITY_PARAM(0, 7)) { + getData()->entityPosition = kPosition_8200; + + setCallback(4); + setup_enterExitCompartment2("698Ha", kObjectCompartmentA, kPosition_8200, kPosition_7850); + } else { + setCallback(1); + setup_function16(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case 2: + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction238358920); + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_8200); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment2("698Ha", kObjectCompartmentA, kPosition_8200, kPosition_7850); + break; + + case 4: + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + setup_function38(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Coudert, function38) +switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + + setCallback(2); + setup_function18(); + break; + + case 2: + setup_chapter1Handler(); + break; + } + break; + + case kAction191477936: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Coudert, function39) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_playSound("LIB070"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function16(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("627Vd", kObjectCompartmentD); + break; + + case 4: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wd"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentD, true); + + setCallback(5); + setup_playSound("MME1151A"); + break; + + case 5: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentD, true); + + setCallback(6); + setup_enterExitCompartment("627Zd", kObjectCompartmentD); + break; + + case 6: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(7); + setup_playSound("MME1151"); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment("MME1151", kObjectCompartmentD); + break; + + case 8: + getSavePoints()->push(kEntityCoudert, kEntityMmeBoutarel, kAction223068211); + getData()->location = kLocationOutsideCompartment; + + setCallback(9); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 9: + setCallback(10); + setup_function18(); + break; + + case 10: + getSavePoints()->push(kEntityCoudert, kEntityVerges, kAction167854368); + ENTITY_PARAM(2, 2) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Coudert, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(2, 3)) { + ENTITY_PARAM(0, 1) = 1; + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 5) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + + ENTITY_PARAM(2, 1) = 0; + ENTITY_PARAM(2, 2) = 0; + + getEntities()->drawSequenceLeft(kEntityCoudert, "697F"); + + params->param1 = 1; + params->param2 = 1; + + ENTITY_PARAM(2, 3) = 0; + } + + getData()->inventoryItem = (getProgress().eventCorpseFound || getEvent(kEventCoudertAskTylerCompartment)) ? kItemNone : kItemInvalid; + + if (ENTITY_PARAM(0, 8)) { + getData()->inventoryItem = kItemNone; + + setCallback(4); + setup_function15(true); + break; + } + +label_callback_4: + if (ENTITY_PARAM(1, 1)) { + getData()->inventoryItem = kItemNone; + + setCallback(5); + setup_function15(false); + break; + } + +label_callback_5: + if (ENTITY_PARAM(0, 6) || ENTITY_PARAM(0, 7)) { + getData()->inventoryItem = kItemNone; + setup_function37(); + break; + } + + if (ENTITY_PARAM(0, 3)) { + getData()->inventoryItem = kItemNone; + + setCallback(6); + setup_function14(kEntityVerges); + break; + } + +label_callback_6: + if (ENTITY_PARAM(0, 5)) { + getData()->inventoryItem = kItemNone; + + setCallback(7); + setup_function14(kEntityMertens); + break; + } + +label_callback_7: + if (ENTITY_PARAM(0, 4)) { + getData()->inventoryItem = kItemNone; + + setCallback(8); + setup_function14(kEntityMmeBoutarel); + break; + } + +label_callback_8: + if (ENTITY_PARAM(2, 2)) { + getData()->inventoryItem = kItemNone; + + setCallback(9); + setup_function39(); + break; + } + +label_callback_9: + if (ENTITY_PARAM(0, 1) && !getSound()->isBuffered(kEntityCoudert)) + getSound()->playSound(kEntityCoudert, rnd(2) ? "JAC1065" : "JAC1065A"); + + if (getState()->time > kTime1107000 && !ENTITY_PARAM(0, 1) && !getEvent(kEventVassiliSeizure)) { + getData()->inventoryItem = kItemNone; + + setCallback(10); + setup_function41(); + break; + } + +label_callback_10: + if (getState()->time > kTime1189800 && !ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { + UPDATE_PARAM_PROC(params->param3, getState()->time, 2700); + ENTITY_PARAM(0, 2) = 1; + ENTITY_PARAM(0, 1) = 1; + + getEntities()->drawSequenceLeft(kEntityCoudert, "697F"); + + params->param3 = 0; + UPDATE_PARAM_PROC_END + } + + if (!ENTITY_PARAM(0, 2)) + break; + + TIME_CHECK_OBJECT(kTime1107000, params->param4, kObject111, kObjectLocation2); + TIME_CHECK_OBJECT(kTime1161000, params->param5, kObject111, kObjectLocation3); + TIME_CHECK_OBJECT(kTime1206000, params->param6, kObject111, kObjectLocation4); + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(11); + setup_savegame(kSavegameTypeEvent, kEventCoudertAskTylerCompartment); + break; + + case kAction11: + if (!ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { + getData()->inventoryItem = kItemNone; + + setCallback(13); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2); + } + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + + getScenes()->loadSceneFromItemPosition(kItem5); + break; + + case kActionDrawScene: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + + if (!getEntities()->isPlayerPosition(kCarRedSleeping, 1) && !getEntities()->isPlayerPosition(kCarRedSleeping, 23)) + break; + + if (getProgress().jacket == kJacketBlood) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCoudertBloodJacket); + } else { + setCallback(getEntities()->isPlayerPosition(kCarRedSleeping, 1) ? 2 : 3); + setup_function13(true, kEntityPlayer); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + + case 9: + goto label_callback_9; + + case 10: + params->param1 = 1; + goto label_callback_10; + + case 11: + getAction()->playAnimation(kEventCoudertAskTylerCompartment); + getEntities()->drawSequenceRight(kEntityCoudert, ENTITY_PARAM(0, 2) ? "627A" : "627D"); + getScenes()->loadSceneFromItemPosition(kItem5); + + ENTITY_PARAM(0, 1) = 0; + + getScenes()->loadSceneFromPosition(kCarRedSleeping, 25); + + setCallback(12); + setup_callbackActionOnDirection(); + break; + + case 12: + getEntities()->drawSequenceLeft(kEntityCoudert, ENTITY_PARAM(0, 2) ? "627B" : "627E"); + break; + + case 14: + setCallback(15); + setup_function18(); + break; + } + break; + + case kAction168253822: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + getData()->inventoryItem = kItemNone; + getSound()->playSound(kEntityCoudert, "JAC1120"); + + setCallback(14); + setup_bloodJacket("697D"); + } + break; + + case kAction225358684: + if (!ENTITY_PARAM(0, 1)) { + getData()->inventoryItem = kItemNone; + setCallback(16); + setup_function30((ObjectIndex)savepoint.param.intValue); + } + break; + + case kAction225932896: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) + getSavePoints()->push(kEntityCoudert, kEntityFrancois, kAction205346192); + break; + + case kAction305159806: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + getData()->inventoryItem = kItemNone; + setCallback(17); + setup_function31(savepoint.param.intValue); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Coudert, function41) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_visitCompartmentA(); + break; + + case 2: + setCallback(3); + setup_function33(); + break; + + case 3: + setCallback(4); + setup_visitCompartmentB(); + break; + + case 4: + setCallback(5); + setup_function33(); + break; + + case 5: + setCallback(6); + setup_function27(); + break; + + case 6: + getSavePoints()->push(kEntityCoudert, kEntityRebecca, kAction285528346); + + setCallback(7); + setup_function33(); + break; + + case 7: + setCallback(8); + setup_function26(); + break; + + case 8: + setCallback(9); + setup_function33(); + break; + + case 9: + setCallback(10); + setup_function25(); + break; + + case 10: + setCallback(11); + setup_function33(); + break; + + case 11: + setCallback(12); + setup_function23(); + break; + + case 12: + setCallback(13); + setup_function33(); + break; + + case 13: + setCallback(14); + setup_function22(); + break; + + case 14: + setCallback(15); + setup_function33(); + break; + + case 15: + setCallback(16); + setup_function21(); + break; + + case 16: + setCallback(17); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 17: + setCallback(18); + setup_function18(); + break; + + case 18: + getSavePoints()->push(kEntityCoudert, kEntityMilos, kAction208228224); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Coudert, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function18(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCoudert); + + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 5) = 0; + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 8) = 0; + + ENTITY_PARAM(2, 4) = 0; + + getObjects()->updateLocation2(kObject111, kObjectLocation5); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function43(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, Coudert, function43) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(0, 8)) { + setCallback(1); + setup_function15(true); + break; + } + +label_callback1: + if (!ENTITY_PARAM(1, 1)) { + setCallback(2); + setup_function15(false); + break; + } + +label_callback2: + if (ENTITY_PARAM(0, 3)) { + setCallback(3); + setup_function14(kEntityVerges); + } + break; + + case kAction11: + if (!ENTITY_PARAM(2, 1)) { + setCallback(4); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2); + } + break; + + case kActionDrawScene: + if (ENTITY_PARAM(2, 1)) + break; + + if (getEntities()->isPlayerPosition(kCarRedSleeping, 1)) { + setCallback(5); + setup_function13(true, kEntityPlayer); + + } else if (getEntities()->isPlayerPosition(kCarRedSleeping, 23)) { + setCallback(6); + setup_function13(false, kEntityPlayer); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 7: + setCallback(8); + setup_function18(); + break; + } + break; + + case kAction225358684: + if (!ENTITY_PARAM(0, 1)) { + setCallback(9); + setup_function30((ObjectIndex)savepoint.param.intValue); + } + break; + + case kAction226078300: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + getSound()->playSound(kEntityCoudert, "JAC2020"); + + setCallback(7); + setup_bloodJacket("697D"); + } + break; + + case kAction305159806: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(10); + setup_function31(savepoint.param.intValue); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Coudert, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function18(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCoudert); + + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 5) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 8) = 0; + + ENTITY_PARAM(2, 4) = 0; + ENTITY_PARAM(2, 5) = 0; + + getObjects()->updateLocation2(kObject111, kObjectLocation6); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function45(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, Coudert, function45) + error("Coudert: callback function 45 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Coudert, function46) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Vf"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentF, true); + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction253868128); + + setCallback(3); + setup_playSound("LIB012"); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wf"); + + setCallback(4); + setup_playSound("Ann1016A"); + break; + + case 4: + setCallback(5); + setup_playSound("Ann4150"); + break; + + case 5: + getSound()->playSound(kEntityCoudert, "Ann3121"); + + setCallback(6); + setup_enterExitCompartment("629Bf", kObjectCompartmentF); + break; + + case 6: + getEntities()->drawSequenceLeft(kEntityCoudert, "629Cf"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentF, true); + // Fallback to next case + + case 7: + if (getSound()->isBuffered(kEntityCoudert)) { + setCallback(7); + setup_updateFromTime(75); + } else { + setCallback(8); + setup_playSound("Ann3122"); + } + break; + + case 8: + getSound()->playSound(kEntityCoudert, "Ann3123"); + + setCallback(9); + setup_updateFromTicks(75); + break; + + case 9: + setCallback(10); + setup_enterExitCompartment("629Ff", kObjectCompartmentF); + break; + + case 10: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentF, true); + ENTITY_PARAM(1, 3) = 0; + + setCallback(11); + setup_function35(true); + break; + + case 11: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(47, Coudert, function47, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("627Xf", kObjectCompartmentF); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wf"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentF); + // Fallback to next case + + case 4: + if (getSound()->isBuffered(kEntityCoudert)) { + setCallback(4); + setup_updateFromTime(225); + } else { + setCallback(5); + setup_playSound(params->param1 ? "Ann3149" : "Ann3147a"); + } + break; + + case 5: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentF, true); + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction157894320); + + setCallback(6); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 6: + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + + setCallback(7); + setup_function18(); + break; + + case 7: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Coudert, function48) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSound()->playSound(kEntityCoudert, "Ann3148A"); + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + getSound()->playSound(kEntityCoudert, rnd(2) ? "Ann3148B" : "Ann3148"); + setCallback(3); + setup_enterExitCompartment("627Xf", kObjectCompartmentF); + break; + + case 3: + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction192063264); + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 4: + ENTITY_PARAM(1, 8) = 0; + setCallback(5); + setup_function18(); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(49, Coudert, function49) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_7500); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("627Vb", kObjectCompartmentB); + break; + + case 3: + if (getEntities()->isInsideCompartment(kEntityTatiana, kCarRedSleeping, kPosition_7500)) { + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wb"); + + setCallback(4); + setup_playSound("Jac3006"); + } else { + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wb"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentB, true); + + setCallback(8); + setup_playSound("LIB012"); + } + break; + + case 4: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB, true); + + setCallback(5); + setup_enterExitCompartment("627Zb", kObjectCompartmentB); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(6); + setup_playSound("Jac3006A"); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("697Ab", kObjectCompartmentB); + break; + + case 7: + getData()->location = kLocationOutsideCompartment; + + setCallback(10); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 8: + setCallback(9); + setup_updateFromTime(150); + break; + + case 9: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB, true); + + setCallback(10); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 10: + getSavePoints()->push(kEntityCoudert, kEntityMmeBoutarel, kAction242526416); + ENTITY_PARAM(2, 4) = 0; + ENTITY_PARAM(2, 5) = 1; + + setCallback(11); + setup_function18(); + break; + + case 11: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(50, Coudert, function50) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Me"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentE, true); + + setCallback(3); + setup_playSound("LIB012"); + break; + + case 3: + if (!getEntities()->isInsideCompartment(kEntityRebecca, kCarRedSleeping, kPosition_4840)) { + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentE, true); + + setCallback(8); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + } else { + getEntities()->drawSequenceLeft(kEntityCoudert, "627Ne"); + + setCallback(4); + setup_playSound("Jac3005"); + } + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("627Re", kObjectCompartmentE); + break; + + case 5: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentE, true); + + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityCoudert); + + setCallback(6); + setup_playSound("Jac3005A"); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("627Se", kObjectCompartmentE); + break; + + case 7: + getData()->location = kLocationOutsideCompartment; + + setCallback(8); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 8: + ENTITY_PARAM(2, 5) = 0; + + setCallback(9); + setup_function18(); + break; + + case 9: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(51, Coudert, function51) + error("Coudert: callback function 51 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(52, Coudert, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function18(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCoudert); + + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 5) = 0; + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 8) = 0; + + ENTITY_PARAM(2, 3) = 0; + ENTITY_PARAM(2, 4) = 0; + + getObjects()->updateLocation2(kObject111, kObjectLocation10); + break; + + case kActionCallback: + if (getCallback() == 1) { + ENTITY_PARAM(1, 2) = 1; + setup_function53(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(53, Coudert, function53) + error("Coudert: callback function 53 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(54, Coudert, function54) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getEntities()->hasValidFrame(kEntityCoudert)) { + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_540); + } else { + getData()->car = kCarLocomotive; + getData()->entityPosition = kPosition_540; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityCoudert); + getData()->car = kCarLocomotive; + break; + + case 2: + setCallback(3); + setup_function18(); + break; + + case 3: + CALLBACK_ACTION(); + break; + } + break; + + case kAction191001984: + getData()->car = kCarRedSleeping; + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_1500); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(55, Coudert, function55) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_playSound("LIB070"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function16(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Wf"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentF, true); + + setCallback(4); + setup_playSound("Ann4150A"); + break; + + case 4: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentF, true); + getSavePoints()->push(kEntityCoudert, kEntityAnna, kAction219971920); + getSavePoints()->push(kEntityCoudert, kEntityPascale, kAction101824388); + + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 5: + getEntities()->clearSequences(kEntityCoudert); + getSavePoints()->push(kEntityCoudert, kEntityPascale, kAction136059947); + break; + + case 6: + ENTITY_PARAM(1, 2) = 0; + + setCallback(7); + setup_function18(); + break; + + case 7: + CALLBACK_ACTION(); + break; + } + break; + + case kAction123712592: + setCallback(6); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(56, Coudert, function56) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function21(); + break; + + case 2: + setCallback(3); + setup_function33(); + break; + + case 3: + setCallback(4); + setup_function22(); + break; + + case 4: + setCallback(5); + setup_function33(); + break; + + case 5: + setCallback(6); + setup_visitCompartmentF(); + break; + + case 6: + setCallback(7); + setup_function33(); + break; + + case 7: + setCallback(8); + setup_function25(); + break; + + case 8: + setCallback(9); + setup_function33(); + break; + + case 9: + setCallback(10); + setup_function26(); + break; + + case 10: + setCallback(11); + setup_function33(); + break; + + case 11: + setCallback(12); + setup_function27(); + break; + + case 12: + setCallback(13); + setup_function33(); + break; + + case 13: + setCallback(14); + setup_visitCompartmentB(); + break; + + case 14: + setCallback(15); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 15: + setCallback(16); + setup_function18(); + break; + + case 16: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(57, Coudert, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityCoudert); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(58, Coudert, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function59(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(59, Coudert, function59) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + getSound()->playSound(kEntityCoudert, "Jac5010"); // Situation is under control, please remain in your compartment + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); + setup_function60(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(60, Coudert, function60) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function61(); + break; + + case kAction155991520: + setCallback(1); + setup_updateFromTime(225); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(61, Coudert, function61) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_2088; + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("627Me", kObjectCompartmentE); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityCoudert, "627Ne"); + getEntities()->enterCompartment(kEntityCoudert, kObjectCompartmentE, true); + + setCallback(3); + setup_updateFromTime(75); + break; + + case 3: + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentE, true); + + setCallback(4); + setup_enterExitCompartment("627Re", kObjectCompartmentE); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityCoudert); + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(5); + setup_playSound("Reb5010"); + break; + + case 5: + setCallback(6); + setup_enterExitCompartment("627Se", kObjectCompartmentE); + break; + + case 6: + getSavePoints()->push(kEntityCoudert, kEntityRebecca, kAction155604840); + + getData()->location = kLocationOutsideCompartment; + + setCallback(7); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment("627Zh", kObjectCompartmentH); + break; + + case 8: + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityCoudert); + getSavePoints()->push(kEntityCoudert, kEntityPascale, kAction169750080); + + setup_function62(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(62, Coudert, function62) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM(params->param4, getState()->timeTicks, 75); + + params->param1 = 0; + params->param2 = 1; + + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param4 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (params->param1) { + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorNormal); + params->param1 = 0; + + setCallback(1); + setup_playSound(getSound()->justCheckingCath()); + } else { + setCallback(savepoint.action == kActionKnock ? 2 : 3); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param1 || params->param2) { + params->param1 = 0; + params->param2 = 0; + params->param3 = 0; + + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case 2: + case 3: + ++params->param3; + + if (params->param3 == 1 || params->param2) { + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorNormal); + setCallback(params->param3 == 1 ? 4 : 5); + setup_playSound(params->param3 == 1 ? "Jac5002" : "Jac5002A"); + } + break; + + case 4: + params->param1 = 1; + getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorTalk, kCursorNormal); + break; + + case 5: + params->param2 = 1; + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(63, Coudert) + + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Coudert::visitCompartment(const SavePoint &savepoint, EntityPosition position, const char* seq1, ObjectIndex compartment, const char* seq2, const char* seq3, EntityPosition sittingPosition, ObjectIndex object, const char* seq4) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, position); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment(seq1, compartment); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityCoudert, seq2); + getEntities()->enterCompartment(kEntityCoudert, compartment, true); + + setCallback(3); + setup_updateFromTime(150); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment2(seq3, compartment, position, sittingPosition); + break; + + case 4: + getEntities()->exitCompartment(kEntityCoudert, compartment, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityCoudert); + + setCallback(5); + setup_function20(compartment, object); + break; + + case 5: + setCallback(6); + setup_enterExitCompartment(seq4, compartment); + break; + + case 6: + getData()->location = kLocationOutsideCompartment; + CALLBACK_ACTION(); + break; + } + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/coudert.h b/engines/lastexpress/entities/coudert.h new file mode 100644 index 0000000000..e86e519385 --- /dev/null +++ b/engines/lastexpress/entities/coudert.h @@ -0,0 +1,229 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_COUDERT_H +#define LASTEXPRESS_COUDERT_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Coudert : public Entity { +public: + Coudert(LastExpressEngine *engine); + ~Coudert() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Handle meeting Coudert with the blooded jacket + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(bloodJacket, const char *sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + * @param entityPosition1 The entity position 1 + * @param entityPosition2 The entity position 2 + */ + DECLARE_FUNCTION_4(enterExitCompartment2, const char* sequence, ObjectIndex compartment, EntityPosition entityPosition1, EntityPosition entityPosition2) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param savepoint The savepoint + * - the sound filename + */ + DECLARE_FUNCTION_NOSETUP(playSound16) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates parameter 2 using ticks value + * + * @param ticks The number of ticks to add + */ + DECLARE_FUNCTION_1(updateFromTicks, uint32 ticks) + + DECLARE_FUNCTION_1(excuseMe, EntityIndex entity) + DECLARE_FUNCTION_2(function13, bool, EntityIndex entity) + DECLARE_FUNCTION_1(function14, EntityIndex entity) + DECLARE_FUNCTION_1(function15, bool) + DECLARE_FUNCTION(function16) + DECLARE_FUNCTION_1(function17, bool) + DECLARE_FUNCTION(function18) + DECLARE_FUNCTION_1(function19, bool) + + /** + * ??? + * + * @param object1 The first object index + * @param object2 The second object index + */ + DECLARE_FUNCTION_2(function20, ObjectIndex object1, ObjectIndex object2) + + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(visitCompartmentF) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(visitCompartmentB) + DECLARE_FUNCTION(visitCompartmentA) + + /** + * ??? + * + * @param compartment The compartment + */ + DECLARE_FUNCTION_1(function30, ObjectIndex compartment) + + DECLARE_FUNCTION_1(function31, uint32) + DECLARE_FUNCTION(function32) + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION_1(function34, bool) + DECLARE_FUNCTION_1(function35, bool) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + DECLARE_FUNCTION(function39) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function41) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + DECLARE_FUNCTION(function43) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + DECLARE_FUNCTION(function45) + DECLARE_FUNCTION(function46) + DECLARE_FUNCTION_1(function47, bool) + DECLARE_FUNCTION(function48) + DECLARE_FUNCTION(function49) + DECLARE_FUNCTION(function50) + DECLARE_FUNCTION(function51) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + DECLARE_FUNCTION(function53) + DECLARE_FUNCTION(function54) + DECLARE_FUNCTION(function55) + DECLARE_FUNCTION(function56) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function59) + DECLARE_FUNCTION(function60) + DECLARE_FUNCTION(function61) + DECLARE_FUNCTION(function62) + + DECLARE_NULL_FUNCTION() + +private: + void visitCompartment(const SavePoint &savepoint, EntityPosition position, const char* seq1, ObjectIndex compartment, const char* seq2, const char* seq3, EntityPosition sittingPosition, ObjectIndex object, const char* seq4); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_COUDERT_H diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp new file mode 100644 index 0000000000..8400c38737 --- /dev/null +++ b/engines/lastexpress/entities/entity.cpp @@ -0,0 +1,434 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/entity.h" + +#include "lastexpress/entities/entity_intern.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/state.h" +#include "lastexpress/game/savegame.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// EntityData +////////////////////////////////////////////////////////////////////////// +EntityData::EntityParameters *EntityData::getParameters(uint callback, byte index) const { + if (callback >= 9) + error("EntityData::getParameters: invalid callback value (was: %d, max: 9)", callback); + + if (index >= 4) + error("EntityData::getParameters: invalid index value (was: %d, max: 4)", index); + + return _parameters[callback].parameters[index]; +} + +int EntityData::getCallback(uint callback) const { + if (callback >= 16) + error("EntityData::getParameters: invalid callback value (was: %d, max: 16)", callback); + + return _data.callbacks[callback]; +} + +void EntityData::setCallback(uint callback, byte index) { + if (callback >= 16) + error("EntityData::getParameters: invalid callback value (was: %d, max: 16)", callback); + + _data.callbacks[callback] = index; +} + +void EntityData::updateParameters(uint32 index) const { + if (index < 8) + getParameters(8, 0)->update(index); + else if (index < 16) + getParameters(8, 1)->update(index - 8); + else if (index < 24) + getParameters(8, 2)->update(index - 16); + else if (index < 32) + getParameters(8, 3)->update(index - 24); + else + error("EntityData::updateParameters: invalid param index to update (was:%d, max:32)!", index); +} + +void EntityData::saveLoadWithSerializer(Common::Serializer &) { + error("EntityData::saveLoadWithSerializer: not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +// Entity +////////////////////////////////////////////////////////////////////////// +Entity::Entity(LastExpressEngine *engine, EntityIndex index) : _engine(engine), _entityIndex(index) { + _data = new EntityData(); + + // Add first empty entry to callbacks array + _callbacks.push_back(NULL); +} + +Entity::~Entity() { + for (uint i = 0; i < _callbacks.size(); i++) + delete _callbacks[i]; + + delete _data; + + // Zero-out passed pointers + _engine = NULL; +} + +void Entity::setup(ChapterIndex index) { + switch(index) { + case kChapterAll: + getSavePoints()->setCallback(_entityIndex, _callbacks[_data->getCurrentCallback()]); + break; + + case kChapter1: + setup_chapter1(); + break; + + case kChapter2: + setup_chapter2(); + break; + + case kChapter3: + setup_chapter3(); + break; + + case kChapter4: + setup_chapter4(); + break; + + case kChapter5: + setup_chapter5(); + break; + + default: + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// Shared functions +////////////////////////////////////////////////////////////////////////// + +void Entity::reset(const SavePoint &savepoint, bool resetClothes, bool resetItem) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + switch (savepoint.action) { + default: + break; + + case kAction1: + if (resetClothes) { + // Select next available clothes + getData()->clothes = (ClothesIndex)(getData()->clothes + 1); + if (getData()->clothes > kClothes3) + getData()->clothes = kClothesDefault; + } + break; + + case kActionNone: + if (getEntities()->updateEntity(_entityIndex, kCarGreenSleeping, (EntityPosition)params->param1)) + params->param1 = (params->param1 == 10000) ? 0 : 10000; + break; + + case kActionDefault: + getData()->entityPosition = kPositionNone; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + + if (resetItem) + getData()->inventoryItem = kItemInvalid; + + params->param1 = 10000; + break; + } +} + +void Entity::savegame(const SavePoint &savepoint) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + switch (savepoint.action) { + default: + break; + + case kActionNone: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getSaveLoad()->saveGame((SavegameType)params->param1, _entityIndex, (EventIndex)params->param2); + CALLBACK_ACTION(); + break; + } +} + +void Entity::playSound(const SavePoint &savepoint, bool resetItem, SoundManager::FlagType flag) { + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) + + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + CALLBACK_ACTION(); + break; + + case kActionDefault: + if (resetItem) + getData()->inventoryItem = kItemNone; + + getSound()->playSound(_entityIndex, (char *)¶ms->seq1, flag); + break; + } +} + +void Entity::draw(const SavePoint &savepoint, bool handleExcuseMe) { + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) + + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + if (handleExcuseMe && !params->param4) { + getSound()->excuseMe(_entityIndex); + params->param4 = 1; + } + break; + + case kActionDefault: + getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1); + break; + } +} + +void Entity::draw2(const SavePoint &savepoint) { + EXPOSE_PARAMS(EntityData::EntityParametersSSII) + + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1); + getEntities()->drawSequenceRight((EntityIndex)params->param7, (char *)¶ms->seq2); + break; + } +} + +void Entity::updateFromTicks(const SavePoint &savepoint) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->timeTicks, params->param1) + CALLBACK_ACTION(); + break; + } +} + +void Entity::updateFromTime(const SavePoint &savepoint) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->time, params->param1) + CALLBACK_ACTION(); + break; + } +} + +void Entity::callbackActionOnDirection(const SavePoint &savepoint) { + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionDefault: + if (getData()->direction != kDirectionRight) + CALLBACK_ACTION(); + break; + } +} + +void Entity::callbackActionRestaurantOrSalon(const SavePoint &savepoint) { + switch (savepoint.action) { + default: + break; + + case kActionNone: + case kActionDefault: + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) + CALLBACK_ACTION(); + break; + } +} + +void Entity::updateEntity(const SavePoint &savepoint, bool handleExcuseMe) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + switch (savepoint.action) { + default: + break; + + case kActionExcuseMeCath: + if (handleExcuseMe) + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + if (handleExcuseMe) + getSound()->excuseMe(_entityIndex); + break; + + case kActionNone: + case kActionDefault: + if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + } +} + +void Entity::callSavepoint(const SavePoint &savepoint, bool handleExcuseMe) { + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) + + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + if (!CURRENT_PARAMS(1, 1)) + getSavePoints()->call(_entityIndex, (EntityIndex)params->param4, (ActionIndex)params->param5, (char *)¶ms->seq2); + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + if (handleExcuseMe && !CURRENT_PARAMS(1, 2)) { + getSound()->excuseMe(_entityIndex); + CURRENT_PARAMS(1, 2) = 1; + } + break; + + case kAction10: + if (!CURRENT_PARAMS(1, 1)) { + getSavePoints()->call(_entityIndex, (EntityIndex)params->param4, (ActionIndex)params->param5, (char *)¶ms->seq2); + CURRENT_PARAMS(1, 1) = 1; + } + break; + + case kActionDefault: + getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1); + break; + } +} + +void Entity::enterExitCompartment(const SavePoint &savepoint, EntityPosition position1, EntityPosition position2, CarIndex car, ObjectIndex compartment, bool alternate, bool updateLocation) { + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) + + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->exitCompartment(_entityIndex, (ObjectIndex)params->param4); + if (position1) + getData()->entityPosition = position1; + + if (updateLocation) + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1); + getEntities()->enterCompartment(_entityIndex, (ObjectIndex)params->param4); + + if (position1) { + getData()->location = kLocationInsideCompartment; + + if (getEntities()->isInsideCompartment(kEntityPlayer, car, position1) || getEntities()->isInsideCompartment(kEntityPlayer, car, position2)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(compartment, alternate); + } + } + break; + } +} + +void Entity::updatePosition(const SavePoint &savepoint, bool handleExcuseMe) { + EXPOSE_PARAMS(EntityData::EntityParametersSIII) + + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->updatePositionExit(_entityIndex, (CarIndex)params->param4, (Position)params->param5); + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + if (handleExcuseMe && !params->param6) { + getSound()->excuseMe(_entityIndex); + params->param6 = 1; + } + break; + + case kActionDefault: + getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq); + getEntities()->updatePositionEnter(_entityIndex, (CarIndex)params->param4, (Position)params->param5); + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h new file mode 100644 index 0000000000..b0a1ab68ea --- /dev/null +++ b/engines/lastexpress/entities/entity.h @@ -0,0 +1,681 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ENTITY_H +#define LASTEXPRESS_ENTITY_H + +#include "lastexpress/shared.h" + +#include "lastexpress/game/sound.h" + +#include "common/array.h" +#include "common/func.h" +#include "common/serializer.h" + +namespace LastExpress { + +class LastExpressEngine; +class Sequence; +class SequenceFrame; +struct SavePoint; + +class EntityData : Common::Serializable { +public: + + struct EntityParameters { + virtual ~EntityParameters() {} + virtual Common::String toString() = 0; + + virtual void update(uint32 index) = 0; + }; + + struct EntityParametersIIII : EntityParameters { + uint param1; + uint param2; + uint param3; + uint param4; + uint param5; + uint param6; + uint param7; + uint param8; + + EntityParametersIIII() { + param1 = 0; + param2 = 0; + param3 = 0; + param4 = 0; + param5 = 0; + param6 = 0; + param7 = 0; + param8 = 0; + } + + bool hasNonNullParameter() { + return param1 || param2 || param3 || param4 || param5 || param6 || param7 || param8; + } + + Common::String toString() { + return Common::String::printf("IIII: %d %d %d %d %d %d %d %d\n", param1, param2, param3, param4, param5, param6, param7, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersIIII::update: invalid index (was: %d)", index); + + case 0: param1 = 1; break; + case 1: param2 = 1; break; + case 2: param3 = 1; break; + case 3: param4 = 1; break; + case 4: param5 = 1; break; + case 5: param6 = 1; break; + case 6: param7 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersSIII : EntityParameters { + char seq[12]; + uint param4; + uint param5; + uint param6; + uint param7; + uint param8; + + EntityParametersSIII() { + memset(&seq, 0, 12); + param4 = 0; + param5 = 0; + param6 = 0; + param7 = 0; + param8 = 0; + } + + Common::String toString() { + return Common::String::printf("SIII: %s %d %d %d %d %d\n", seq, param4, param5, param6, param7, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersSIII::update: invalid index (was: %d)", index); + + case 3: param4 = 1; break; + case 4: param5 = 1; break; + case 5: param6 = 1; break; + case 6: param7 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersSIIS : EntityParameters { + char seq1[12]; + uint param4; + uint param5; + char seq2[12]; + + EntityParametersSIIS() { + memset(&seq1, 0, 12); + param4 = 0; + param5 = 0; + memset(&seq2, 0, 12); + } + + Common::String toString() { + return Common::String::printf("SIIS: %s %d %d %s\n", seq1, param4, param5, seq2); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersSIIS::update: invalid index (was: %d)", index); + + case 3: param4 = 1; break; + case 4: param5 = 1; break; + } + } + }; + + struct EntityParametersISSI : EntityParameters { + uint param1; + char seq1[12]; + char seq2[12]; + uint param8; + + EntityParametersISSI() { + param1 = 0; + memset(&seq1, 0, 12); + memset(&seq2, 0, 12); + param8 = 0; + } + + Common::String toString() { + return Common::String::printf("ISSI: %d %s %s %d\n", param1, seq1, seq2, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersISSI::update: invalid index (was: %d)", index); + + case 0: param1 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersISII : EntityParameters { + uint param1; + char seq[12]; + uint param5; + uint param6; + uint param7; + uint param8; + + EntityParametersISII() { + param1 = 0; + memset(&seq, 0, 12); + param5 = 0; + param6 = 0; + param7 = 0; + param8 = 0; + } + + Common::String toString() { + return Common::String::printf("ISII: %d %s %d %d %d %d\n", param1, seq, param5, param6, param7, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersISII::update: invalid index (was: %d)", index); + + case 0: param1 = 1; break; + case 4: param5 = 1; break; + case 5: param6 = 1; break; + case 6: param7 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersSSII : EntityParameters { + char seq1[12]; + char seq2[12]; + uint param7; + uint param8; + + EntityParametersSSII() { + memset(&seq1, 0, 12); + memset(&seq2, 0, 12); + param7 = 0; + param8 = 0; + } + + Common::String toString() { + return Common::String::printf("SSII: %s %s %d %d\n", seq1, seq2, param7, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersSSII::update: invalid index (was: %d)", index); + + case 6: param7 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersIISS : EntityParameters { + uint param1; + uint param2; + char seq1[12]; + char seq2[12]; + + EntityParametersIISS() { + param1 = 0; + param2 = 0; + memset(&seq1, 0, 12); + memset(&seq2, 0, 12); + } + + Common::String toString() { + return Common::String::printf("IISS: %d %d %s %s\n", param1, param2, seq1, seq2); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersIISS::update: invalid index (was: %d)", index); + + case 0: param1 = 1; break; + case 1: param2 = 1; break; + } + } + }; + + struct EntityParametersIISI : EntityParameters { + uint param1; + uint param2; + char seq[12]; + uint param6; + uint param7; + uint param8; + + EntityParametersIISI() { + param1 = 0; + param2 = 0; + memset(&seq, 0, 12); + param6 = 0; + param7 = 0; + param8 = 0; + } + + Common::String toString() { + return Common::String::printf("IISI: %d %d %s %d %d %d\n", param1, param2, seq, param6, param7, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersIISI::update: invalid index (was: %d)", index); + + case 0: param1 = 1; break; + case 1: param2 = 1; break; + case 5: param6 = 1; break; + case 6: param7 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersIIIS : EntityParameters { + uint param1; + uint param2; + uint param3; + char seq[12]; + uint param7; + uint param8; + + EntityParametersIIIS() { + param1 = 0; + param2 = 0; + param3 = 0; + memset(&seq, 0, 12); + param7 = 0; + param8 = 0; + } + + Common::String toString() { + return Common::String::printf("IIIS: %d %d %d %s %d %d\n", param1, param2, param3, seq, param7, param8); + } + + void update(uint32 index) { + switch (index) { + default: + error("EntityParametersIIIS::update: invalid index (was: %d)", index); + + case 0: param1 = 1; break; + case 1: param2 = 1; break; + case 2: param3 = 1; break; + case 6: param7 = 1; break; + case 7: param8 = 1; break; + } + } + }; + + struct EntityParametersI5S : EntityParameters { + uint param1; + uint param2; + uint param3; + uint param4; + uint param5; + char seq[12]; + + EntityParametersI5S() { + param1 = 0; + param2 = 0; + param3 = 0; + param4 = 0; + param5 = 0; + memset(&seq, 0, 12); + } + }; + + struct EntityCallParameters { + EntityParameters* parameters[4]; + + EntityCallParameters() { + // We default to int parameters + create<EntityParametersIIII>(); + } + + ~EntityCallParameters() { + clear(); + } + + template <class parameter> + void create() { + for (int i = 0; i < 4; i++) + parameters[i] = new parameter(); + } + + void clear() { + for (int i = 0; i < 4; i++) { + if (parameters[i]) + delete parameters[i]; + parameters[i] = NULL; + } + } + }; + + struct EntityCallData { + byte callbacks[16]; + byte currentCall; + EntityPosition entityPosition; // word + Location location; // word + CarIndex car; // word + byte field_497; + EntityIndex entity; // byte + InventoryItem inventoryItem; // byte + EntityDirection direction; // byte + int16 field_49B; + int16 currentFrame; + int16 currentFrame2; + int16 field_4A1; + int16 field_4A3; + ClothesIndex clothes; // byte + Position position; + CarIndex car2; // byte + bool doProcessEntity; // byte + bool field_4A9; // byte + bool field_4AA; // byte + EntityDirection directionSwitch; + Common::String sequenceName; // char[13] + Common::String sequenceName2; // char[13] + Common::String sequenceNamePrefix; // char[7] + Common::String sequenceNameCopy; // char[13] + SequenceFrame *frame; + SequenceFrame *frame1; + Sequence *sequence; + Sequence *sequence2; + Sequence *sequence3; + + /** + * Default constructor. + */ + EntityCallData() { + memset(&callbacks, 0, 16 * sizeof(byte)); + currentCall = 0; + entityPosition = kPositionNone; + location = kLocationOutsideCompartment; + car = kCarNone; + field_497 = 0; + entity = kEntityPlayer; + inventoryItem = kItemNone; + direction = kDirectionNone; + field_49B = 0; + currentFrame = 0; + currentFrame2 = 0; + field_4A1 = 0; + field_4A3 = 30; + clothes = kClothesDefault; + position = 0; + car2 = kCarNone; + doProcessEntity = false; + field_4A9 = false; + field_4AA = false; + directionSwitch = kDirectionNone; + frame = NULL; + frame1 = NULL; + sequence = NULL; + sequence2 = NULL; + sequence3 = NULL; + } + + /** + * Convert this object into a string representation. + * + * @return A string representation of this object. + */ + Common::String toString() { + Common::String str = ""; + + str += Common::String::printf("Entity position: %d - Location: %d - Car: %d\n", entityPosition, location, car); + str += Common::String::printf("Entity: %d - Item: %d - Direction: %d\n", entity, inventoryItem, direction); + str += Common::String::printf("Clothes: %d - Position: %d - Direction switch: %d\n", clothes, position, directionSwitch); + str += "\n"; + str += Common::String::printf("field_497: %02d - field_49B: %i - field_4A1: %i\n", field_497, field_49B, field_4A1); + str += Common::String::printf("field_4A9: %02d - field_4AA: %i - Car 2: %d\n", field_4A9, field_4AA, car2); + str += "\n"; + str += "Sequence: " + sequenceName + " - Sequence 2: " + sequenceName2 + "\n"; + str += "Sequence prefix: " + sequenceNamePrefix + " - Sequence copy: " + sequenceNameCopy + "\n"; + str += Common::String::printf("Current frame: %i - Current frame 2: %i - Process entity: %d\n", currentFrame, currentFrame2, doProcessEntity); + str += "\n"; + str += Common::String::printf("Current call: %d\n", currentCall); + str += Common::String::printf("Functions: %d %d %d %d %d %d %d %d\n", callbacks[0], callbacks[1], callbacks[2], callbacks[3], callbacks[4], callbacks[5], callbacks[6], callbacks[7]); + str += Common::String::printf("Callbacks: %d %d %d %d %d %d %d %d\n", callbacks[8], callbacks[9], callbacks[10], callbacks[11], callbacks[12], callbacks[13], callbacks[14], callbacks[15]); + + return str; + } + }; + + EntityData() {} + + template <class parameter> + void resetCurrentParameters() { + _parameters[_data.currentCall].clear(); + _parameters[_data.currentCall].create<parameter>(); + } + + EntityCallData *getCallData() { return &_data; } + + EntityParameters *getParameters(uint callback, byte index) const; + EntityParameters *getCurrentParameters(byte index = 0) { return getParameters(_data.currentCall, index); } + + int getCallback(uint callback) const; + int getCurrentCallback() { return getCallback(_data.currentCall); } + void setCallback(uint callback, byte index); + void setCurrentCallback(uint index) { setCallback(_data.currentCall, index); } + + void updateParameters(uint32 index) const; + + // Serializable + void saveLoadWithSerializer(Common::Serializer &ser); + +private: + + EntityCallData _data; + EntityCallParameters _parameters[9]; +}; + +class Entity : Common::Serializable { +public: + + typedef Common::Functor1<const SavePoint&, void> Callback; + + Entity(LastExpressEngine *engine, EntityIndex index); + virtual ~Entity(); + + // Accessors + EntityData *getParamData() { return _data; } + EntityData::EntityCallData *getData() { return _data->getCallData(); } + + // Callbacks + int getCallback() { return _data->getCallback(_data->getCallData()->currentCall + 8); } + void setCallback(byte index) { _data->setCallback(_data->getCallData()->currentCall + 8, index); getData()->currentCall++; } + + // Setup + void setup(ChapterIndex index); + + virtual void setup_chapter1() = 0; + virtual void setup_chapter2() = 0; + virtual void setup_chapter3() = 0; + virtual void setup_chapter4() = 0; + virtual void setup_chapter5() = 0; + + // Serializable + void saveLoadWithSerializer(Common::Serializer &ser) { _data->saveLoadWithSerializer(ser); } + + void nullfunction(const SavePoint &savepoint) {} + +protected: + LastExpressEngine* _engine; + + EntityIndex _entityIndex; + EntityData *_data; + Common::Array<Callback *> _callbacks; + + /** + * Saves the game + * + * @param savepoint The savepoint + * - SavegameType + * - EventIndex + */ + void savegame(const SavePoint &savepoint); + + /** + * Play sound + * + * @param savepoint The savepoint + * - Sound filename + * @param resetItem true to reset item. + * @param flag sound flag + */ + void playSound(const SavePoint &savepoint, bool resetItem = false, SoundManager::FlagType flag = SoundManager::kFlagInvalid); + + /** + * Draws the entity + * + * @param savepoint The savepoint + * - Sequence + * - ExcuseMe flag + * @param handleExcuseMe true to handle excuseMeCath action + */ + void draw(const SavePoint &savepoint, bool handleExcuseMe = false); + + /** + * Draws the entity along with another one + * + * @param savepoint The savepoint. + * - Sequence 1 + * - Sequence 2 + * - EntityIndex + */ + void draw2(const SavePoint &savepoint); + + /** + * Updates parameter 2 using ticks value + * + * @param savepoint The savepoint + * - Number of ticks to add + */ + void updateFromTicks(const SavePoint &savepoint); + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint. + * - Time to add + */ + void updateFromTime(const SavePoint &savepoint); + + /** + * Resets an entity + * + * @param savepoint The savepoint. + * @param resetClothes true to reset clothes. + * @param resetItem true to reset inventoryItem to kItemInvalid + */ + void reset(const SavePoint &savepoint, bool resetClothes = false, bool resetItem = false); + + /** + * Process callback action when the entity direction is not kDirectionRight + * + * @param savepoint The savepoint. + */ + void callbackActionOnDirection(const SavePoint &savepoint); + + /** + * Process callback action when somebody is standing in the restaurant or salon. + * + * @param savepoint The savepoint. + */ + void callbackActionRestaurantOrSalon(const SavePoint &savepoint); + + /** + * Updates the entity + * + * @param savepoint The savepoint. + * - CarIndex + * - EntityPosition + * @param handleExcuseMe true to handle the kActionExcuseMe/kActionExcuseMeCath actions. + */ + void updateEntity(const SavePoint &savepoint, bool handleExcuseMe = false); + + /** + * Call a specific savepoint (or draw sequence in default case) + * + * @param savepoint The savepoint. + * - Sequence to draw in default case + * - EntityIndex + * - ActionIndex + * - Sequence for the savepoint + * @param handleExcuseMe true to handle excuse me. + */ + void callSavepoint(const SavePoint &savepoint, bool handleExcuseMe = false); + + /** + * Handles entering/exiting a compartment. + * + * @param savepoint The savepoint. + * @param position1 The first position. + * @param position2 The second position. + * @param car The car. + * @param compartment The compartment. + * @param alternate true to use the alternate version of SceneManager::loadSceneFromObject() + */ + void enterExitCompartment(const SavePoint &savepoint, EntityPosition position1 = kPositionNone, EntityPosition position2 = kPositionNone, CarIndex car = kCarNone, ObjectIndex compartment = kObjectNone, bool alternate = false, bool updateLocation = false); + + /** + * Updates the position + * + * @param savepoint The savepoint + * - Sequence name + * - CarIndex + * - Position + * @param handleExcuseMe true to handle excuseMe actions + */ + void updatePosition(const SavePoint &savepoint, bool handleExcuseMe = false); +}; + + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ENTITY_H diff --git a/engines/lastexpress/entities/entity39.cpp b/engines/lastexpress/entities/entity39.cpp new file mode 100644 index 0000000000..6d139094c7 --- /dev/null +++ b/engines/lastexpress/entities/entity39.cpp @@ -0,0 +1,103 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/entity39.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Entity39::Entity39(LastExpressEngine *engine) : Entity(engine, kEntity39) { + ADD_CALLBACK_FUNCTION(Entity39, chapter1); + ADD_CALLBACK_FUNCTION(Entity39, chapter2); + ADD_CALLBACK_FUNCTION(Entity39, chapter3); + ADD_CALLBACK_FUNCTION(Entity39, chapter4); + ADD_CALLBACK_FUNCTION(Entity39, chapter5); + ADD_CALLBACK_FUNCTION(Entity39, process); + + memset(&_sequence, 0, 12); + _counter = 0; +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Entity39, chapter1) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(2, Entity39, chapter2) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Entity39, chapter3) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Entity39, chapter4) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Entity39, chapter5) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Entity39, process) +// TODO: _sequence & counter do not seem to be touched anywhere else in the code :( + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->drawSequenceRight(kEntity39, (char *)&_sequence); + break; + + case kActionNone: + getData()->car = getEntityData(kEntityPlayer)->car; + + if (*_sequence && !_counter) { + _counter++; + getEntities()->drawSequenceRight(kEntity39, (char *)&_sequence); + } + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/entity39.h b/engines/lastexpress/entities/entity39.h new file mode 100644 index 0000000000..652dbd139e --- /dev/null +++ b/engines/lastexpress/entities/entity39.h @@ -0,0 +1,78 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ENTITY39_H +#define LASTEXPRESS_ENTITY39_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Entity39 : public Entity { +public: + Entity39(LastExpressEngine *engine); + ~Entity39() {}; + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Process function + */ + DECLARE_FUNCTION(process) + +private: + char _sequence[12]; + int _counter; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_##define##_H diff --git a/engines/lastexpress/entities/entity_intern.h b/engines/lastexpress/entities/entity_intern.h new file mode 100644 index 0000000000..6442f76b3c --- /dev/null +++ b/engines/lastexpress/entities/entity_intern.h @@ -0,0 +1,577 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_ENTITY_INTERN_H +#define LASTEXPRESS_ENTITY_INTERN_H + +namespace LastExpress { + +#define LOBYTE(w) ((unsigned char)(((unsigned long)(w)) & 0xff)) + +////////////////////////////////////////////////////////////////////////// +// Callbacks +#define ENTITY_CALLBACK(class, name, pointer) \ + Common::Functor1Mem<const SavePoint&, void, class>(pointer, &class::name) + +#define ADD_CALLBACK_FUNCTION(class, name) \ + _callbacks.push_back(new ENTITY_CALLBACK(class, name, this)); + +#define ADD_NULL_FUNCTION() \ + _callbacks.push_back(new ENTITY_CALLBACK(Entity, nullfunction, this)); + +////////////////////////////////////////////////////////////////////////// +// Declaration +////////////////////////////////////////////////////////////////////////// + +#define DECLARE_FUNCTION(name) \ + void setup_##name(); \ + void name(const SavePoint &savepoint); + +#define DECLARE_FUNCTION_1(name, param1) \ + void setup_##name(param1); \ + void name(const SavePoint &savepoint); + +#define DECLARE_FUNCTION_2(name, param1, param2) \ + void setup_##name(param1, param2); \ + void name(const SavePoint &savepoint); + +#define DECLARE_FUNCTION_3(name, param1, param2, param3) \ + void setup_##name(param1, param2, param3); \ + void name(const SavePoint &savepoint); + +#define DECLARE_FUNCTION_4(name, param1, param2, param3, param4) \ + void setup_##name(param1, param2, param3, param4); \ + void name(const SavePoint &savepoint); + +#define DECLARE_FUNCTION_NOSETUP(name) \ + void name(const SavePoint &savepoint); + +#define DECLARE_NULL_FUNCTION() \ + void setup_nullfunction(); + +////////////////////////////////////////////////////////////////////////// +// Setup +////////////////////////////////////////////////////////////////////////// + +#define IMPLEMENT_SETUP(class, callback_class, name, index) \ +void class::setup_##name() { \ + BEGIN_SETUP(callback_class, name, index, EntityData::EntityParametersIIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::setup_" #name "()"); \ + END_SETUP() \ +} + +#define BEGIN_SETUP(class, name, index, type) \ + _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, new ENTITY_CALLBACK(class, name, this)); \ + _data->setCurrentCallback(index); \ + _data->resetCurrentParameters<type>(); + +#define END_SETUP() \ + _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); + + +////////////////////////////////////////////////////////////////////////// +// Implementation +////////////////////////////////////////////////////////////////////////// + +// Expose parameters and check validity +#define EXPOSE_PARAMS(type) \ + type *params = (type*)_data->getCurrentParameters(); \ + if (!params) \ + error("Trying to call an entity function with invalid parameters!"); \ + + +// function signature without setup (we keep the index for consistency but never use it) +#define IMPLEMENT_FUNCTION_NOSETUP(index, class, name) \ + void class::name(const SavePoint &savepoint) { \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(index=" #index ")"); + +// simple setup with no parameters +#define IMPLEMENT_FUNCTION(index, class, name) \ + IMPLEMENT_SETUP(class, class, name, index) \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "() - action: %s", ACTION_NAME(savepoint.action)); + +// nullfunction call +#define IMPLEMENT_NULL_FUNCTION(index, class) \ + IMPLEMENT_SETUP(class, Entity, nullfunction, index) + +// setup with one uint parameter +#define IMPLEMENT_FUNCTION_I(index, class, name, paramType) \ + void class::setup_##name(paramType param1) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersIIII) \ + EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII*)_data->getCurrentParameters(); \ + params->param1 = (unsigned int)param1; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d) - action: %s", params->param1, ACTION_NAME(savepoint.action)); + +// setup with two uint parameters +#define IMPLEMENT_FUNCTION_II(index, class, name, paramType1, paramType2) \ + void class::setup_##name(paramType1 param1, paramType2 param2) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersIIII) \ + EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII*)_data->getCurrentParameters(); \ + params->param1 = param1; \ + params->param2 = param2; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d, %d) - action: %s", params->param1, params->param2, ACTION_NAME(savepoint.action)); + +// setup with three uint parameters +#define IMPLEMENT_FUNCTION_III(index, class, name, paramType1, paramType2, paramType3) \ + void class::setup_##name(paramType1 param1, paramType2 param2, paramType3 param3) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersIIII) \ + EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII*)_data->getCurrentParameters(); \ + params->param1 = param1; \ + params->param2 = param2; \ + params->param3 = param3; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d, %d, %d) - action: %s", params->param1, params->param2, params->param3, ACTION_NAME(savepoint.action)); + +// setup with on char* parameter +#define IMPLEMENT_FUNCTION_S(index, class, name) \ + void class::setup_##name(const char* seq1) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSIIS) \ + EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s) - action: %s", (char *)¶ms->seq1, ACTION_NAME(savepoint.action)); + +// setup with on char* parameter and one uint +#define IMPLEMENT_FUNCTION_SI(index, class, name, paramType2) \ + void class::setup_##name(const char* seq1, paramType2 param4) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSIIS) \ + EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + params->param4 = param4; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %d) - action: %s", (char *)¶ms->seq1, params->param4, ACTION_NAME(savepoint.action)); + +// setup with on char* parameter and two uints +#define IMPLEMENT_FUNCTION_SII(index, class, name, paramType2, paramType3) \ + void class::setup_##name(const char* seq1, paramType2 param4, paramType3 param5) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSIIS) \ + EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + params->param4 = param4; \ + params->param5 = param5; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %d, %d) - action: %s", (char *)¶ms->seq1, params->param4, params->param5, ACTION_NAME(savepoint.action)); + +// setup with on char* parameter and three uints +#define IMPLEMENT_FUNCTION_SIII(index, class, name, paramType2, paramType3, paramType4) \ + void class::setup_##name(const char* seq, paramType2 param4, paramType3 param5, paramType4 param6) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSIII) \ + EntityData::EntityParametersSIII *params = (EntityData::EntityParametersSIII*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq, seq, 12); \ + params->param4 = param4; \ + params->param5 = param5; \ + params->param6 = param6; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %d, %d, %d) - action: %s", (char *)¶ms->seq, params->param4, params->param5, params->param6, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_SIIS(index, class, name, paramType2, paramType3) \ + void class::setup_##name(const char* seq1, paramType2 param4, paramType3 param5, const char* seq2) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSIIS) \ + EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + params->param4 = param4; \ + params->param5 = param5; \ + strncpy((char *)¶ms->seq2, seq2, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %d, %d, %s) - action: %s", (char *)¶ms->seq1, params->param4, params->param5, (char *)¶ms->seq2, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_SS(index, class, name) \ + void class::setup_##name(const char* seq1, const char* seq2) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSSII) \ + EntityData::EntityParametersSSII *params = (EntityData::EntityParametersSSII*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + strncpy((char *)¶ms->seq2, seq2, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSSII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %s) - action: %s", (char *)¶ms->seq1, (char *)¶ms->seq2, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_SSI(index, class, name, paramType3) \ + void class::setup_##name(const char* seq1, const char* seq2, paramType3 param7) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersSSII) \ + EntityData::EntityParametersSSII *params = (EntityData::EntityParametersSSII*)_data->getCurrentParameters(); \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + strncpy((char *)¶ms->seq2, seq2, 12); \ + params->param7 = param7; \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersSSII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %s, %d) - action: %s", (char *)¶ms->seq1, (char *)¶ms->seq2, params->param7, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_IS(index, class, name, paramType) \ + void class::setup_##name(paramType param1, const char* seq) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersISII) \ + EntityData::EntityParametersISII *params = (EntityData::EntityParametersISII*)_data->getCurrentParameters(); \ + params->param1 = (unsigned int)param1; \ + strncpy((char *)¶ms->seq, seq, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersISII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d, %s) - action: %s", params->param1, (char *)¶ms->seq, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_ISS(index, class, name, paramType) \ + void class::setup_##name(paramType param1, const char* seq1, const char* seq2) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersISSI) \ + EntityData::EntityParametersISSI *params = (EntityData::EntityParametersISSI*)_data->getCurrentParameters(); \ + params->param1 = param1; \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + strncpy((char *)¶ms->seq2, seq2, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersISSI) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d, %s, %s) - action: %s", params->param1, (char *)¶ms->seq1, (char *)¶ms->seq2, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_IIS(index, class, name, paramType1, paramType2) \ + void class::setup_##name(paramType1 param1, paramType2 param2, const char* seq) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersIISI) \ + EntityData::EntityParametersIISI *params = (EntityData::EntityParametersIISI*)_data->getCurrentParameters(); \ + params->param1 = param1; \ + params->param2 = param2; \ + strncpy((char *)¶ms->seq, seq, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersIISI) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d, %d, %s) - action: %s", params->param1, params->param2, (char *)¶ms->seq, ACTION_NAME(savepoint.action)); + +#define IMPLEMENT_FUNCTION_IISS(index, class, name, paramType1, paramType2) \ + void class::setup_##name(paramType1 param1, paramType2 param2, const char* seq1, const char* seq2) { \ + BEGIN_SETUP(class, name, index, EntityData::EntityParametersIISS) \ + EntityData::EntityParametersIISS *params = (EntityData::EntityParametersIISS*)_data->getCurrentParameters(); \ + params->param1 = param1; \ + params->param2 = param2; \ + strncpy((char *)¶ms->seq1, seq1, 12); \ + strncpy((char *)¶ms->seq2, seq2, 12); \ + END_SETUP() \ + } \ + void class::name(const SavePoint &savepoint) { \ + EXPOSE_PARAMS(EntityData::EntityParametersIISS) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%d, %d, %s, %s) - action: %s", params->param1, params->param2, (char *)¶ms->seq1, (char *)¶ms->seq2, ACTION_NAME(savepoint.action)); + + +////////////////////////////////////////////////////////////////////////// +// Misc +////////////////////////////////////////////////////////////////////////// +#define RESET_ENTITY_STATE(entity, class, function) \ + getEntities()->resetState(entity); \ + ((class*)getEntities()->get(entity))->function(); + +////////////////////////////////////////////////////////////////////////// +// Parameters macros (for default IIII parameters) +////////////////////////////////////////////////////////////////////////// +#define CURRENT_PARAMS(index, id) \ + ((EntityData::EntityParametersIIII*)_data->getCurrentParameters(index))->param##id + +#define ENTITY_PARAM(index, id) \ + ((EntityData::EntityParametersIIII*)_data->getParameters(8, index))->param##id + +////////////////////////////////////////////////////////////////////////// +// Time check macros +////////////////////////////////////////////////////////////////////////// +#define TIME_CHECK_CHAPTER1(function) \ + TIME_CHECK(kTimeChapter1, params->param1, function) + +#define TIME_CHECK(timeValue, parameter, function) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + function(); \ + break; \ + } + +#define TIME_CHECK_SAVEPOINT(timeValue, parameter, entity1, entity2, action) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + getSavePoints()->push(entity1, entity2, action); \ + } + +#define TIME_CHECK_CALLBACK(timeValue, parameter, callback, function) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + function(); \ + break; \ + } + +#define TIME_CHECK_CALLBACK_1(timeValue, parameter, callback, function, param1) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + function(param1); \ + break; \ + } + +#define TIME_CHECK_CALLBACK_2(timeValue, parameter, callback, function, param1, param2) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + function(param1, param2); \ + break; \ + } + +#define TIME_CHECK_CALLBACK_3(timeValue, parameter, callback, function, param1, param2, param3) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + function(param1, param2, param3); \ + break; \ + } + +#define TIME_CHECK_CALLBACK_INVENTORY(timeValue, parameter, callback, function) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + getData()->inventoryItem = kItemNone; \ + setCallback(callback); \ + function(); \ + break; \ + } + +#define TIME_CHECK_CALLBACK_ACTION(timeValue, parameter) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + CALLBACK_ACTION(); \ + break; \ + } + +#define TIME_CHECK_SAVEGAME(timeValue, parameter, callback, type, event) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + setup_savegame(type, event); \ + break; \ + } + +#define TIME_CHECK_ENTERSTATION(timeValue, parameter, callback, name, param2) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + setup_enterStation(name, param2); \ + break; \ + } + +#define TIME_CHECK_EXITSTATION(timeValue, parameter, callback, name) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + setup_exitStation(name); \ + break; \ + } + +#define TIME_CHECK_EXITSTATION_2(timeValue, parameter1, parameter2, callback, name) \ + if (getState()->time > timeValue && !parameter1) { \ + parameter1 = 1; \ + parameter2 = 1; \ + setCallback(callback); \ + setup_exitStation(name); \ + break; \ + } + +#define TIME_CHECK_EXITSTATION_0(parameter1, parameter2, callback, name) \ + if (parameter1 && !parameter2) { \ + setCallback(callback); \ + setup_exitStation(name); \ + break; \ + } + +#define TIME_CHECK_PLAYSOUND(timeValue, parameter, callback, sound) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + setCallback(callback); \ + setup_playSound(sound); \ + break; \ + } + +#define TIME_CHECK_PLAYSOUND_UPDATEPOSITION(timeValue, parameter, callback, sound, position) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + getData()->entityPosition = position; \ + setCallback(callback); \ + setup_playSound(sound); \ + break; \ + } + +#define TIME_CHECK_OBJECT(timeValue, parameter, object, location) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + getObjects()->updateLocation2(object, location); \ + } + +#define TIME_CHECK_POSITION(timeValue, parameter, position) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + getData()->entityPosition = position; \ + } + +#define TIME_CHECK_CAR(timeValue, parameter, callback, function) {\ + if ((getState()->time <= timeValue && !getEntities()->isPlayerInCar(kCarGreenSleeping)) || !parameter) \ + parameter = getState()->time + 75; \ + if (getState()->time > timeValue || parameter < getState()->time) { \ + parameter = kTimeInvalid; \ + setCallback(callback); \ + function(); \ + break; \ + } \ +} + +////////////////////////////////////////////////////////////////////////// +// Callback action +////////////////////////////////////////////////////////////////////////// +#define CALLBACK_ACTION() { \ + if (getData()->currentCall == 0) \ + error("CALLBACK_ACTION: currentCall is already 0, cannot proceed!"); \ + getData()->currentCall--; \ + getSavePoints()->setCallback(_entityIndex, _callbacks[_data->getCurrentCallback()]); \ + getSavePoints()->call(_entityIndex, _entityIndex, kActionCallback); \ + } + +////////////////////////////////////////////////////////////////////////// +// Param update +////////////////////////////////////////////////////////////////////////// +#define UPDATE_PARAM(parameter, type, value) { \ + if (!parameter) \ + parameter = type + value; \ + if (parameter >= type) \ + break; \ + parameter = kTimeInvalid; \ +} + +// Todo: replace with UPDATE_PARAM_PROC as appropriate +#define UPDATE_PARAM_GOTO(parameter, type, value, label) { \ + if (!parameter) \ + parameter = type + value; \ + if (parameter >= type) \ + goto label; \ + parameter = kTimeInvalid; \ +} + +// Updating parameter with code inside the check +#define UPDATE_PARAM_PROC(parameter, type, value) \ + if (!parameter) \ + parameter = type + value; \ + if (parameter < type) { \ + parameter = kTimeInvalid; + +#define UPDATE_PARAM_PROC_END } + +// Updating parameter with an added check (and code inside the check) +#define UPDATE_PARAM_CHECK(parameter, type, value) \ + if (!parameter || parameter < type) { \ + if (!parameter) \ + parameter = type + value; + +////////////////////////////////////////////////////////////////////////// +// Compartments +////////////////////////////////////////////////////////////////////////// +// Go from one compartment to another (or the same one if no optional args are passed +#define COMPARTMENT_TO(class, compartmentFrom, positionFrom, sequenceFrom, sequenceTo) \ + switch (savepoint.action) { \ + default: \ + break; \ + case kActionDefault: \ + getData()->entityPosition = positionFrom; \ + setCallback(1); \ + setup_enterExitCompartment(sequenceFrom, compartmentFrom); \ + break; \ + case kActionCallback: \ + switch (getCallback()) { \ + default: \ + break; \ + case 1: \ + setCallback(2); \ + setup_enterExitCompartment(sequenceTo, compartmentFrom); \ + break; \ + case 2: \ + getData()->entityPosition = positionFrom; \ + getEntities()->clearSequences(_entityIndex); \ + CALLBACK_ACTION(); \ + } \ + break; \ + } + +#define COMPARTMENT_FROM_TO(class, compartmentFrom, positionFrom, sequenceFrom, compartmentTo, positionTo, sequenceTo) \ + switch (savepoint.action) { \ + default: \ + break; \ + case kActionDefault: \ + getData()->entityPosition = positionFrom; \ + getData()->location = kLocationOutsideCompartment; \ + setCallback(1); \ + setup_enterExitCompartment(sequenceFrom, compartmentFrom); \ + break; \ + case kActionCallback: \ + switch (getCallback()) { \ + default: \ + break; \ + case 1: \ + setCallback(2); \ + setup_updateEntity(kCarGreenSleeping, positionTo); \ + break; \ + case 2: \ + setCallback(3); \ + setup_enterExitCompartment(sequenceTo, compartmentTo); \ + break; \ + case 3: \ + getData()->location = kLocationInsideCompartment; \ + getEntities()->clearSequences(_entityIndex); \ + CALLBACK_ACTION(); \ + break; \ + } \ + break; \ + } + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ENTITY_INTERN_H diff --git a/engines/lastexpress/entities/francois.cpp b/engines/lastexpress/entities/francois.cpp new file mode 100644 index 0000000000..fd1237f8a3 --- /dev/null +++ b/engines/lastexpress/entities/francois.cpp @@ -0,0 +1,1043 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/francois.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Francois::Francois(LastExpressEngine *engine) : Entity(engine, kEntityFrancois) { + ADD_CALLBACK_FUNCTION(Francois, reset); + ADD_CALLBACK_FUNCTION(Francois, updateFromTime); + ADD_CALLBACK_FUNCTION(Francois, draw); + ADD_CALLBACK_FUNCTION(Francois, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Francois, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Francois, playSound); + ADD_CALLBACK_FUNCTION(Francois, savegame); + ADD_CALLBACK_FUNCTION(Francois, updateEntity); + ADD_CALLBACK_FUNCTION(Francois, function9); + ADD_CALLBACK_FUNCTION(Francois, function10); + ADD_CALLBACK_FUNCTION(Francois, function11); + ADD_CALLBACK_FUNCTION(Francois, function12); + ADD_CALLBACK_FUNCTION(Francois, function13); + ADD_CALLBACK_FUNCTION(Francois, function14); + ADD_CALLBACK_FUNCTION(Francois, function15); + ADD_CALLBACK_FUNCTION(Francois, function16); + ADD_CALLBACK_FUNCTION(Francois, chapter1); + ADD_CALLBACK_FUNCTION(Francois, chapter1Handler); + ADD_CALLBACK_FUNCTION(Francois, function19); + ADD_CALLBACK_FUNCTION(Francois, function20); + ADD_CALLBACK_FUNCTION(Francois, chapter2); + ADD_CALLBACK_FUNCTION(Francois, chapter2Handler); + ADD_CALLBACK_FUNCTION(Francois, function23); + ADD_CALLBACK_FUNCTION(Francois, chapter3); + ADD_CALLBACK_FUNCTION(Francois, chapter3Handler); + ADD_CALLBACK_FUNCTION(Francois, chapter4); + ADD_CALLBACK_FUNCTION(Francois, chapter4Handler); + ADD_CALLBACK_FUNCTION(Francois, chapter5); + ADD_CALLBACK_FUNCTION(Francois, chapter5Handler); + ADD_CALLBACK_FUNCTION(Francois, function30); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Francois, reset) + Entity::reset(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(2, Francois, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Francois, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(4, Francois, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(5, Francois, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_5790, kPosition_6130, kCarRedSleeping, kObjectCompartmentD, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Francois, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, Francois, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Francois, updateEntity, CarIndex, EntityPosition) + error("Francois: callback function 8 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Francois, function9) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getObjects()->get(kObjectCompartmentD).location == kObjectLocation2) { + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction134289824); + setCallback(1); + setup_enterExitCompartment("605Cd", kObjectCompartmentD); + } else { + setCallback(2); + setup_enterExitCompartment("605Ed", kObjectCompartmentD); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Francois, function10) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getObjects()->get(kObjectCompartmentD).location == kObjectLocation2) { + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + setCallback(1); + setup_enterExitCompartment("605Bd", kObjectCompartmentD); + } else { + setCallback(2); + setup_enterExitCompartment("605Dd", kObjectCompartmentD); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction102484312); + break; + + case 2: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityFrancois); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(11, Francois, function11, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getSound()->isBuffered(kEntityFrancois)) { + + UPDATE_PARAM_PROC(CURRENT_PARAMS(1, 1), getState()->timeTicks, params->param6) + switch (rnd(7)) { + default: + break; + + case 0: + getSound()->playSound(kEntityFrancois, "Fra1002A"); + break; + + case 1: + getSound()->playSound(kEntityFrancois, "Fra1002B"); + break; + + case 2: + getSound()->playSound(kEntityFrancois, "Fra1002C"); + break; + + case 3: + getSound()->playSound(kEntityFrancois, "Fra1002D"); + break; + + case 4: + getSound()->playSound(kEntityFrancois, "Fra1002E"); + break; + + case 5: + case 6: + getSound()->playSound(kEntityFrancois, "Fra1002F"); + break; + } + + params->param6 = 15 * rnd(7); + CURRENT_PARAMS(1, 1) = 0; + UPDATE_PARAM_PROC_END + } + + if (!getEntities()->hasValidFrame(kEntityFrancois) || !getEntities()->isWalkingOppositeToPlayer(kEntityFrancois)) + getData()->inventoryItem = kItemNone; + + if (getEntities()->updateEntity(kEntityFrancois, (CarIndex)params->param2, (EntityPosition)params->param3)) { + params->param5 = 0; + + if (params->param3 == kPosition_540) { + params->param2 = (getProgress().chapter == kChapter1) ? kCarRedSleeping : kCarGreenSleeping; + params->param3 = kPosition_9460; + } else { + params->param2 = kCarGreenSleeping; + params->param3 = kPosition_540; + params->param7 = 0; + params->param8 = 0; + + getSavePoints()->push(kEntityFrancois, kEntityCoudert, kAction225932896); + getSavePoints()->push(kEntityFrancois, kEntityMertens, kAction225932896); + } + } + + if (getEntities()->checkDistanceFromPosition(kEntityFrancois, kPosition_2000, 500) && getData()->direction == kDirectionDown) { + + if (getEntities()->isInsideTrainCar(kEntityFrancois, kCarRedSleeping) && params->param8) { + setCallback(2); + setup_draw("605A"); + break; + } + + if (getEntities()->isInsideTrainCar(kEntityFrancois, kCarGreenSleeping) && params->param7) { + setCallback(3); + setup_draw("605A"); + break; + } + } + +label_callback: + if (getProgress().chapter == kChapter1) { + + if (getEntities()->isInsideTrainCar(kEntityFrancois, kCarRedSleeping) + && (getEntities()->hasValidFrame(kEntityFrancois) || params->param1 < getState()->time || params->param4) + && !params->param5 + && getData()->entityPosition < getEntityData(kEntityMmeBoutarel)->entityPosition) { + + if (getData()->direction == kDirectionDown) { + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction202221040); + params->param4 = 1; + params->param5 = 1; + } else if (params->param4 && getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityMmeBoutarel, 1000)) { + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction168986720); + params->param5 = 1; + } + } + } else if (params->param1 < getState()->time) { + getData()->clothes = kClothesDefault; + getData()->field_4A3 = 30; + getData()->inventoryItem = kItemNone; + + if (getSound()->isBuffered(kEntityFrancois)) + getSound()->processEntry(kEntityFrancois); + + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + if (getSound()->isBuffered(kEntityFrancois)) + getSound()->processEntry(kEntityFrancois); + + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventFrancoisWhistle); + break; + + case kActionExcuseMeCath: + if (getProgress().jacket == kJacketGreen + && !getEvent(kEventFrancoisWhistle) + && !getEvent(kEventFrancoisWhistleD) + && !getEvent(kEventFrancoisWhistleNight) + && !getEvent(kEventFrancoisWhistleNightD)) + getData()->inventoryItem = kItemInvalid; + break; + + case kActionDefault: + setCallback(1); + setup_function9(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->clothes = kClothes1; + getData()->field_4A3 = 100; + getData()->inventoryItem = kItemNone; + + params->param2 = kCarGreenSleeping; + params->param3 = kPosition_540; + + getEntities()->updateEntity(kEntityFrancois, kCarGreenSleeping, kPosition_540); + + params->param6 = 15 * rnd(7); + break; + + case 2: + getSavePoints()->push(kEntityFrancois, kEntityCoudert, kAction168253822); + // Fallback to next case + + case 3: + params->param2 = kCarRedSleeping; + params->param3 = kPosition_9460; + params->param5 = 0; + + getData()->entityPosition = kPosition_2088; + + getEntities()->updateEntity(kEntityFrancois, kCarRedSleeping, kPosition_9460); + goto label_callback; + + case 4: + setCallback(5); + setup_function10(); + break; + + case 5: + CALLBACK_ACTION(); + break; + + case 6: + if (getProgress().jacket == kJacketGreen) { + if (isNight()) + getAction()->playAnimation(getData()->entityPosition <= getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisWhistleNightD : kEventFrancoisWhistleNight); + else + getAction()->playAnimation(getData()->entityPosition <= getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisWhistleD : kEventFrancoisWhistleD); + } + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750 * (getData()->direction == kDirectionUp ? -1 : 1)), getData()->direction == kDirectionUp); + break; + } + break; + + case kAction102752636: + getEntities()->clearSequences(kEntityFrancois); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_5790; + getData()->clothes = kClothesDefault; + getData()->field_4A3 = 30; + getData()->inventoryItem = kItemNone; + + CALLBACK_ACTION(); + break; + + case kAction205346192: + if (savepoint.entity2 == kEntityCoudert) + params->param8 = 1; + else if (savepoint.entity2 == kEntityMertens) + params->param7 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Francois, function12) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function9(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 2: + setCallback(3); + setup_updateFromTime(675); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_540); + break; + + case 4: + setCallback(5); + setup_updateFromTime(675); + break; + + case 5: + setCallback(6); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case 6: + setCallback(7); + setup_function10(); + break; + + case 7: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Francois, function13) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function9(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_540); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_4070); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("605Df", kObjectCompartment6); + break; + + case 4: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityFrancois); + + setCallback(5); + setup_playSound("Har2010"); + break; + + case 5: + getSavePoints()->push(kEntityFrancois, kEntityAlouan, kAction189489753); + break; + + case 6: + getData()->location = kLocationOutsideCompartment; + + setCallback(7); + setup_updateEntity(kCarGreenSleeping, kPosition_4840); + break; + + case 7: + if (getInventory()->hasItem(kItemWhistle) || getInventory()->get(kItemWhistle)->location == kObjectLocation3) { + setCallback(10); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + } + + getEntities()->drawSequenceLeft(kEntityFrancois, "605He"); + break; + + case 8: + setCallback(9); + setup_updateFromTime(450); + break; + + case 9: + getEntities()->exitCompartment(kEntityFrancois, kObjectCompartmentE, true); + + setCallback(10); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + + case 10: + setCallback(11); + setup_function10(); + break; + + case 11: + CALLBACK_ACTION(); + break; + } + break; + + case kAction190219584: + setCallback(6); + setup_enterExitCompartment("605Ef", kObjectCompartment6); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IIS(14, Francois, function14, ObjectIndex, EntityPosition) + error("Francois: callback function 14 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Francois, function15) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function9(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getData()->entityPosition >= getEntityData(kEntityPlayer)->entityPosition) { + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_540); + } else { + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + } + break; + + case 2: + case 3: + setCallback(4); + setup_updateFromTime(450); + break; + + case 4: + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case 5: + setCallback(6); + setup_function10(); + break; + + case 6: + setCallback(7); + setup_updateFromTime(900); + break; + + case 7: + if (!getEntities()->isInsideCompartment(kEntityMmeBoutarel, kCarRedSleeping, kPosition_5790)) { + CALLBACK_ACTION(); + break; + } + + setCallback(8); + setup_playSound("Fra2012"); + break; + + case 8: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Francois, function16) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->entityPosition = getEntityData(kEntityBoutarel)->entityPosition; + getData()->location = getEntityData(kEntityBoutarel)->location; + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_enterExitCompartment("605Cd", kObjectCompartmentD); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getData()->entityPosition = kPosition_5890; + + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction101107728); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getEntities()->clearSequences(kEntityFrancois); + getSavePoints()->push(kEntityFrancois, kEntityBoutarel, kAction237889408); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("605Id", kObjectCompartmentD); + break; + + case 4: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction100957716); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + } + break; + + case kAction100901266: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Francois, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Francois, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_1(kTimeParisEpernay, params->param1, 1, setup_function11, kTime1093500); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function19(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Francois, function19) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime1161000, params->param1, 2, setup_function12); + break; + + case kAction101107728: + setCallback(1); + setup_function16(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Francois, function20) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityFrancois); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21 ,Francois, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityFrancois); + + getData()->entityPosition = kPosition_4689; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Francois, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("605Id", kObjectCompartmentD); + break; + + case 2: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getSavePoints()->push(kEntityFrancois, kEntityMmeBoutarel, kAction100957716); + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityFrancois); + setup_function23(); + break; + } + break; + + case kAction100901266: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Francois, function23) + error("Francois: callback function 23 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Francois, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityFrancois); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Francois, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEvent(kEventFrancoisShowBeetle) || getEvent(kEventFrancoisShowBeetleD)) + if (!getEvent(kEventFrancoisTradeWhistle) && !getEvent(kEventFrancoisTradeWhistleD)) + ENTITY_PARAM(0, 1) = 1; + + if (params->param2 && getEntities()->isInsideCompartment(kEntityMmeBoutarel, kCarRedSleeping, kPosition_5790) && !params->param1) { + + if (ENTITY_PARAM(0, 1) && getEntities()->isPlayerInCar(kCarRedSleeping)) { + setCallback(2); + setup_function15(); + break; + } + +label_callback_2: + TIME_CHECK_CALLBACK(kTime2025000, params->param3, 3, setup_function12); + +label_callback_3: + TIME_CHECK_CALLBACK(kTime2052000, params->param4, 4, setup_function12); + +label_callback_4: + TIME_CHECK_CALLBACK(kTime2079000, params->param5, 5, setup_function12); + +label_callback_5: + TIME_CHECK_CALLBACK(kTime2092500, params->param6, 6, setup_function12); + +label_callback_6: + TIME_CHECK_CALLBACK(kTime2173500, params->param7, 7, setup_function12); + +label_callback_7: + TIME_CHECK_CALLBACK(kTime2182500, params->param8, 8, setup_function12); + +label_callback_8: + TIME_CHECK_CALLBACK(kTime2241000, CURRENT_PARAMS(1, 1), 9, setup_function12); + +label_callback_9: + if (!getInventory()->hasItem(kItemWhistle) && getInventory()->get(kItemWhistle)->location != kObjectLocation3) { + TIME_CHECK_CALLBACK_1(kTime2011500, CURRENT_PARAMS(1, 2), 10, setup_function11, kTime2016000); + +label_callback_10: + TIME_CHECK_CALLBACK_1(kTime2115000, CURRENT_PARAMS(1, 3), 11, setup_function11, kTime2119500); + } + +label_callback_11: + if (getInventory()->get(kItemWhistle)->location == kObjectLocation3) { + if (getState()->time <= kTimeEnd) + if (!getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 2000) || !params->param4) + params->param4 = getState()->time + 75; + + if (params->param4 < getState()->time || getState()->time > kTimeEnd) { + params->param4 = kTimeInvalid; + + setCallback(12); + setup_playSound("Fra2010"); + break; + } + +label_callback_12: + TIME_CHECK_CALLBACK_3(kTime2040300, CURRENT_PARAMS(1, 5), 13, setup_function14, kObjectCompartmentE, kPosition_4840, "e"); + +label_callback_13: + TIME_CHECK_CALLBACK_3(kTime2040300, CURRENT_PARAMS(1, 6), 14, setup_function14, kObjectCompartmentF, kPosition_4070, "f"); + +label_callback_14: + TIME_CHECK_CALLBACK_3(kTime2040300, CURRENT_PARAMS(1, 7), 15, setup_function14, kObjectCompartmentB, kPosition_7500, "b"); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param2 = 1; + break; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + + case 9: + goto label_callback_9; + + case 10: + goto label_callback_10; + + case 11: + goto label_callback_11; + + case 12: + getProgress().field_9C = 1; + goto label_callback_12; + + case 13: + goto label_callback_13; + + case 14: + goto label_callback_14; + } + break; + + case kAction101107728: + setCallback(1); + setup_function16(); + break; + + case kAction189872836: + params->param1 = 1; + break; + case kAction190390860: + params->param1 = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Francois, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityFrancois); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Francois, chapter4Handler) + if (savepoint.action == kAction101107728) { + setCallback(1); + setup_function16(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Francois, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityFrancois); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Francois, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) { + if (!getInventory()->hasItem(kItemWhistle) + && getInventory()->get(kItemWhistle)->location != kObjectLocation3) + getInventory()->setLocationAndProcess(kItemWhistle, kObjectLocation1); + + setup_function30(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Francois, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + + case kAction135800432: + setup_nullfunction(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(31, Francois) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/francois.h b/engines/lastexpress/entities/francois.h new file mode 100644 index 0000000000..894a60bc5b --- /dev/null +++ b/engines/lastexpress/entities/francois.h @@ -0,0 +1,170 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_FRANCOIS_H +#define LASTEXPRESS_FRANCOIS_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Francois : public Entity { +public: + Francois(LastExpressEngine *engine); + ~Francois() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION(function9) + DECLARE_FUNCTION(function10) + DECLARE_FUNCTION_1(function11, TimeValue timeValue) + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION(function13) + DECLARE_FUNCTION_3(function14, ObjectIndex compartment, EntityPosition entityPosition, const char *str) + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION(function16) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function23) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function30) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FRANCOIS_H diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp new file mode 100644 index 0000000000..3af85ffdb9 --- /dev/null +++ b/engines/lastexpress/entities/gendarmes.cpp @@ -0,0 +1,491 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/gendarmes.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Gendarmes::Gendarmes(LastExpressEngine *engine) : Entity(engine, kEntityGendarmes) { + ADD_CALLBACK_FUNCTION(Gendarmes, reset); + ADD_CALLBACK_FUNCTION(Gendarmes, chapter1); + ADD_CALLBACK_FUNCTION(Gendarmes, arrestDraw); + ADD_CALLBACK_FUNCTION(Gendarmes, arrestPlaysound); + ADD_CALLBACK_FUNCTION(Gendarmes, arrestPlaysound16); + ADD_CALLBACK_FUNCTION(Gendarmes, arrestCallback); + ADD_CALLBACK_FUNCTION(Gendarmes, savegame); + ADD_CALLBACK_FUNCTION(Gendarmes, arrestUpdateEntity); + ADD_CALLBACK_FUNCTION(Gendarmes, function9); + ADD_CALLBACK_FUNCTION(Gendarmes, function10); + ADD_CALLBACK_FUNCTION(Gendarmes, chapter1Handler); + ADD_CALLBACK_FUNCTION(Gendarmes, function12); + ADD_CALLBACK_FUNCTION(Gendarmes, function13); + ADD_CALLBACK_FUNCTION(Gendarmes, chapter2); + ADD_CALLBACK_FUNCTION(Gendarmes, chapter3); + ADD_CALLBACK_FUNCTION(Gendarmes, chapter4); + ADD_CALLBACK_FUNCTION(Gendarmes, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Gendarmes, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(2, Gendarmes, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->car = kCarNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Gendarmes, arrestDraw) + arrest(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(4, Gendarmes, arrestPlaysound) + arrest(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(5, Gendarmes, arrestPlaysound16) + arrest(savepoint, true, SoundManager::kFlagDefault); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(6, Gendarmes, arrestCallback, TimeValue) + arrest(savepoint, true, SoundManager::kFlagInvalid, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, Gendarmes, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Gendarmes, arrestUpdateEntity, CarIndex, EntityPosition) + arrest(savepoint, true, SoundManager::kFlagInvalid, false, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition) + error("Gendarmes: callback function 9 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param5 || getState()->timeTicks > (uint32)params->param5) { + if (!params->param5) + params->param5 = getState()->timeTicks + 75; + + if (!getEntities()->isOutsideAlexeiWindow() && getObjects()->get((ObjectIndex)params->param3).location != kObjectLocation1) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventGendarmesArrestation); + break; + } + } + + if (!params->param6) + params->param6 = getState()->timeTicks + 150; + + if (params->param6 == 0 || getState()->timeTicks > (uint32)params->param6) { + params->param6 = kTimeInvalid; + + getSound()->playSound(kEntityGendarmes, "POL1046A", SoundManager::kFlagDefault); + } + + UPDATE_PARAM(params->param7, getState()->timeTicks, 300); + + if (!params->param4 && getEntities()->isOutsideAlexeiWindow()) { + getObjects()->update((ObjectIndex)params->param3, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + CALLBACK_ACTION(); + } else { + if (getEntities()->isOutsideAlexeiWindow()) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + getSound()->playSound(kEntityGendarmes, "LIB017", SoundManager::kFlagDefault); + + setCallback(getProgress().jacket == kJacketBlood ? 3 : 4); + setup_savegame(kSavegameTypeEvent, getProgress().jacket == kJacketBlood ? kEventMertensBloodJacket : kEventGendarmesArrestation); + } + break; + + case kActionKnock: + getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).location, kCursorNormal, kCursorNormal); + + setCallback(5); + setup_arrestPlaysound16("POL1046B"); + break; + + case kActionOpenDoor: + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventGendarmesArrestation); + break; + + case kActionDefault: + getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).location, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_arrestPlaysound16("POL1046"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).location, kCursorTalk, kCursorNormal); + break; + + case 2: + getSound()->playSound(kEntityGendarmes, "LIB014", SoundManager::kFlagDefault); + getAction()->playAnimation(kEventGendarmesArrestation); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + break; + + case 3: + getAction()->playAnimation((params->param1 < kCarRedSleeping) ? kEventMertensBloodJacket : kEventCoudertBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + + getObjects()->update((ObjectIndex)params->param3, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + CALLBACK_ACTION(); + break; + + case 4: + getAction()->playAnimation(kEventGendarmesArrestation); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + + getObjects()->update((ObjectIndex)params->param3, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + CALLBACK_ACTION(); + break; + + case 5: + getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).location, kCursorNormal, kCursorHand); + break; + + case 6: + getSound()->playSound(kEntityGendarmes, "LIB014", SoundManager::kFlagDefault); + getAction()->playAnimation(kEventGendarmesArrestation); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Gendarmes, chapter1Handler) + if (savepoint.action == kAction169499649) { + getSavePoints()->push(kEntityGendarmes, kEntityMertens, kAction190082817); + setup_function12(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Gendarmes, function12) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + + getProgress().field_14 = 29; + + setCallback(1); + setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_5540); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function9(kCarGreenSleeping, kPosition_5790, "d", "A"); + break; + + case 2: + setCallback(3); + setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_6220); + break; + + case 3: + setCallback(4); + setup_function9(kCarGreenSleeping, kPosition_6470, "c", "B"); + break; + + case 4: + setCallback(5); + setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_7250); + break; + + case 5: + setCallback(6); + setup_function9(kCarGreenSleeping, kPosition_7500, "b", "C"); + break; + + case 6: + setCallback(7); + setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_7950); + break; + + case 7: + setCallback(8); + setup_function9(kCarGreenSleeping, kPosition_8200, "a", "NODIALOG"); + break; + + case 8: + setCallback(9); + setup_arrestUpdateEntity(kCarGreenSleeping, kPosition_9460); + break; + + case 9: + if (getEntityData(kEntityPlayer)->car == kCarGreenSleeping) { + getProgress().field_14 = 0; + getEntities()->clearSequences(kEntityGendarmes); + getSavePoints()->push(kEntityGendarmes, kEntityVerges, kAction168710784); + setup_function13(); + break; + } + + setCallback(10); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_2490); + break; + + case 10: + setCallback(11); + setup_function9(kCarRedSleeping, kPosition_2740, "h", "NODIALOG"); + break; + + case 11: + setCallback(12); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_3820); + break; + + case 12: + setCallback(13); + setup_function9(kCarRedSleeping, kPosition_4070, "f", "E"); + break; + + case 13: + setCallback(14); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_4590); + break; + + case 14: + setCallback(15); + setup_function9(kCarRedSleeping, kPosition_4840, "e", "F"); + break; + + case 15: + setCallback(16); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_5540); + break; + + case 16: + setCallback(17); + setup_function9(kCarRedSleeping, kPosition_5790, "d", "G"); + break; + + case 17: + setCallback(18); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_6220); + break; + + case 18: + setCallback(19); + setup_function9(kCarRedSleeping, kPosition_6470, "c", "H"); + break; + + case 19: + setCallback(20); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_7250); + break; + + case 20: + setCallback(21); + setup_function9(kCarRedSleeping, kPosition_7500, "b", "J"); + break; + + case 21: + setCallback(22); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_7950); + break; + + case 22: + setCallback(23); + setup_function9(kCarRedSleeping, kPosition_8200, "a", "NODIALOG"); + break; + + case 23: + setCallback(24); + setup_arrestUpdateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 24: + getProgress().field_14 = 0; + getEntities()->clearSequences(kEntityGendarmes); + getSavePoints()->push(kEntityGendarmes, kEntityVerges, kAction168710784); + setup_function13(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Gendarmes, function13) + if (savepoint.action == kActionDefault) + getData()->car = kCarNone; +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Gendarmes, chapter2) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityGendarmes); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Gendarmes, chapter3) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityGendarmes); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Gendarmes, chapter4) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityGendarmes); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Gendarmes, chapter5) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityGendarmes); +} + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Gendarmes::arrest(const SavePoint &savepoint, bool shouldPlaySound, SoundManager::FlagType flag, bool checkCallback, bool shouldUpdateEntity) { + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (checkCallback) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII); + TIME_CHECK_CALLBACK_ACTION(params->param1, params->param2); + } + + if (shouldUpdateEntity) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII); + if (getEntities()->updateEntity(kEntityGendarmes, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + } + // Fallback to next action + + case kActionDrawScene: + if (!ENTITY_PARAM(0, 1) && getEntities()->hasValidFrame(kEntityGendarmes)) { + getSound()->playSound(kEntityPlayer, "MUS007"); + ENTITY_PARAM(0, 1) = 1; + } + + if (getEntities()->isDistanceBetweenEntities(kEntityGendarmes, kEntityPlayer, 1000) && !getEntityData(kEntityPlayer)->location) { + + if (shouldUpdateEntity) + if (getEntities()->isPlayerPosition(kCarRedSleeping, 22) && !getEntities()->isDistanceBetweenEntities(kEntityGendarmes, kEntityPlayer, 250)) + break; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventGendarmesArrestation); + } + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionDefault: + // Only handle when passing SIIS params + if (!checkCallback) { + EXPOSE_PARAMS(EntityData::EntityParametersSIIS); + + if (!shouldPlaySound) + getEntities()->drawSequenceRight(kEntityGendarmes, (char *)¶ms->seq1); + else + getSound()->playSound(kEntityGendarmes, (char *)¶ms->seq1, flag); + } + + if (shouldUpdateEntity) { + EXPOSE_PARAMS(EntityData::EntityParametersIIII); + if (getEntities()->updateEntity(kEntityGendarmes, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + } + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventGendarmesArrestation); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + } + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/gendarmes.h b/engines/lastexpress/entities/gendarmes.h new file mode 100644 index 0000000000..b0aec28bfb --- /dev/null +++ b/engines/lastexpress/entities/gendarmes.h @@ -0,0 +1,99 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_GENDARMES_H +#define LASTEXPRESS_GENDARMES_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +#include "lastexpress/game/sound.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Gendarmes : public Entity { +public: + Gendarmes(LastExpressEngine *engine); + ~Gendarmes() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION_1(arrestDraw, const char *sequence) + DECLARE_FUNCTION_1(arrestPlaysound, const char *soundName) + DECLARE_FUNCTION_1(arrestPlaysound16, const char *soundName) + DECLARE_FUNCTION_1(arrestCallback, TimeValue timeValue) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + DECLARE_FUNCTION_2(arrestUpdateEntity, CarIndex car, EntityPosition entityPosition) + DECLARE_FUNCTION_4(function9, CarIndex car, EntityPosition entityPosition, const char *sequence1, const char *sequence2) + DECLARE_FUNCTION_3(function10, CarIndex car, EntityPosition entityPosition, ObjectIndex object) + DECLARE_FUNCTION(chapter1Handler) + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION(function13) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + +private: + void arrest(const SavePoint &savepoint, bool playSound = false, SoundManager::FlagType flag = SoundManager::kFlagInvalid, bool checkCallback = false, bool shouldUpdateEntity = false); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_GENDARMES_H diff --git a/engines/lastexpress/entities/hadija.cpp b/engines/lastexpress/entities/hadija.cpp new file mode 100644 index 0000000000..564ac942ca --- /dev/null +++ b/engines/lastexpress/entities/hadija.cpp @@ -0,0 +1,529 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/hadija.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Hadija::Hadija(LastExpressEngine *engine) : Entity(engine, kEntityHadija) { + ADD_CALLBACK_FUNCTION(Hadija, reset); + ADD_CALLBACK_FUNCTION(Hadija, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Hadija, playSound); + ADD_CALLBACK_FUNCTION(Hadija, updateFromTime); + ADD_CALLBACK_FUNCTION(Hadija, updateEntity); + ADD_CALLBACK_FUNCTION(Hadija, compartment6); + ADD_CALLBACK_FUNCTION(Hadija, compartment8); + ADD_CALLBACK_FUNCTION(Hadija, compartment6to8); + ADD_CALLBACK_FUNCTION(Hadija, compartment8to6); + ADD_CALLBACK_FUNCTION(Hadija, chapter1); + ADD_CALLBACK_FUNCTION(Hadija, chapter1Handler); + ADD_CALLBACK_FUNCTION(Hadija, function12); + ADD_CALLBACK_FUNCTION(Hadija, chapter2); + ADD_CALLBACK_FUNCTION(Hadija, chapter2Handler); + ADD_CALLBACK_FUNCTION(Hadija, chapter3); + ADD_CALLBACK_FUNCTION(Hadija, chapter3Handler); + ADD_CALLBACK_FUNCTION(Hadija, chapter4); + ADD_CALLBACK_FUNCTION(Hadija, chapter4Handler); + ADD_CALLBACK_FUNCTION(Hadija, function19); + ADD_CALLBACK_FUNCTION(Hadija, chapter5); + ADD_CALLBACK_FUNCTION(Hadija, chapter5Handler); + ADD_CALLBACK_FUNCTION(Hadija, function22); + ADD_CALLBACK_FUNCTION(Hadija, function23); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Hadija, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(2, Hadija, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Hadija, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(4, Hadija, updateFromTime) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(5, Hadija, updateEntity, CarIndex, EntityPosition) + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Hadija, compartment6) + COMPARTMENT_TO(Hadija, kObjectCompartment6, kPosition_4070, "619Cf", "619Df"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Hadija, compartment8) + COMPARTMENT_TO(Hadija, kObjectCompartment8, kPosition_2740, "619Ch", "619Dh"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Hadija, compartment6to8) + COMPARTMENT_FROM_TO(Hadija, kObjectCompartment6, kPosition_4070, "619Bf", kObjectCompartment8, kPosition_2740, "619Ah"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Hadija, compartment8to6) + COMPARTMENT_FROM_TO(Hadija, kObjectCompartment8, kPosition_2740, "619Bh", kObjectCompartment6, kPosition_4070, "619Af"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Hadija, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Hadija, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_PLAYSOUND_UPDATEPOSITION(kTimeParisEpernay, params->param1, 1, "Har1100", kPosition_4840); + +label_callback1: + TIME_CHECK_CALLBACK(kTime1084500, params->param2, 2, setup_compartment6to8); + +label_callback2: + if (params->param3 != kTimeInvalid && getState()->time > kTime1093500) { + + if (getState()->time <= kTime1134000) { + + if (!getEntities()->isPlayerInCar(kCarGreenSleeping) || !getEntities()->isInsideCompartment(kEntityMahmud, kCarGreenSleeping, kPosition_5790) || !params->param3) { + params->param3 = getState()->time + 75; + + if (!params->param3) { + setCallback(3); + setup_compartment8(); + return; + } + } + + if (params->param3 >= getState()->time) + return; + } + + params->param3 = kTimeInvalid; + + setCallback(3); + setup_compartment8(); + } + +label_callback3: + TIME_CHECK_CALLBACK(kTime1156500, params->param4, 4, setup_compartment8to6); + +label_callback4: + if (params->param5 != kTimeInvalid && getState()->time > kTime1165500) { + if (getState()->time <= kTime1188000) { + + if (!getEntities()->isPlayerInCar(kCarGreenSleeping) || !getEntities()->isInsideCompartment(kEntityMahmud, kCarGreenSleeping, kPosition_5790) || !params->param5) { + params->param5 = getState()->time + 75; + + if (!params->param5) { + setCallback(5); + setup_compartment6(); + return; + } + } + + if (params->param5 >= getState()->time) + return; + } + + params->param5 = kTimeInvalid; + + setCallback(5); + setup_compartment6(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + + case 4: + goto label_callback4; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Hadija, function12) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartment8, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityHadija); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Hadija, chapter2) + if (savepoint.action == kActionDefault) { + + getEntities()->clearSequences(kEntityHadija); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + setup_chapter2Handler(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Hadija, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_POSITION(kTime1782000, params->param1, kPosition_2740); + + if (params->param2 == kTimeInvalid || getState()->time <= kTime1786500) { + TIME_CHECK_CALLBACK(kTime1822500, params->param3, 2, setup_compartment8to6); + break; + } + + if (getState()->time <= kTime1818000) { + + if (!getEntities()->isPlayerInCar(kCarGreenSleeping) || !params->param2) + params->param2 = getState()->time + 75; + + if (params->param2 >= getState()->time) { + TIME_CHECK_CALLBACK(kTime1822500, params->param3, 2, setup_compartment8to6); + break; + } + } + + params->param2 = kTimeInvalid; + + setCallback(1); + setup_compartment8(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + TIME_CHECK_CALLBACK(kTime1822500, params->param3, 2, setup_compartment8to6); + break; + + case 2: + setCallback(3); + setup_playSound("Har2012"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Hadija, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityHadija); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Hadija, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime1998000, params->param1, 1, setup_compartment6to8); + +label_callback1: + TIME_CHECK_CALLBACK(kTime2020500, params->param2, 2, setup_compartment8to6); + +label_callback2: + TIME_CHECK_CALLBACK(kTime2079000, params->param3, 3, setup_compartment6to8); + +label_callback3: + TIME_CHECK_CALLBACK(kTime2187000, params->param4, 4, setup_compartment8to6); + +label_callback4: + if (params->param5 != kTimeInvalid && getState()->time > kTime2196000) + TIME_CHECK_CAR(kTime2254500, params->param5, 5, setup_compartment6); + break; + + case kActionDefault: + getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + + case 4: + goto label_callback4; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Hadija, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Hadija, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 != kTimeInvalid) + TIME_CHECK_CAR(kTime1714500, params->param1, 1, setup_compartment6); + +label_callback1: + TIME_CHECK_CALLBACK(kTime2367000, params->param2, 2, setup_compartment6to8); + +label_callback2: + TIME_CHECK_CALLBACK(kTime2421000, params->param3, 3, setup_compartment8to6); + +label_callback3: + if (params->param4 != kTimeInvalid && getState()->time > kTime2425500) + TIME_CHECK_CAR(kTime2484000, params->param4, 4, setup_compartment6); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Hadija, function19) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartment8, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityHadija); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Hadija, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityHadija); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Hadija, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function22(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Hadija, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->time, 2700); + setup_function23(); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + break; + + case kActionDrawScene: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { + setup_function23(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Hadija, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_4070); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("619AF", kObjectCompartment6); + break; + + case 2: + getEntities()->clearSequences(kEntityHadija); + + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + + getObjects()->update(kObjectCompartment5, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(24, Hadija) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/hadija.h b/engines/lastexpress/entities/hadija.h new file mode 100644 index 0000000000..4792f97cad --- /dev/null +++ b/engines/lastexpress/entities/hadija.h @@ -0,0 +1,144 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_HADIJA_H +#define LASTEXPRESS_HADIJA_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Hadija : public Entity { +public: + Hadija(LastExpressEngine *engine); + ~Hadija() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint + * - Time to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTime) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION(compartment6) + DECLARE_FUNCTION(compartment8) + DECLARE_FUNCTION(compartment6to8) + DECLARE_FUNCTION(compartment8to6) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function12) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function19) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_HADIJA_H diff --git a/engines/lastexpress/entities/ivo.cpp b/engines/lastexpress/entities/ivo.cpp new file mode 100644 index 0000000000..d56c184c15 --- /dev/null +++ b/engines/lastexpress/entities/ivo.cpp @@ -0,0 +1,829 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/ivo.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/fight.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Ivo::Ivo(LastExpressEngine *engine) : Entity(engine, kEntityIvo) { + ADD_CALLBACK_FUNCTION(Ivo, reset); + ADD_CALLBACK_FUNCTION(Ivo, draw); + ADD_CALLBACK_FUNCTION(Ivo, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Ivo, updateFromTime); + ADD_CALLBACK_FUNCTION(Ivo, updateFromTicks); + ADD_CALLBACK_FUNCTION(Ivo, updateEntity); + ADD_CALLBACK_FUNCTION(Ivo, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Ivo, playSound); + ADD_CALLBACK_FUNCTION(Ivo, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Ivo, savegame); + ADD_CALLBACK_FUNCTION(Ivo, function11); + ADD_CALLBACK_FUNCTION(Ivo, sitAtTableWithSalko); + ADD_CALLBACK_FUNCTION(Ivo, leaveTableWithSalko); + ADD_CALLBACK_FUNCTION(Ivo, chapter1); + ADD_CALLBACK_FUNCTION(Ivo, chapter1Handler); + ADD_CALLBACK_FUNCTION(Ivo, function16); + ADD_CALLBACK_FUNCTION(Ivo, function17); + ADD_CALLBACK_FUNCTION(Ivo, chapter2); + ADD_CALLBACK_FUNCTION(Ivo, function19); + ADD_CALLBACK_FUNCTION(Ivo, function20); + ADD_CALLBACK_FUNCTION(Ivo, function21); + ADD_CALLBACK_FUNCTION(Ivo, chapter3); + ADD_CALLBACK_FUNCTION(Ivo, chapter3Handler); + ADD_CALLBACK_FUNCTION(Ivo, chapter4); + ADD_CALLBACK_FUNCTION(Ivo, chapter4Handler); + ADD_CALLBACK_FUNCTION(Ivo, function26); + ADD_CALLBACK_FUNCTION(Ivo, function27); + ADD_CALLBACK_FUNCTION(Ivo, function28); + ADD_CALLBACK_FUNCTION(Ivo, function29); + ADD_CALLBACK_FUNCTION(Ivo, chapter5); + ADD_CALLBACK_FUNCTION(Ivo, chapter5Handler); + ADD_CALLBACK_FUNCTION(Ivo, fight); + ADD_CALLBACK_FUNCTION(Ivo, function33); + ADD_CALLBACK_FUNCTION(Ivo, function34); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Ivo, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Ivo, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Ivo, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(4, Ivo, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(5, Ivo, updateFromTicks, uint32) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(6, Ivo, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath || savepoint.action == kActionExcuseMe) { + getSound()->playSound(kEntityPlayer, "CAT1127A"); + return; + } + + Entity::updateEntity(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Ivo, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(8, Ivo, playSound) + Entity::playSound(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Ivo, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Ivo, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Ivo, function11) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isDistanceBetweenEntities(kEntityIvo, kEntitySalko, 750) || getEntities()->checkDistanceFromPosition(kEntitySalko, kPosition_2740, 500)) { + getSavePoints()->push(kEntityIvo, kEntitySalko, kAction123668192); + + setCallback(4); + setup_enterExitCompartment("613Ah", kObjectCompartmentH); + } + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityIvo, "809DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityIvo); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityIvo, kEntitySalko, kAction125242096); + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + break; + + case 2: + if (getEntities()->isDistanceBetweenEntities(kEntityIvo, kEntitySalko, 750) || getEntities()->checkDistanceFromPosition(kEntitySalko, kPosition_2740, 500)) { + getSavePoints()->push(kEntityIvo, kEntitySalko, kAction123668192); + + setCallback(3); + setup_enterExitCompartment("613Ah", kObjectCompartmentH); + } else { + getEntities()->drawSequenceLeft(kEntityIvo, "613Hh"); + getEntities()->enterCompartment(kEntityIvo, kObjectCompartmentH, true); + } + break; + + case 3: + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityIvo); + + CALLBACK_ACTION(); + break; + + case 4: + getEntities()->exitCompartment(kEntityIvo, kObjectCompartmentH, true); + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityIvo); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Ivo, sitAtTableWithSalko) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->clearSequences(kEntitySalko); + getSavePoints()->push(kEntityIvo, kEntityTables2, kAction136455232); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityIvo, "023A1"); + getEntities()->drawSequenceRight(kEntitySalko, "023A2"); + getEntities()->drawSequenceRight(kEntityTables2, "023A3"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Ivo, leaveTableWithSalko) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getSavePoints()->push(kEntityIvo, kEntityTables2, kActionDrawTablesWithChairs, "009E"); + getEntities()->clearSequences(kEntitySalko); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityIvo, "023D1"); + getEntities()->drawSequenceRight(kEntitySalko, "023D2"); + getEntities()->drawSequenceRight(kEntityTables2, "023D3"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Ivo, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject47, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_4691; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Ivo, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->entityPosition = getEntityData(kEntityMilos)->entityPosition; + getData()->location = getEntityData(kEntityMilos)->location; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function11(); + break; + + case 2: + getSavePoints()->push(kEntityIvo, kEntityMilos, kAction135024800); + setup_function16(); + break; + } + break; + + case kAction125242096: + setCallback(1); + setup_updateFromTicks(75); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Ivo, function16) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getEntities()->clearSequences(kEntityIvo); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityIvo, "613Ch"); + getEntities()->enterCompartment(kEntityIvo, kObjectCompartmentH); + getSavePoints()->push(kEntityIvo, kEntityCoudert, kAction88652208); + break; + + case 2: + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityIvo); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + } + break; + + case kAction122865568: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_enterExitCompartment("613Bh", kObjectCompartmentH); + break; + + case kAction123852928: + getEntities()->exitCompartment(kEntityIvo, kObjectCompartmentH, true); + + setCallback(2); + setup_enterExitCompartment("613Dh", kObjectCompartmentH); + break; + + case kAction221683008: + getSavePoints()->push(kEntityIvo, kEntityCoudert, kAction123199584); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Ivo, function17) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityIvo); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Ivo, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime1777500, params->param1, setup_function19); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityIvo); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject47, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Ivo, function19) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("613FH", kObjectCompartmentH); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getSavePoints()->push(kEntityIvo, kEntitySalko, kAction136184016); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("809US"); + break; + + case 4: + setCallback(5); + setup_sitAtTableWithSalko(); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + setup_function20(); + break; + } + break; + + case kAction102675536: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Ivo, function20) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime1809000 && params->param1) { + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_leaveTableWithSalko(); + } + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityIvo, kEntityServers1, kAction189688608); + getEntities()->drawSequenceLeft(kEntityIvo, "023B"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityIvo, kEntityServers1, kAction101106391); + getEntities()->drawSequenceLeft(kEntityIvo, "023B"); + params->param1 = 1; + break; + + case 2: + setCallback(3); + setup_function11(); + break; + + case 3: + getSavePoints()->push(kEntityIvo, kEntityServers1, kAction236237423); + setup_function21(); + break; + } + break; + + case kAction123712592: + getEntities()->drawSequenceLeft(kEntityIvo, "023C2"); + + setCallback(1); + setup_updateFromTime(450); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Ivo, function21) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Ivo, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityIvo); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Ivo, chapter3Handler) + if (savepoint.action == kActionDefault) + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Ivo, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Ivo, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2361600 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + setup_function26(); + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityIvo, kEntityTables2, kAction136455232); + getEntities()->drawSequenceLeft(kEntityIvo, "023B"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Ivo, function26) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_leaveTableWithSalko(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function11(); + break; + + case 2: + setup_function27(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Ivo, function27) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getEntities()->clearSequences(kEntityIvo); + setup_function28(); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityIvo, "613Ch"); + getEntities()->enterCompartment(kEntityIvo, kObjectCompartmentH, true); + getSavePoints()->push(kEntityIvo, kEntityCoudert, kAction88652208); + break; + + case 4: + getEntities()->exitCompartment(kEntityIvo, kObjectCompartmentH, true); + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityIvo); + break; + } + break; + + case kAction55996766: + setCallback(1); + setup_enterExitCompartment("613FH", kObjectCompartmentH); + break; + + case kAction122865568: + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_enterExitCompartment("613Bh", kObjectCompartmentH); + break; + + case kAction123852928: + setCallback(4); + setup_enterExitCompartment("613Dh", kObjectCompartmentH); + break; + + case kAction221683008: + getSavePoints()->push(kEntityIvo, kEntityCoudert, kAction123199584); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Ivo, function28) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2425500 && !params->param1) { + params->param1 = 1; + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("613EH", kObjectCompartmentH); + break; + + case 2: + setup_function29(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Ivo, function29) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityIvo); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Ivo, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityIvo); + + getData()->entityPosition = kPosition_540; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarBaggageRear; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Ivo, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_fight(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Ivo, fight) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + getData()->entityPosition = kPosition_540; + getData()->car = kCarBaggageRear; + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCathIvoFight); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSound()->playSound(kEntityPlayer, "LIB090"); + getAction()->playAnimation(kEventCathIvoFight); + + setCallback(2); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case 2: + params->param1 = getFight()->setup(kFightIvo); + if (params->param1) { + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true); + } else { + getScenes()->loadSceneFromPosition(kCarBaggageRear, 96); + setup_function33(); + } + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Ivo, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getState()->time += 1800; + + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionCallback: + if (getCallback() == 1) + getObjects()->update(kObject94, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + + break; + + case kAction135800432: + setup_function34(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Ivo, function34) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityIvo); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/ivo.h b/engines/lastexpress/entities/ivo.h new file mode 100644 index 0000000000..65bf9de165 --- /dev/null +++ b/engines/lastexpress/entities/ivo.h @@ -0,0 +1,177 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_IVO_H +#define LASTEXPRESS_IVO_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Ivo : public Entity { +public: + Ivo(LastExpressEngine *engine); + ~Ivo() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates parameter 2 using ticks value + * + * @param ticks The number of ticks to add + */ + DECLARE_FUNCTION_1(updateFromTicks, uint32 ticks) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Plays sound + * + * @param savepoint The savepoint + * - the sound filename + */ + DECLARE_FUNCTION_NOSETUP(playSound) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + DECLARE_FUNCTION(function11) + DECLARE_FUNCTION(sitAtTableWithSalko) + DECLARE_FUNCTION(leaveTableWithSalko) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function16) + DECLARE_FUNCTION(function17) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(fight) + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_IVO_H diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp new file mode 100644 index 0000000000..b10b60476b --- /dev/null +++ b/engines/lastexpress/entities/kahina.cpp @@ -0,0 +1,944 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/kahina.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Kahina::Kahina(LastExpressEngine *engine) : Entity(engine, kEntityKahina) { + ADD_CALLBACK_FUNCTION(Kahina, reset); + ADD_CALLBACK_FUNCTION(Kahina, playSound); + ADD_CALLBACK_FUNCTION(Kahina, savegame); + ADD_CALLBACK_FUNCTION(Kahina, updateFromTime); + ADD_CALLBACK_FUNCTION(Kahina, updateFromTicks); + ADD_CALLBACK_FUNCTION(Kahina, function6); + ADD_CALLBACK_FUNCTION(Kahina, updateEntity2); + ADD_CALLBACK_FUNCTION(Kahina, updateEntity); + ADD_CALLBACK_FUNCTION(Kahina, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Kahina, chapter1); + ADD_CALLBACK_FUNCTION(Kahina, chapter1Handler); + ADD_CALLBACK_FUNCTION(Kahina, function12); + ADD_CALLBACK_FUNCTION(Kahina, function13); + ADD_CALLBACK_FUNCTION(Kahina, function14); + ADD_CALLBACK_FUNCTION(Kahina, function15); + ADD_CALLBACK_FUNCTION(Kahina, chapter2); + ADD_CALLBACK_FUNCTION(Kahina, chapter2Handler); + ADD_CALLBACK_FUNCTION(Kahina, chapter3); + ADD_CALLBACK_FUNCTION(Kahina, function19); + ADD_CALLBACK_FUNCTION(Kahina, chapter3Handler); + ADD_CALLBACK_FUNCTION(Kahina, function21); + ADD_CALLBACK_FUNCTION(Kahina, function22); + ADD_CALLBACK_FUNCTION(Kahina, function23); + ADD_CALLBACK_FUNCTION(Kahina, function24); + ADD_CALLBACK_FUNCTION(Kahina, function25); + ADD_CALLBACK_FUNCTION(Kahina, function26); + ADD_CALLBACK_FUNCTION(Kahina, function27); + ADD_CALLBACK_FUNCTION(Kahina, chapter4); + ADD_CALLBACK_FUNCTION(Kahina, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Kahina, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Kahina, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(3, Kahina, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(4, Kahina, updateFromTime, uint32) + if (savepoint.action == kAction137503360) { + ENTITY_PARAM(0, 2) = 1; + CALLBACK_ACTION(); + } + + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(5, Kahina, updateFromTicks) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(6, Kahina, function6, TimeValue) + error("Kahina: callback function 6 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7 ,Kahina, updateEntity2, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionDefault: + if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + } else if (getEntities()->isDistanceBetweenEntities(kEntityKahina, kEntityPlayer, 1000) + && !getEntities()->isInGreenCarEntrance(kEntityPlayer) + && !getEntities()->isInsideCompartments(kEntityPlayer) + && !getEntities()->checkFields10(kEntityPlayer)) { + + if (getData()->car == kCarGreenSleeping || getData()->car == kCarRedSleeping) { + ENTITY_PARAM(0, 1) = 1; + CALLBACK_ACTION(); + } + } + break; + + case kAction137503360: + ENTITY_PARAM(0, 2) = 1; + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Kahina, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + if (getEvent(kEventKronosConversation) || getEvent(kEventKronosConversationFirebird)) { + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1019" : "CAT1019A"); + } else { + getSound()->excuseMeCath(); + } + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(9, Kahina, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Kahina, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarKronos; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Kahina, chapter1Handler) + if (savepoint.action != kActionNone) + return; + + if (getProgress().jacket != kJacketOriginal) + TIME_CHECK_SAVEPOINT(kTime1107000, params->param1, kEntityKahina, kEntityMertens, kAction238732837); + + if (getProgress().eventMertensKronosInvitation) + setup_function12(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Kahina, function12) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime1485000, params->param2, setup_function13); + break; + + case kActionKnock: + getSound()->playSound(kEntityPlayer, "LIB012"); + // Fallback to next action + + case kActionOpenDoor: + if (!getEvent(kEventKronosGoingToInvitation)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosGoingToInvitation); + break; + } + + if (savepoint.action == kActionOpenDoor) + getSound()->playSound(kEntityPlayer, "LIB014"); + + getScenes()->loadSceneFromPosition(kCarKronos, 80); + getSavePoints()->push(kEntityKahina, kEntityKronos, kAction171849314); + params->param1 = 1; + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventKronosGoingToInvitation); + getScenes()->loadSceneFromPosition(kCarKronos, 80); + getSavePoints()->push(kEntityKahina, kEntityKronos, kAction171849314); + params->param1 = 1; + } + break; + + case kAction137685712: + setup_function13(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Kahina, function13) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().field_14 || getState()->time >= kTime1201500 || params->param2 == kTimeInvalid || params->param1 >= getState()->time) + break; + + if (getState()->time <= kTime1197000) { + if (!getEntities()->isPlayerInCar(kCarGreenSleeping) || !params->param2) { + params->param2 = getState()->time; + + if (!getState()->time) + goto label_callback; + } + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + +label_callback: + setCallback(1); + setup_function15(); + break; + + case kActionDefault: + getData()->car = kCarKronos; + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param1 = getState()->time + 1800; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Kahina, function14) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->exitCompartment(kEntityKahina, kObjectCompartmentF); + CALLBACK_ACTION(); + break; + + case kAction4: + getEntities()->exitCompartment(kEntityKahina, kObjectCompartmentF); + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityKahina, "616Cf"); + getEntities()->enterCompartment(kEntityKahina, kObjectCompartmentF); + getSavePoints()->push(kEntityKahina, kEntityMax, kAction158007856); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Kahina, function15) + error("Kahina: callback function 15 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Kahina, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityKahina); + + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarKronos; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorHandKnock, kCursorHand); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Kahina, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM_PROC(params->param2, getState()->time, 9000) + params->param1 = 1; + params->param2 = 0; + UPDATE_PARAM_PROC_END + } + + if (getEvent(kEventKahinaAskSpeakFirebird) && getEvent(kEventKronosConversationFirebird) && getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { + UPDATE_PARAM_PROC(params->param3, getState()->time, 900) + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosConversationFirebird); + break; + UPDATE_PARAM_PROC_END + } + +label_callback_3: + if (getState()->time > kTime1845000 && getEvent(kEventKronosConversationFirebird) && getEntities()->isInKronosSalon(kEntityPlayer)) { + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getScenes()->loadSceneFromPosition(kCarKronos, 87); + } + break; + + case kActionKnock: + case kActionOpenDoor: + if (getEvent(kEventKronosConversationFirebird)) + break; + + if (getEvent(kEventKahinaAskSpeakFirebird)) { + if (getSound()->isBuffered(kEntityKahina)) + getSound()->processEntry(kEntityKahina); + + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventKronosConversationFirebird); + break; + } + + if (getEvent(kEventMilosCompartmentVisitAugust) || getEvent(kEventTatianaGivePoem) || getEvent(kEventTatianaBreakfastGivePoem)) { + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(7); + setup_savegame(kSavegameTypeEvent, kEventKahinaAskSpeakFirebird); + break; + } + + if (params->param1) { + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + getAction()->playAnimation(kEventKahinaAskSpeak); + getScenes()->processScene(); + + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(8); + setup_playSound("KRO3003"); + } else { + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 9 : 10); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + params->param1 = 1; + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 4: + getAction()->playAnimation(kEventKronosConversationFirebird); + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getScenes()->loadSceneFromPosition(kCarKronos, 80, 1); + + setCallback(getCallback() == 1 ? 2 : 5); + setup_updateFromTime(900); + break; + + case 2: + case 5: + setCallback(getCallback() == 2 ? 3 : 6); + setup_playSound("KRO3005"); + break; + + case 3: + goto label_callback_3; + + case 7: + getAction()->playAnimation(kEventKahinaAskSpeakFirebird); + getScenes()->loadSceneFromPosition(kCarKronos, 81); + getSound()->playSound(kEntityKahina, "KRO3004"); + break; + + case 8: + case 9: + case 10: + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorHandKnock, kCursorHand); + if (getCallback() == 8) + params->param1 = 0; + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Kahina, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityKahina); + + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarKronos; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(19, Kahina, function19, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEvent(kEventAnnaBaggageArgument)) + RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_function22); + + if (getEntities()->updateEntity(kEntityKahina, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + if (getEvent(kEventKronosConversation) || getEvent(kEventKronosConversationFirebird)) + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1019" : "CAT1019A"); + else + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntityKahina); + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityKahina, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Kahina, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEvent(kEventKronosVisit)) + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + if (getEntities()->isInKronosSanctum(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunchSuite4); + break; + } + +label_callback_1: + if (getState()->time > kTime2079000 && !params->param2) { + params->param2 = 1; + + if (getEvent(kEventKahinaAskSpeakFirebird) + && !getEvent(kEventKronosConversationFirebird) + && getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventKronosConversationFirebird); + break; + } + +label_callback_2: + if (getEntities()->isInKronosSalon(kEntityPlayer)) + getScenes()->loadSceneFromPosition(kCarKronos, 87); + + setup_function21(); + break; + } + + if (!params->param1) { + UPDATE_PARAM_PROC(params->param3, getState()->time, 9000) + params->param1 = 1; + params->param3 = 0; + UPDATE_PARAM_PROC_END + } + + if (getEvent(kEventKahinaAskSpeakFirebird) + && !getEvent(kEventKronosConversationFirebird) + && getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { + UPDATE_PARAM(params->param4, getState()->time, 900); + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventKronosConversationFirebird); + } + break; + + case kActionKnock: + case kActionOpenDoor: + if (!getEvent(kEventKronosConversationFirebird)) { + + if (getEvent(kEventKahinaAskSpeakFirebird)) { + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventKronosConversationFirebird); + break; + } + + if (getEvent(kEventMilosCompartmentVisitAugust) || getEvent(kEventTatianaGivePoem) || getEvent(kEventTatianaBreakfastGivePoem)) { + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + setCallback(9); + setup_savegame(kSavegameTypeEvent, kEventKahinaAskSpeakFirebird); + break; + } + + if (params->param1) { + if (savepoint.action == kActionKnock) + getSound()->playSound(kEntityPlayer, "LIB012"); + + getAction()->playAnimation(kEventKahinaAskSpeak); + getScenes()->processScene(); + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(10); + setup_playSound("KRO3003"); + break; + } + + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 11 : 12); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + if (getEvent(kEventKronosConversationFirebird)) { + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + } else { + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorHandKnock, kCursorHand); + params->param1 = 1; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventKahinaPunchSuite4); + getLogic()->gameOver(kSavegameTypeEvent2, kEventCathJumpDownCeiling, kSceneNone, false); + goto label_callback_1; + + case 2: + getAction()->playAnimation(kEventKronosConversationFirebird); + getScenes()->loadSceneFromPosition(kCarKronos, 87); + goto label_callback_2; + + case 3: + getAction()->playAnimation(kEventKronosConversationFirebird); + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getScenes()->loadSceneFromPosition(kCarKronos, 80, 1); + + setCallback(4); + setup_updateFromTime(900); + break; + + case 4: + setCallback(5); + setup_playSound("KRO3005"); + break; + + case 6: + getAction()->playAnimation(kEventKronosConversationFirebird); + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getScenes()->loadSceneFromPosition(kCarKronos, 80, 1); + + setCallback(7); + setup_updateFromTime(900); + break; + + case 7: + setCallback(8); + setup_playSound("KRO3005"); + break; + + case 9: + getAction()->playAnimation(kEventKahinaAskSpeakFirebird); + getScenes()->loadSceneFromPosition(kCarKronos, 81); + getSound()->playSound(kEntityKahina, "KRO3004"); + break; + + case 10: + params->param1 = 0; + // Fallback to next case + + case 11: + case 12: + getObjects()->update(kObjectCompartmentKronos, kEntityKahina, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Kahina, function21) + error("Kahina: callback function 21 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Kahina, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + ObjectLocation location = getInventory()->get(kItemFirebird)->location; + + if (ENTITY_PARAM(0, 3) || location == kObjectLocation3 || location == kObjectLocation7) { + setCallback(1); + setup_function25(); + } else if (location == kObjectLocation2 || location == kObjectLocation1) { + setCallback(2); + setup_function26(); + } + } + break; + + case kActionDefault: + getData()->car = kCarKronos; + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + break; + + case kActionDrawScene: + if (getData()->car > kCarGreenSleeping || (getData()->car == kCarGreenSleeping && getData()->entityPosition > kPosition_2740)) + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Kahina, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSound()->playSound(kEntityPlayer, "LIB014", getSound()->getSoundFlag(kEntityKahina)); + getSound()->playSound(kEntityPlayer, "LIB015", getSound()->getSoundFlag(kEntityKahina), 15); + + getEntities()->clearSequences(kEntityKahina); + + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_540; + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_4455) || getEntities()->isOutsideAnnaWindow()) { + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + } else { + setCallback(2); + setup_enterExitCompartment("616Cf", kObjectCompartmentF); + } + break; + + case 2: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityKahina); + + getObjects()->update(kObjectCompartmentF, kEntityPlayer, getObjects()->get(kObjectCompartmentF).location, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityPlayer, getObjects()->get(kObject53).location, kCursorNormal, kCursorNormal); + + setCallback(3); + setup_updateFromTime(900); + break; + + case 3: + getObjects()->update(kObjectCompartmentF, kEntityPlayer, getObjects()->get(kObjectCompartmentF).location, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, getObjects()->get(kObject53).location, kCursorHandKnock, kCursorHand); + + setCallback(4); + setup_enterExitCompartment("616Df", kObjectCompartmentF); + break; + + case 4: + getData()->location = kLocationOutsideCompartment; + + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 5: + getEntities()->clearSequences(kEntityKahina); + + setCallback(6); + setup_updateFromTime(900); + break; + + case 6: + setCallback(7); + setup_updateEntity(kCarKronos, kPosition_9270); + break; + + case 7: + getEntities()->clearSequences(kEntityKahina); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Kahina, function24) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 && getEntities()->updateEntity(kEntityKahina, (CarIndex)params->param2, (EntityPosition)params->param3)) { + getEntities()->clearSequences(kEntityKahina); + params->param1 = 0; + } + break; + + case kActionEndSound: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) + getSavePoints()->push(kEntityKahina, kEntityKronos, kActionOpenDoor); + else + setup_function27(); + break; + + case kActionDefault: + setCallback(1); + setup_function6(kTime2241000); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (ENTITY_PARAM(0, 2)) { + getEntities()->clearSequences(kEntityKahina); + if (getSound()->isBuffered(kEntityKahina)) + getSound()->processEntry(kEntityKahina); + + getProgress().field_44 = 0; + + setup_function22(); + } else if (ENTITY_PARAM(0, 1)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventKahinaGunYellow); + } else { + setup_function27(); + } + break; + + case 2: + if (getEntityData(kEntityPlayer)->entityPosition >= getData()->entityPosition) + getAction()->playAnimation(getData()->car < kCarRedSleeping ? kEventKahinaGunYellow : kEventKahinaGunBlue); + else + getAction()->playAnimation(kEventKahinaGun); + + getEntities()->updateEntity(kEntityKahina, kCarKronos, kPosition_9270); + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750)); + getSavePoints()->push(kEntityKahina, kEntityKronos, kAction235599361); + getSound()->playSound(kEntityKahina, "MUS016", SoundManager::kFlagDefault); + getProgress().field_44 = 1; + + params->param1 = true; + params->param2 = kCarKronos; + params->param3 = kPosition_9270; + break; + } + break; + + case kAction137503360: + getEntities()->clearSequences(kEntityKahina); + if (getSound()->isBuffered(kEntityKahina)) + getSound()->processEntry(kEntityKahina); + + getProgress().field_44 = 0; + + setup_function22(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Kahina, function25) + error("Kahina: callback function 25 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Kahina, function26) + error("Kahina: callback function 26 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Kahina, function27) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) + params->param1 = kEventKahinaPunchCar; + else if (getEntities()->isPlayerInCar(kCarGreenSleeping)) + params->param1 = kEventKahinaPunchBlue; + else if (getEntities()->isPlayerInCar(kCarRedSleeping)) + params->param1 = kEventKahinaPunchYellow; + else if (getEntities()->isInSalon(kEntityPlayer)) + params->param1 = kEventKahinaPunchSalon; + else if (getEntities()->isInRestaurant(kEntityPlayer)) + params->param1 = kEventKahinaPunchRestaurant; + else if (getEntities()->isInKitchen(kEntityPlayer)) + params->param1 = kEventKahinaPunchKitchen; + else if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) + params->param1 = kEventKahinaPunchBaggageCarEntrance; + else if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarBaggage)) + params->param1 = kEventKahinaPunchBaggageCar; + + if (params->param1) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kSceneGameOverAlarm2); + } + break; + + case kActionDefault: + getState()->timeDelta = 0; + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation((EventIndex)params->param1); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Kahina, chapter4) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityKahina); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Kahina, chapter5) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityKahina); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/kahina.h b/engines/lastexpress/entities/kahina.h new file mode 100644 index 0000000000..1eba9c62d9 --- /dev/null +++ b/engines/lastexpress/entities/kahina.h @@ -0,0 +1,166 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_KAHINA_H +#define LASTEXPRESS_KAHINA_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Kahina : public Entity { +public: + Kahina(LastExpressEngine *engine); + ~Kahina() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates parameter 2 using ticks value + * + * @param savepoint The savepoint + * - ticks to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTicks) + + DECLARE_FUNCTION_1(function6, TimeValue timeValue) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity2, CarIndex car, EntityPosition entityPosition) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION(function13) + DECLARE_FUNCTION(function14) + DECLARE_FUNCTION(function15) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Update the entity, handling excuse me events and resetting the entity state after the argument with Anna in the baggage car + * + * @param car The car index + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(function19, CarIndex car, EntityPosition entityPosition) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_KAHINA_H diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp new file mode 100644 index 0000000000..f45f18bbd2 --- /dev/null +++ b/engines/lastexpress/entities/kronos.cpp @@ -0,0 +1,666 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/kronos.h" + +#include "lastexpress/entities/anna.h" +#include "lastexpress/entities/august.h" +#include "lastexpress/entities/rebecca.h" +#include "lastexpress/entities/sophie.h" +#include "lastexpress/entities/tatiana.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Kronos::Kronos(LastExpressEngine *engine) : Entity(engine, kEntityKronos) { + ADD_CALLBACK_FUNCTION(Kronos, reset); + ADD_CALLBACK_FUNCTION(Kronos, savegame); + ADD_CALLBACK_FUNCTION(Kronos, updateEntity); + ADD_CALLBACK_FUNCTION(Kronos, playSound); + ADD_CALLBACK_FUNCTION(Kronos, updateFromTime); + ADD_CALLBACK_FUNCTION(Kronos, updateFromTicks); + ADD_CALLBACK_FUNCTION(Kronos, chapter1); + ADD_CALLBACK_FUNCTION(Kronos, chapter1Handler); + ADD_CALLBACK_FUNCTION(Kronos, function9); + ADD_CALLBACK_FUNCTION(Kronos, function10); + ADD_CALLBACK_FUNCTION(Kronos, function11); + ADD_CALLBACK_FUNCTION(Kronos, chapter2); + ADD_CALLBACK_FUNCTION(Kronos, chapter3); + ADD_CALLBACK_FUNCTION(Kronos, chapter3Handler); + ADD_CALLBACK_FUNCTION(Kronos, function15); + ADD_CALLBACK_FUNCTION(Kronos, function16); + ADD_CALLBACK_FUNCTION(Kronos, function17); + ADD_CALLBACK_FUNCTION(Kronos, function18); + ADD_CALLBACK_FUNCTION(Kronos, function19); + ADD_CALLBACK_FUNCTION(Kronos, function20); + ADD_CALLBACK_FUNCTION(Kronos, function21); + ADD_CALLBACK_FUNCTION(Kronos, function22); + ADD_CALLBACK_FUNCTION(Kronos, function23); + ADD_CALLBACK_FUNCTION(Kronos, chapter4); + ADD_CALLBACK_FUNCTION(Kronos, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Kronos, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(2, Kronos, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(3, Kronos, updateEntity, CarIndex, EntityPosition) + Entity::updateEntity(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(4, Kronos, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(5, Kronos, updateFromTime) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(6, Kronos, updateFromTicks) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Kronos, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarKronos; + + getObjects()->update(kObjectCeiling, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Kronos, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime1489500, params->param2, setup_function11); + break; + + case kAction171849314: + params->param1 = 1; + break; + + case kAction202621266: + setup_function9(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Kronos, function9) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosConversation); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventKronosConversation); + getScenes()->loadSceneFromPosition(kCarKronos, 87); + getSavePoints()->push(kEntityKronos, kEntityKahina, kAction137685712); + setup_function10(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Kronos, function10) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK(kTime1489500, params->param1, setup_function11); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarKronos; + + getEntities()->clearSequences(kEntityKronos); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Kronos, function11) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + params->param1++; + getSound()->playSound(kEntityKronos, (params->param1 & 1) ? "KRO1001" : "KRO1002"); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_7000; + + if (!getSound()->isBuffered(kEntityKronos)) + getSound()->playSound(kEntityKronos, "KRO1001"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Kronos, chapter2) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityKronos); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Kronos, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityKronos); + + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarKronos; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCeiling, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Kronos, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime1993500 && !params->param1 && !params->param2 && !params->param3) + setup_function15(); + break; + + case kAction157159392: + switch (savepoint.entity2) { + case kEntityAnna: + params->param1 = 1; + break; + + case kEntityTatiana: + params->param2 = 1; + break; + + case kEntityAbbot: + params->param3 = 1; + break; + + default: + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Kronos, function15) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 && !getEntities()->isInSalon(kEntityBoutarel)) { + UPDATE_PARAM_PROC(params->param2, getState()->timeTicks, 75) + setup_function16(); + break; + UPDATE_PARAM_PROC_END + } + + if (params->param3 != kTimeInvalid && getState()->time > kTime2002500) { + if (getState()->time <= kTime2052000) { + if (!getEntities()->isInSalon(kEntityPlayer) || getEntities()->isInSalon(kEntityPlayer) || !params->param3) + params->param3 = getState()->time + 900; + + if (params->param3 >= getState()->time) + break; + } + + params->param3 = kTimeInvalid; + + if (getEntities()->isInSalon(kEntityPlayer)) { + setup_function16(); + } else { + getSavePoints()->push(kEntityKronos, kEntityAnna, kAction101169422); + getSavePoints()->push(kEntityKronos, kEntityTatiana, kAction101169422); + getSavePoints()->push(kEntityKronos, kEntityAbbot, kAction101169422); + + setup_function18(); + } + } + break; + + case kActionDefault: + if (getEntities()->isPlayerPosition(kCarRestaurant, 60) + || getEntities()->isPlayerPosition(kCarRestaurant, 59) + || getEntities()->isPlayerPosition(kCarRestaurant, 83) + || getEntities()->isPlayerPosition(kCarRestaurant, 81) + || getEntities()->isPlayerPosition(kCarRestaurant, 87)) + params->param1 = 1; + break; + + case kActionDrawScene: + if (params->param1 && getEntities()->isPlayerPosition(kCarRestaurant, 51) && !getEntities()->isInSalon(kEntityBoutarel)) + setup_function16(); + else + params->param1 = getEntities()->isPlayerPosition(kCarRestaurant, 60) + || getEntities()->isPlayerPosition(kCarRestaurant, 59) + || getEntities()->isPlayerPosition(kCarRestaurant, 83) + || getEntities()->isPlayerPosition(kCarRestaurant, 81) + || getEntities()->isPlayerPosition(kCarRestaurant, 87); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16 ,Kronos, function16) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosVisit); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventKronosVisit); + getSavePoints()->push(kEntityKronos, kEntityAnna, kAction101169422); + getSavePoints()->push(kEntityKronos, kEntityTatiana, kAction101169422); + getSavePoints()->push(kEntityKronos, kEntityAbbot, kAction101169422); + getScenes()->loadSceneFromPosition(kCarRestaurant, 60); + + setup_function17(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Kronos, function17) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_9270); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function18(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Kronos, function18) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2079000 && !params->param2) { + getObjects()->updateLocation2(kObjectCompartmentKronos, kObjectLocation3); + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param1 = 1; + params->param2 = 1; + } + + TIME_CHECK(kTime2106000, params->param3, setup_function19) + else { + if (params->param1 && getEntities()->isInKronosSanctum(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunchSuite4); + } + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6000; + getData()->car = kCarKronos; + getData()->location = kLocationOutsideCompartment; + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventKahinaPunchSuite4); + getLogic()->gameOver(kSavegameTypeEvent2, kEventCathJumpDownCeiling, kSceneNone, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Kronos, function19) + switch (savepoint.action) { + default: + break; + + case kActionNone: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + break; + + case kActionDrawScene: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventKahinaPunchSuite4); + getLogic()->gameOver(kSavegameTypeEvent2, kEventCathJumpDownCeiling, kSceneNone, true); + break; + + case 2: + getAction()->playAnimation(kEventConcertStart); + getSound()->setupEntry(SoundManager::kSoundType7, kEntityKronos); + getScenes()->loadSceneFromPosition(kCarKronos, 83); + + RESET_ENTITY_STATE(kEntityRebecca, Rebecca, setup_function39); + RESET_ENTITY_STATE(kEntitySophie, Sophie, setup_chaptersHandler); + RESET_ENTITY_STATE(kEntityAugust, August, setup_function50); + RESET_ENTITY_STATE(kEntityAnna, Anna, setup_function56); + RESET_ENTITY_STATE(kEntityTatiana, Tatiana, setup_function35); + + setup_function20(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Kronos, function20) + error("Kronos: callback function 20 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Kronos, function21) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInKronosSanctum(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaWrongDoor); + } + break; + + case kActionDefault: + getProgress().field_40 = 0; + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorNormal, kCursorNormal); + getSavePoints()->push(kEntityKronos, kEntityRebecca, kAction191668032); + if (!getEvent(kEventConcertLeaveWithBriefcase)) + setup_function22(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventKahinaWrongDoor); + + if (getInventory()->hasItem(kItemBriefcase)) + getInventory()->removeItem(kItemBriefcase); + + getSound()->playSound(kEntityPlayer, "BUMP"); + + getScenes()->loadSceneFromPosition(kCarKronos, 81); + + getSound()->playSound(kEntityPlayer, "LIB015"); + } + break; + + case kAction235599361: + setup_function22(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Kronos, function22) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().field_44) { + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunchBaggageCarEntrance); + } else { + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventKahinaWrongDoor); + } + break; + + case kActionKnock: + case kActionOpenDoor: + if (!getSound()->isBuffered(savepoint.action == kActionKnock ? "LIB012" : "LIB013", true)) + getSound()->playSound(kEntityPlayer, savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + + if (getEvent(kEventConcertLeaveWithBriefcase)) + getSavePoints()->call(kEntityKronos, kEntityKahina, kAction137503360); + + if (getInventory()->hasItem(kItemBriefcase)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosReturnBriefcase); + break; + } + + if (getInventory()->hasItem(kItemFirebird) && getEvent(kEventConcertLeaveWithBriefcase)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventKronosBringEggCeiling); + break; + } + + if (getInventory()->hasItem(kItemFirebird)) { + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventKronosBringEggCeiling); + break; + } + + if (getEvent(kEventConcertLeaveWithBriefcase)) { + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventKronosBringNothing); + break; + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentKronos, kEntityKronos, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventKronosReturnBriefcase); + getScenes()->loadSceneFromPosition(kCarKronos, 87); + getInventory()->removeItem(kItemFirebird); + getInventory()->removeItem(kItemScarf); + + setup_function23(); + break; + + case 2: + getAction()->playAnimation(kEventKronosBringEggCeiling); + getScenes()->loadSceneFromPosition(kCarKronos, 87); + getInventory()->removeItem(kItemFirebird); + getInventory()->get(kItemFirebird)->location = kObjectLocation5; + + setup_function23(); + break; + + case 3: + getInventory()->removeItem(kItemFirebird); + getInventory()->get(kItemFirebird)->location = kObjectLocation5; + getAction()->playAnimation(kEventKronosBringEgg); + getScenes()->loadSceneFromPosition(kCarKronos, 87); + getInventory()->addItem(kItemBriefcase); + setup_function23(); + break; + + case 4: + getAction()->playAnimation(kEventKronosBringNothing); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + + case 5: + getAction()->playAnimation(kEventKahinaPunchSuite4); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + + case 6: + getAction()->playAnimation(kEventKahinaWrongDoor); + if (getInventory()->hasItem(kItemBriefcase)) + getInventory()->removeItem(kItemBriefcase); + + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarKronos, 81); + getSound()->playSound(kEntityPlayer, "LIB015"); + break; + } + break; + + case kAction138085344: + setup_function23(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Kronos, function23) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInKronosSanctum(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaWrongDoor); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventKahinaWrongDoor); + + if (getInventory()->hasItem(kItemBriefcase)) + getInventory()->removeItem(kItemBriefcase); + + getSound()->playSound(kEntityPlayer, "BUMP"); + + getScenes()->loadSceneFromPosition(kCarKronos, 81); + + getSound()->playSound(kEntityPlayer, "LIB015"); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Kronos, chapter4) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityKronos); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Kronos, chapter5) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityKronos); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/kronos.h b/engines/lastexpress/entities/kronos.h new file mode 100644 index 0000000000..5d8efbd4c2 --- /dev/null +++ b/engines/lastexpress/entities/kronos.h @@ -0,0 +1,138 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_KRONOS_H +#define LASTEXPRESS_KRONOS_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Kronos : public Entity { +public: + Kronos(LastExpressEngine *engine); + ~Kronos() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Plays sound + * + * @param savepoint The savepoint + * - the sound filename + */ + DECLARE_FUNCTION_NOSETUP(playSound) + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint + * - Time to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTime) + + /** + * Updates parameter 2 using ticks value + * + * @param savepoint The savepoint + * - ticks to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTicks) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function9) + DECLARE_FUNCTION(function10) + DECLARE_FUNCTION(function11) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION(function16) + DECLARE_FUNCTION(function17) + DECLARE_FUNCTION(function18) + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_KRONOS_H diff --git a/engines/lastexpress/entities/mahmud.cpp b/engines/lastexpress/entities/mahmud.cpp new file mode 100644 index 0000000000..0200f0b554 --- /dev/null +++ b/engines/lastexpress/entities/mahmud.cpp @@ -0,0 +1,839 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/data/scene.h" + +#include "lastexpress/entities/mahmud.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Mahmud::Mahmud(LastExpressEngine *engine) : Entity(engine, kEntityMahmud) { + ADD_CALLBACK_FUNCTION(Mahmud, reset); + ADD_CALLBACK_FUNCTION(Mahmud, draw); + ADD_CALLBACK_FUNCTION(Mahmud, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Mahmud, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Mahmud, playSound); + ADD_CALLBACK_FUNCTION(Mahmud, playSoundMertens); + ADD_CALLBACK_FUNCTION(Mahmud, updateFromTime); + ADD_CALLBACK_FUNCTION(Mahmud, savegame); + ADD_CALLBACK_FUNCTION(Mahmud, updateEntity); + ADD_CALLBACK_FUNCTION(Mahmud, function10); + ADD_CALLBACK_FUNCTION(Mahmud, function11); + ADD_CALLBACK_FUNCTION(Mahmud, function12); + ADD_CALLBACK_FUNCTION(Mahmud, function13); + ADD_CALLBACK_FUNCTION(Mahmud, chaptersHandler); + ADD_CALLBACK_FUNCTION(Mahmud, chapter1); + ADD_CALLBACK_FUNCTION(Mahmud, resetChapter); + ADD_CALLBACK_FUNCTION(Mahmud, chapter2); + ADD_CALLBACK_FUNCTION(Mahmud, chapter3); + ADD_CALLBACK_FUNCTION(Mahmud, chapter4); + ADD_CALLBACK_FUNCTION(Mahmud, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Mahmud, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(2, Mahmud, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Mahmud, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIII(4, Mahmud, enterExitCompartment2, ObjectIndex, uint32, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param7, getState()->timeTicks, params->param5); + + if (!getScenes()->checkPosition(kSceneNone, SceneManager::kCheckPositionLookingUp)) + getScenes()->loadSceneFromObject((ObjectIndex)params->param6, true); + break; + + case kActionExitCompartment: + getEntities()->exitCompartment(kEntityMahmud, (ObjectIndex)params->param4); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityMahmud, (char *)¶ms->seq); + getEntities()->enterCompartment(kEntityMahmud, (ObjectIndex)params->param4); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(5, Mahmud, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Mahmud, playSoundMertens) + Entity::playSound(savepoint, false, getSound()->getSoundFlag(kEntityMertens)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(7, Mahmud, updateFromTime) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Mahmud, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(9, Mahmud, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + if (getInventory()->hasItem(kItemPassengerList)) + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1025" : "CAT1025Q"); + else + getSound()->excuseMeCath(); + + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param6, getState()->time, 13500); + + getObjects()->update(kObjectCompartment5, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_enterExitCompartment("614Ed", kObjectCompartment4); + break; + + case kActionEndSound: + case kActionDrawScene: + if (!getSound()->isBuffered(kEntityMahmud)) { + EntityPosition position = getEntityData(kEntityPlayer)->entityPosition; + if (position < kPosition_1500 || position >= kPosition_5790 || (position > kPosition_4455 && params->param5 != 5)) { + getObjects()->update(kObjectCompartment5, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(3); + setup_enterExitCompartment("614Ed", kObjectCompartment4); + } + } + break; + + case kActionKnock: + case kActionOpenDoor: + if (!getSound()->isBuffered((savepoint.action == kActionKnock) ? "LIB012" : "LIB013", true)) + getSound()->playSound(kEntityPlayer, (savepoint.action == kActionKnock) ? "LIB012" : "LIB013"); + + params->param5 = savepoint.param.intValue; + + if (!getSound()->isBuffered(kEntityMahmud)) { + params->param3++; + + switch(params->param3) { + default: + params->param4 = 1; + break; + + case 1: + getSound()->playSound(kEntityMahmud, "MAH1174"); + break; + + case 2: + getSound()->playSound(kEntityMahmud, "MAH1173B"); + break; + + case 3: + getSound()->playSound(kEntityMahmud, params->param2 ? "MAH1170E" : "MAH1173A"); + break; + } + } + + if (params->param4) { + if (getState()->time >= kTimeCityGalanta) { + params->param3 = 0; + } else { + getSound()->playSound(kEntityTrain, "LIB050", SoundManager::kFlagDefault); + getLogic()->gameOver(kSavegameTypeIndex, 0, (getProgress().chapter == kChapter1) ? kSceneGameOverPolice1 : kSceneGameOverPolice2, true); + } + break; + } + + getAction()->handleOtherCompartment((ObjectIndex)savepoint.param.intValue, false, false); + + switch (getScenes()->get(getState()->scene)->position) { + default: + break; + + case 55: + getScenes()->loadSceneFromObject(kObjectCompartment5, true); + break; + + case 56: + getScenes()->loadSceneFromObject(kObjectCompartment6, true); + break; + + case 57: + getScenes()->loadSceneFromObject(kObjectCompartment7, true); + break; + + case 58: + getScenes()->loadSceneFromObject(kObjectCompartment8, true); + break; + } + break; + + case kActionDefault: + getSound()->playSound(kEntityMahmud, params->param2 ? "MAH1170A" : "MAH1173", SoundManager::kFlagInvalid, 45); + getProgress().field_C4 = 1; + + setCallback(1); + setup_enterExitCompartment2("614Dd", kObjectCompartment4, 30, (ObjectIndex)params->param1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartment5, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->location = kLocationOutsideCompartment; + + getEntities()->drawSequenceLeft(kEntityMahmud, "614Md"); + getEntities()->enterCompartment(kEntityMahmud, kObjectCompartment4, true); + break; + + case 2: + case 3: + getEntities()->exitCompartment(kEntityMahmud, kObjectCompartment4, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMahmud); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Mahmud, function11) + switch (savepoint.action) { + default: + break; + + case kActionKnock: + case kActionOpenDoor: { + getSound()->playSound(kEntityPlayer, (savepoint.action == kActionKnock ? "LIB012" : "LIB013")); + + if (!getSound()->isBuffered(kEntityMahmud)) { + params->param1++; + + getSound()->playSound(kEntityMahmud, (params->param1 == 1 ? "MAH1170E" : (params->param1 == 2 ? "MAH1173B" : "MAH1174"))); + } + + switch (getScenes()->get(getState()->scene)->position) { + default: + break; + + case 55: + getScenes()->loadSceneFromObject(kObjectCompartment5, true); + break; + + case 56: + getScenes()->loadSceneFromObject(kObjectCompartment6, true); + break; + + case 57: + getScenes()->loadSceneFromObject(kObjectCompartment7, true); + break; + + case 58: + getScenes()->loadSceneFromObject(kObjectCompartment8, true); + break; + } + break; + } + + case kActionDefault: + getSavePoints()->push(kEntityMahmud, kEntityMertens, kAction102227384); + setCallback(1); + setup_enterExitCompartment("614Ad", kObjectCompartment4); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getEntities()->drawSequenceLeft(kEntityMahmud, "614Kd"); + getEntities()->enterCompartment(kEntityMahmud, kObjectCompartment4, true); + + setCallback(2); + setup_playSound("MAH1170A"); + break; + + case 2: + setCallback(3); + setup_playSoundMertens("MAH1170B"); + break; + + case 3: + setCallback(4); + setup_playSound("MAH1170C"); + break; + + case 4: + setCallback(5); + setup_playSoundMertens("MAH1170D"); + break; + + case 5: + setCallback(6); + setup_playSound("MAH1170E"); + break; + + case 6: + setCallback(7); + setup_playSoundMertens("MAH1170F"); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment("614Ld", kObjectCompartment4); + break; + + case 8: + getSavePoints()->push(kEntityMahmud, kEntityMertens, kAction156567128); + getEntities()->drawSequenceLeft(kEntityMahmud, "614Bd"); + getEntities()->enterCompartment(kEntityMahmud, kObjectCompartment4, true); + + setCallback(9); + setup_playSound("MAH1170G"); + break; + + case 9: + setCallback(10); + setup_playSoundMertens("MAH1170H"); + break; + + case 10: + getObjects()->update(kObjectCompartment5, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case 11: + getEntities()->exitCompartment(kEntityMahmud, kObjectCompartment4, true); + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityMahmud); + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction123852928: + if (getSound()->isBuffered(kEntityMahmud)) + getSound()->processEntry(kEntityMahmud); + + getObjects()->update(kObjectCompartment5, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(11); + setup_enterExitCompartment("614Cd", kObjectCompartment4); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// TODO: factorize code between function12 & function13 +IMPLEMENT_FUNCTION(12, Mahmud, function12) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("614Gd", kObjectCompartment4); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_4070); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("614Ff", kObjectCompartment6); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMahmud); + + setCallback(4); + setup_playSound("Har1105"); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("614Gf", kObjectCompartment6); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + setCallback(6); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("614Fd", kObjectCompartment4); + break; + + case 7: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMahmud); + + CALLBACK_ACTION(); + break; + + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Mahmud, function13) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("614Gd", kObjectCompartment4); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_2740); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("614Fh", kObjectCompartment8); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMahmud); + + setCallback(4); + setup_playSound("Har1107"); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("614Gh", kObjectCompartment8); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + setCallback(6); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("614Fd", kObjectCompartment4); + break; + + case 7: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMahmud); + + CALLBACK_ACTION(); + break; + + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Mahmud, chaptersHandler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(0, 1)) { + params->param2 = 1; + getSavePoints()->push(kEntityMahmud, kEntityMertens, kAction204379649); + ENTITY_PARAM(0, 1) = 0; + } + + if (!params->param2 && getProgress().chapter == kChapter1) { + + TIME_CHECK_CALLBACK(kTime1098000, params->param6, 1, setup_function13); + + if (!getSound()->isBuffered("HAR1104") && getState()->time > kTime1167300 && !params->param7) { + params->param7 = 1; + + setCallback(2); + setup_function12(); + break; + } + } + + if (params->param5) { + UPDATE_PARAM(params->param8, getState()->timeTicks, 75); + + params->param4 = 1; + params->param5 = 0; + + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorNormal, kCursorNormal); + } + + params->param8 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (params->param5) { + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorNormal, kCursorNormal); + + if (getProgress().jacket == kJacketBlood || getEvent(kEventMahmudWrongDoor) || getEvent(kEventMahmudWrongDoorOriginalJacket) || getEvent(kEventMahmudWrongDoorDay)) { + // Check if we have the passenger list + if (getInventory()->hasItem(kItemPassengerList)) { + setCallback(6); + setup_playSound(rnd(2) == 0 ? "CAT1501" : getSound()->wrongDoorCath()); + } else { + setCallback(7); + setup_playSound(getSound()->wrongDoorCath()); + } + } else { + setCallback(savepoint.action == kActionKnock ? 8 : 9); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + } else { + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 3 : 4); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityMahmud); + params->param3 = 1; + + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param4 || params->param5) { + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param4 = 0; + params->param5 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + return; + + case 1: + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param4 = 0; + params->param5 = 0; + + if (!getSound()->isBuffered("HAR1104") && getState()->time > kTime1167300 && !params->param7) { + params->param7 = 1; + setCallback(2); + setup_function12(); + break; + } + + params->param8 = 0; + break; + + case 2: + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param4 = 0; + params->param5 = 0; + params->param8 = 0; + break; + + case 3: + case 4: + setCallback(5); + setup_playSound("MAH1175"); + break; + + case 5: { + CursorStyle cursor = kCursorHand; + CursorStyle cursor2 = kCursorHandKnock; + + if (getProgress().jacket == kJacketBlood + || getEvent(kEventMahmudWrongDoor) + || getEvent(kEventMahmudWrongDoorOriginalJacket) + || getEvent(kEventMahmudWrongDoorDay)) { + cursor = kCursorNormal; + cursor2 = kCursorTalk; + } + + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation1, cursor, cursor2); + params->param5 = 1; + break; + } + + case 6: + case 7: + params->param4 = 1; + break; + + case 8: + case 9: + setCallback(10); + setup_savegame(kSavegameTypeEvent, kEventMahmudWrongDoor); + return; + + case 10: + getAction()->playAnimation((getProgress().jacket == kJacketGreen) ? (isNight() ? kEventMahmudWrongDoor : kEventMahmudWrongDoorDay) : kEventMahmudWrongDoorOriginalJacket); + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->processScene(); + + params->param4 = 1; + break; + + case 11: + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param4 = 0; + params->param5 = 0; + break; + + case 12: + getObjects()->update(kObjectCompartment4, kEntityMahmud, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param2 = 0; + params->param4 = 0; + params->param5 = 0; + break; + } + break; + + case kAction225563840: + setCallback(12); + setup_function11(); + break; + + case kAction290410610: + params->param3 = (params->param3 < 1) ? 1 : 0; + setCallback(11); + setup_function10((ObjectIndex)savepoint.param.intValue, (bool)params->param3); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Mahmud, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chaptersHandler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityMahmud, kAction170483072, 0); + + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject20, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Mahmud, resetChapter) + if (savepoint.action != kActionDefault) + return; + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getEntities()->clearSequences(kEntityMahmud); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Mahmud, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chaptersHandler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMahmud); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Mahmud, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chaptersHandler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMahmud); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Mahmud, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chaptersHandler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMahmud); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Mahmud, chapter5) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityMahmud); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/mahmud.h b/engines/lastexpress/entities/mahmud.h new file mode 100644 index 0000000000..0b65a8bcff --- /dev/null +++ b/engines/lastexpress/entities/mahmud.h @@ -0,0 +1,153 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_MAHMUD_H +#define LASTEXPRESS_MAHMUD_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Mahmud : public Entity { +public: + Mahmud(LastExpressEngine *engine); + ~Mahmud() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param savepoint The savepoint + * - The sequence to draw + */ + DECLARE_FUNCTION_NOSETUP(draw) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + * @param ticks The time ticks + * @param object The object for loading the scene + */ + DECLARE_FUNCTION_4(enterExitCompartment2, const char* sequence, ObjectIndex compartment, uint32 ticks, ObjectIndex object) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSoundMertens, const char* filename) + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint + * - Time to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTime) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_2(function10, ObjectIndex, bool) + DECLARE_FUNCTION(function11) + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION(function13) + + /** + * Handle chapters events + */ + DECLARE_FUNCTION(chaptersHandler) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Reset chapter data + */ + DECLARE_FUNCTION(resetChapter) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_MAHMUD_H diff --git a/engines/lastexpress/entities/max.cpp b/engines/lastexpress/entities/max.cpp new file mode 100644 index 0000000000..5bc1c1f357 --- /dev/null +++ b/engines/lastexpress/entities/max.cpp @@ -0,0 +1,628 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/max.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Max::Max(LastExpressEngine *engine) : Entity(engine, kEntityMax) { + ADD_CALLBACK_FUNCTION(Max, reset); + ADD_CALLBACK_FUNCTION(Max, playSound); + ADD_CALLBACK_FUNCTION(Max, draw); + ADD_CALLBACK_FUNCTION(Max, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Max, savegame); + ADD_CALLBACK_FUNCTION(Max, chapter12_handler); + ADD_CALLBACK_FUNCTION(Max, function7); + ADD_CALLBACK_FUNCTION(Max, chapter4Handler); + ADD_CALLBACK_FUNCTION(Max, function9); + ADD_CALLBACK_FUNCTION(Max, chapter1); + ADD_CALLBACK_FUNCTION(Max, chapter2); + ADD_CALLBACK_FUNCTION(Max, chapter3); + ADD_CALLBACK_FUNCTION(Max, chapter3Handler); + ADD_CALLBACK_FUNCTION(Max, freeFromCage); + ADD_CALLBACK_FUNCTION(Max, function15); + ADD_CALLBACK_FUNCTION(Max, chapter4); + ADD_CALLBACK_FUNCTION(Max, function17); + ADD_CALLBACK_FUNCTION(Max, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Max, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Max, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(3, Max, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(4, Max, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(5, Max, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Max, chapter12_handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->time, params->param1); + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max1122"); + + params->param1 = 255 * (4 * rnd(20) + 40); + params->param2 = 0; + break; + + case kActionDefault: + params->param1 = 255 * (4 * rnd(20) + 40); + break; + + case kAction71277948: + setCallback(1); + setup_function7(); + break; + + case kAction158007856: + if (!getSound()->isBuffered(kEntityMax)) { + getSound()->playSound(kEntityMax, "Max1122"); + params->param1 = 255 * (4 * rnd(20) + 40); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Max, function7) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->time, params->param1) + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max1122"); + + params->param1 = 255 * (4 * rnd(20) + 40); + params->param2 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentF, kEntityMax, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject53, kEntityMax, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (getSound()->isBuffered(kEntityMax)) + getSound()->processEntry(kEntityMax); + + setCallback((savepoint.action == kActionKnock) ? 1 : 2); + setup_playSound((savepoint.action == kActionKnock) ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + params->param1 = 255 * (4 * rnd(20) + 40); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentF, kEntityMax, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityMax, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (!getSound()->isBuffered(kEntityMax)) { + if (getEntities()->isPlayerPosition(kCarRedSleeping, 56) || getEntities()->isPlayerPosition(kCarRedSleeping, 78)) + getSound()->playSound(kEntityMax, "Max1120"); + } + break; + + case kActionCallback: + switch (getCallback()) { + case 0: + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound("Max1122"); + break; + + case 3: + getObjects()->update(kObjectCompartmentF, kEntityMax, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityMax, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + + case kAction101687594: + getEntities()->clearSequences(kEntityMax); + + CALLBACK_ACTION(); + break; + + case kAction122358304: + case kActionMaxFreeFromCage: + getSavePoints()->push(kEntityMax, kEntityMax, kActionMaxFreeFromCage); + getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject53, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + + case kAction158007856: + if (!getSound()->isBuffered(kEntityMax)) { + getSound()->playSound(kEntityMax, "Max1122"); + params->param1 = 255 * (4 * rnd(20) + 40); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Max, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param3, getState()->time, params->param2); + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max3101"); + + params->param2 = 255 * (4 * rnd(20) + 40); + params->param3 = 0; + break; + + case kActionOpenDoor: + if (params->param1) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCathMaxLickHand); + break; + } + + if (getSound()->isBuffered(kEntityMax)) + getSound()->processEntry(kEntityMax); + + getAction()->playAnimation(kEventCathMaxLickHand); + getScenes()->processScene(); + + params->param1 = 1; + break; + + case kActionDefault: + params->param2 = 255 * (4 * rnd(20) + 40); + + getObjects()->update(kObjectCageMax, kEntityMax, kObjectLocationNone, kCursorNormal, kCursorHand); + getEntities()->clearSequences(kEntityMax); + + getData()->entityPosition = kPosition_8000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarBaggage; + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max3101"); + break; + + case kActionCallback: + if (getCallback() != 1) + break; + + if (getSound()->isBuffered(kEntityMax)) + getSound()->processEntry(kEntityMax); + + getSound()->playSound(kEntityPlayer, "LIB026"); + getAction()->playAnimation(kEventCathMaxFree); + getScenes()->loadSceneFromPosition(kCarBaggage, 92); + getObjects()->update(kObjectCageMax, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + setup_function9(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Max, function9) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 == kTimeInvalid || !getState()->time) + break; + + if (params->param1 >= getState()->time) { + if (!getEntities()->hasValidFrame(kEntityMax) || !params->param2) { + + params->param2 = getState()->time; + if (!params->param2) + goto setup_functions; + } + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + +setup_functions: + if (getProgress().chapter == kChapter3) + setup_function15(); + + if (getProgress().chapter == kChapter4) + setup_function17(); + break; + + ////////////////////////////////////////////////////////////////////////// + // Draw Max outside of cage + case kActionDefault: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->drawSequenceLeft(kEntityMax, "630Af"); + getEntities()->enterCompartment(kEntityMax, kObjectCompartmentF, true); + + params->param1 = getState()->time + 2700; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Max, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter12_handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Max, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter12_handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMax); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Max, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMax); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Max, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2) { + getData()->entityPosition = getEntityData(kEntityCoudert)->entityPosition; + break; + } + + UPDATE_PARAM(params->param3, getState()->time, params->param1); + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max1122"); + + params->param1 = 255 * (4 * rnd(20) + 40); + params->param3 = 0; + break; + + case kActionDefault: + params->param1 = 255 * (4 * rnd(20) + 40); + + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + + case kAction71277948: + setCallback(1); + setup_function7(); + break; + + case kAction122358304: + params->param2 = 1; + break; + + case kActionMaxFreeFromCage: + setup_freeFromCage(); + break; + + case kAction158007856: + if (params->param2) + break; + + if (!getSound()->isBuffered(kEntityMax)) { + getSound()->playSound(kEntityMax, "Max1122"); + params->param1 = 255 * (4 * rnd(20) + 40); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Max, freeFromCage) + switch (savepoint.action) { + default: + break; + + case kActionNone: + break; + + case kActionEndSound: + getSound()->playSound(kEntityMax, "Max1122"); + break; + + ////////////////////////////////////////////////////////////////////////// + // Save game after freeing Max from his cage + case kActionOpenDoor: + if (getEvent(kEventCathMaxCage)) { + if (getEvent(kEventCathMaxFree)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventCathMaxFree); + } + + } else { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCathMaxCage); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCageMax, kEntityMax, kObjectLocationNone, kCursorNormal, kCursorHand); + + getData()->entityPosition = kPosition_8000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarBaggage; + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max1122"); + break; + + ////////////////////////////////////////////////////////////////////////// + // Play animation for Max in the cage and after opening it + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getSound()->isBuffered(kEntityMax)) + getSound()->removeFromQueue(kEntityMax); + + getAction()->playAnimation(kEventCathMaxCage); + getSound()->setupEntry(SoundManager::kSoundType7, kEntityMax); + getScenes()->processScene(); + break; + + case 2: + if (getSound()->isBuffered(kEntityMax)) + getSound()->processEntry(kEntityMax); + + getSound()->playSound(kEntityPlayer, "LIB026"); + getAction()->playAnimation(kEventCathMaxFree); + getScenes()->loadSceneFromPosition(kCarBaggage, 92); + getObjects()->update(kObjectCageMax, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + setup_function9(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Max, function15) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2) { + getData()->entityPosition = getEntityData(kEntityCoudert)->entityPosition; + getData()->car = getEntityData(kEntityCoudert)->car; + } + + if (!params->param1) { + UPDATE_PARAM(params->param3, getState()->time, 900); + + getSavePoints()->push(kEntityMax, kEntityCoudert, kAction157026693); + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + if (!getSound()->isBuffered(kEntityMax)) + getSound()->playSound(kEntityMax, "Max3010"); + + setCallback(1); + setup_enterExitCompartment("630Bf", kObjectCompartment4); + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->drawSequenceLeft(kEntityMax, "630Af"); + getEntities()->enterCompartment(kEntityMax, kObjectCompartmentF, true); + getSavePoints()->push(kEntityMax, kEntityAnna, kAction156622016); + } + break; + + case kAction122358304: + (savepoint.entity2 == kEntityAnna) ? (params->param1 = 1) : (params->param2 = 1); + getEntities()->exitCompartment(kEntityMax, kObjectCompartmentF, true); + getEntities()->drawSequenceLeft(kEntityMax, "BLANK"); + break; + + case kActionMaxFreeFromCage: + getEntities()->exitCompartment(kEntityMax, kObjectCompartmentF, true); + setup_chapter4Handler(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Max, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMax); + + getData()->entityPosition = kPosition_8000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarBaggage; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Max, function17) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + getData()->entityPosition = getEntityData(kEntityCoudert)->entityPosition; + getData()->car = getEntityData(kEntityCoudert)->car; + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4070; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->drawSequenceLeft(kEntityMax, "630Af"); + getSavePoints()->push(kEntityMax, kEntityCoudert, kAction157026693); + break; + + case kAction122358304: + params->param1 = 1; + getEntities()->exitCompartment(kEntityMax, kObjectCompartmentF, true); + getEntities()->drawSequenceLeft(kEntityMax, "BLANK"); + break; + + case kActionMaxFreeFromCage: + getEntities()->exitCompartment(kEntityMax, kObjectCompartmentF, true); + setup_chapter4Handler(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Max, chapter5) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityMax); + + getData()->entityPosition = kPositionNone; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarNone; + + getObjects()->update(kObjectCageMax, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/max.h b/engines/lastexpress/entities/max.h new file mode 100644 index 0000000000..404ee42f5f --- /dev/null +++ b/engines/lastexpress/entities/max.h @@ -0,0 +1,129 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_MAX_H +#define LASTEXPRESS_MAX_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Max : public Entity { +public: + Max(LastExpressEngine *engine); + ~Max() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Draws the entity + * + * @param savepoint The savepoint + * - The sequence to draw + */ + DECLARE_FUNCTION_NOSETUP(draw) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Handle Chapter 1 & 2 events + */ + DECLARE_FUNCTION(chapter12_handler) + + DECLARE_FUNCTION(function7) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function9) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(freeFromCage) + DECLARE_FUNCTION(function15) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + DECLARE_FUNCTION(function17) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_MAX_H diff --git a/engines/lastexpress/entities/mertens.cpp b/engines/lastexpress/entities/mertens.cpp new file mode 100644 index 0000000000..a59a8eebe8 --- /dev/null +++ b/engines/lastexpress/entities/mertens.cpp @@ -0,0 +1,4113 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/mertens.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/state.h" +#include "lastexpress/game/sound.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +#define SAVEGAME_BLOOD_JACKET() \ + if (getProgress().jacket == kJacketBlood \ + && getEntities()->isDistanceBetweenEntities(kEntityMertens, kEntityPlayer, 1000) \ + && !getEntities()->isInsideCompartments(kEntityPlayer) \ + && !getEntities()->checkFields10(kEntityPlayer)) { \ + setCallback(1); \ + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); \ + } + +Mertens::Mertens(LastExpressEngine *engine) : Entity(engine, kEntityMertens) { + ADD_CALLBACK_FUNCTION(Mertens, reset); + ADD_CALLBACK_FUNCTION(Mertens, bloodJacket); + ADD_CALLBACK_FUNCTION(Mertens, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Mertens, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Mertens, enterExitCompartment3); + ADD_CALLBACK_FUNCTION(Mertens, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Mertens, playSound); + ADD_CALLBACK_FUNCTION(Mertens, playSound16); + ADD_CALLBACK_FUNCTION(Mertens, savegame); + ADD_CALLBACK_FUNCTION(Mertens, updateEntity); + ADD_CALLBACK_FUNCTION(Mertens, function11); + ADD_CALLBACK_FUNCTION(Mertens, bonsoir); + ADD_CALLBACK_FUNCTION(Mertens, function13); + ADD_CALLBACK_FUNCTION(Mertens, function14); + ADD_CALLBACK_FUNCTION(Mertens, function15); + ADD_CALLBACK_FUNCTION(Mertens, function16); + ADD_CALLBACK_FUNCTION(Mertens, function17); + ADD_CALLBACK_FUNCTION(Mertens, function18); + ADD_CALLBACK_FUNCTION(Mertens, function19); + ADD_CALLBACK_FUNCTION(Mertens, function20); + ADD_CALLBACK_FUNCTION(Mertens, function21); + ADD_CALLBACK_FUNCTION(Mertens, function22); + ADD_CALLBACK_FUNCTION(Mertens, function23); + ADD_CALLBACK_FUNCTION(Mertens, function24); + ADD_CALLBACK_FUNCTION(Mertens, function25); + ADD_CALLBACK_FUNCTION(Mertens, function26); + ADD_CALLBACK_FUNCTION(Mertens, tylerCompartment); + ADD_CALLBACK_FUNCTION(Mertens, function28); + ADD_CALLBACK_FUNCTION(Mertens, function29); + ADD_CALLBACK_FUNCTION(Mertens, function30); + ADD_CALLBACK_FUNCTION(Mertens, function31); + ADD_CALLBACK_FUNCTION(Mertens, function32); + ADD_CALLBACK_FUNCTION(Mertens, function33); + ADD_CALLBACK_FUNCTION(Mertens, chapter1); + ADD_CALLBACK_FUNCTION(Mertens, function35); + ADD_CALLBACK_FUNCTION(Mertens, function36); + ADD_CALLBACK_FUNCTION(Mertens, function37); + ADD_CALLBACK_FUNCTION(Mertens, function38); + ADD_CALLBACK_FUNCTION(Mertens, function39); + ADD_CALLBACK_FUNCTION(Mertens, function40); + ADD_CALLBACK_FUNCTION(Mertens, chapter1Handler); + ADD_CALLBACK_FUNCTION(Mertens, function42); + ADD_CALLBACK_FUNCTION(Mertens, chapter2); + ADD_CALLBACK_FUNCTION(Mertens, function44); + ADD_CALLBACK_FUNCTION(Mertens, chapter3); + ADD_CALLBACK_FUNCTION(Mertens, function46); + ADD_CALLBACK_FUNCTION(Mertens, chapter4); + ADD_CALLBACK_FUNCTION(Mertens, function48); + ADD_CALLBACK_FUNCTION(Mertens, function49); + ADD_CALLBACK_FUNCTION(Mertens, chapter5); + ADD_CALLBACK_FUNCTION(Mertens, chapter5Handler); + ADD_CALLBACK_FUNCTION(Mertens, function52); + ADD_CALLBACK_FUNCTION(Mertens, function53); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Mertens, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Mertens, bloodJacket) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityMertens, (char *)¶ms->seq1); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Mertens, enterExitCompartment, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + return; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + return; + } + + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(4, Mertens, enterExitCompartment2, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + return; + + case kAction4: + getEntities()->exitCompartment(kEntityMertens, (ObjectIndex)params->param4); + CALLBACK_ACTION(); + return; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + return; + } + + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIII(5, Mertens, enterExitCompartment3, ObjectIndex, EntityPosition, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionExitCompartment: + getEntities()->exitCompartment(_entityIndex, (ObjectIndex)params->param4); + getData()->entityPosition = (EntityPosition)params->param5; + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq); + getEntities()->enterCompartment(_entityIndex, (ObjectIndex)params->param4); + getData()->entityPosition = (EntityPosition)params->param5; + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, (EntityPosition)params->param5) || getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, (EntityPosition)params->param6)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject((ObjectIndex)params->param4); + } + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Mertens, callbackActionOnDirection) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getData()->direction != kDirectionRight) { + CALLBACK_ACTION(); + break; + } + + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(7, Mertens, playSound) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionEndSound: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getSound()->playSound(kEntityMertens, (char *)¶ms->seq1); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(8, Mertens, playSound16) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionEndSound: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getSound()->playSound(kEntityMertens, (char *)¶ms->seq1, SoundManager::kFlagDefault); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(9, Mertens, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Mertens, updateEntity, CarIndex, EntityPosition) + +#define LOADSCENE_FROM_POSITION() \ + if (getData()->direction != kDirectionUp) { \ + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750)); \ + } else { \ + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition - 750), true); \ + } + + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 && getEntities()->isDistanceBetweenEntities(kEntityMertens, kEntityPlayer, 2000)) + getData()->inventoryItem = (InventoryItem)(getData()->inventoryItem | kItemInvalid); + else + getData()->inventoryItem = (InventoryItem)(getData()->inventoryItem & kItemToggleHigh); + + if (!getEntities()->isDistanceBetweenEntities(kEntityMertens, kEntityPlayer, 1000) + || getEntities()->isInsideCompartments(kEntityPlayer) + || getEntities()->checkFields10(kEntityPlayer)) { + if (getEntities()->updateEntity(kEntityMertens, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + CALLBACK_ACTION(); + } + break; + } + + if (getProgress().jacket == kJacketBlood) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + } + + if ((ENTITY_PARAM(0, 6) || ENTITY_PARAM(0, 7)) && (!getEvent(kEventKronosConversation) && getProgress().jacket == kJacketGreen)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitation); + break; + } + + if (ENTITY_PARAM(1, 2) && getProgress().jacket == kJacketGreen && !getProgress().eventMetAugust) { + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventMertensAugustWaiting); + break; + } + + if (ENTITY_PARAM(2, 4) && getState()->time < kTime2133000) { + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosConcertInvitation); + break; + } + + if (getEntities()->updateEntity(kEntityMertens, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; + CALLBACK_ACTION(); + } + break; + + case kAction1: + params->param3 = 0; + if (getProgress().eventCorpseFound || getEvent(kEventMertensAskTylerCompartment) || getEvent(kEventMertensAskTylerCompartmentD)) { + if (ENTITY_PARAM(0, 4) && getProgress().jacket == kJacketGreen && !getEvent(kEventMertensDontMakeBed) && !getProgress().eventCorpseThrown) { + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventMertensDontMakeBed); + } + } else { + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventMertensAskTylerCompartment); + } + break; + + case kActionExcuseMeCath: + getSound()->playSound(kEntityMertens, "CON1110B"); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntityMertens); + break; + + case kActionDefault: + if ((!getProgress().eventCorpseFound && !getEvent(kEventMertensAskTylerCompartment) && !getEvent(kEventMertensAskTylerCompartment)) + || (ENTITY_PARAM(0, 4) && getProgress().jacket == kJacketGreen && !getEvent(kEventMertensDontMakeBed) && !getProgress().eventCorpseThrown)) + params->param3 = 1; + + if (getEntities()->updateEntity(kEntityMertens, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 2: + getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventMertensKronosInvitation : kEventMertensKronosInvitationClosedWindows); + getProgress().eventMertensKronosInvitation = true; + + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + + if (params->param1 != 3 || (params->param2 != kPosition_8200 && params->param2 != kPosition_9510)) { + LOADSCENE_FROM_POSITION(); + break; + } + + getData()->inventoryItem = kItemNone; + + if (getData()->car == kCarGreenSleeping && getEntities()->checkDistanceFromPosition(kEntityMertens, kPosition_2000, 500)) + getData()->entityPosition = kPosition_2500; + + getEntities()->updateEntity(kEntityMertens, kCarGreenSleeping, kPosition_2000); + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750)); + + CALLBACK_ACTION(); + break; + + case 3: + getAction()->playAnimation(kEventMertensAugustWaiting); + getProgress().eventMertensAugustWaiting = true; + + ENTITY_PARAM(1, 2) = 0; + + if (params->param1 == 3 && params->param2 == kPosition_8200) { + if (getData()->car == kCarGreenSleeping && getEntities()->checkDistanceFromPosition(kEntityMertens, kPosition_2000, 500)) + getData()->entityPosition = kPosition_2500; + + getEntities()->updateEntity(kEntityMertens, kCarGreenSleeping, kPosition_2000); + getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750)); + + CALLBACK_ACTION(); + break; + } + + LOADSCENE_FROM_POSITION(); + break; + + case 4: + getAction()->playAnimation(kEventMertensKronosConcertInvitation); + ENTITY_PARAM(2, 4) = 0; + + LOADSCENE_FROM_POSITION(); + break; + + case 5: + getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventMertensAskTylerCompartmentD : kEventMertensAskTylerCompartment); + LOADSCENE_FROM_POSITION(); + break; + + case 6: + getAction()->playAnimation(kEventMertensDontMakeBed); + LOADSCENE_FROM_POSITION(); + ENTITY_PARAM(0, 4) = 0; + break; + } + break; + } + +#undef LOADSCENE_FROM_POSITION +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(11, Mertens, function11, uint32) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + + UPDATE_PARAM(params->param2, getState()->time, params->param1) + + CALLBACK_ACTION(); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(12, Mertens, bonsoir, EntityIndex) + EntityIndex entity = (EntityIndex)params->param1; + + if (savepoint.action == kActionDefault) + return; + + if (getSound()->isBuffered(kEntityMertens)) { + CALLBACK_ACTION(); + return; + } + + if (isNight()) { + if (Entities::isFemale(entity)) { + getSound()->playSound(kEntityMertens, rnd(2) ? "CON1112" : "CON1112A"); + } else { + if (entity || getProgress().field_18 != 2) { + getSound()->playSound(kEntityMertens, "CON1112F"); + } else { + switch (rnd(3)) { + default: + case 0: + getSound()->playSound(kEntityMertens, "CON1061"); + break; + + case 1: + getSound()->playSound(kEntityMertens, "CON1110G"); + break; + + case 2: + getSound()->playSound(kEntityMertens, "CON1110H"); + break; + } + } + } + } else { + if (Entities::isFemale(entity)) + getSound()->playSound(kEntityMertens, rnd(2) ? "CON1112B" : "CON1112C"); + else + getSound()->playSound(kEntityMertens, "CON1112G"); + } + + CALLBACK_ACTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + + if (!params->param2 && !params->param3) { + UPDATE_PARAM_PROC(params->param4, getState()->timeTicks, 75) + getData()->inventoryItem = kItemNone; + setCallback(5); + setup_function18(); + break; + UPDATE_PARAM_PROC_END + } + + UPDATE_PARAM_PROC(params->param5, getState()->timeTicks, 225) + getData()->inventoryItem = kItemNone; + setCallback(6); + setup_function18(); + break; + UPDATE_PARAM_PROC_END + + getData()->inventoryItem = (getProgress().chapter == kChapter1 + && !ENTITY_PARAM(2, 1) + && !getProgress().eventCorpseFound + && !getEvent(kEventMertensAskTylerCompartment) + && !getEvent(kEventMertensAskTylerCompartmentD)) ? kItemMatchBox : kItemNone; + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + setCallback(7); + setup_savegame(kSavegameTypeEvent, kEventMertensAskTylerCompartmentD); + break; + + case kAction11: + params->param3++; + setCallback(11); + setup_bonsoir(savepoint.entity2); + break; + + case kActionDefault: + if (params->param2) + params->param3 = 1; + + if (!getSound()->isBuffered(kEntityMertens)) { + + } + + setCallback(3); + setup_function20(); + break; + + case kAction16: + params->param3--; + + if (params->param2 && !params->param3) { + getData()->inventoryItem = kItemNone; + setCallback(10); + setup_function18(); + } + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23) && ENTITY_PARAM(0, 7) && !getEvent(kEventKronosConversation)) { + setCallback(8); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitation); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_function20(); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntityMertens, params->param1 ? "601I" : "601H"); + break; + + case 4: + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 5: + case 6: + case 9: + case 10: + CALLBACK_ACTION(); + break; + + case 7: + getAction()->playAnimation(kEventMertensAskTylerCompartmentD); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 25); + break; + + case 8: + getAction()->playAnimation(kEventMertensKronosInvitation); + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + getScenes()->processScene(); + + if (!params->param3) { + getData()->inventoryItem = kItemNone; + setCallback(10); + setup_function18(); + } + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(14, Mertens, function14, EntityIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + SAVEGAME_BLOOD_JACKET(); + break; + + case kActionDefault: + getData()->inventoryItem = kItemNone; + + if (ENTITY_PARAM(2, 1)) { + ENTITY_PARAM(2, 1) = 0; + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_1500); + } else { + setCallback(1); + setup_function11(15); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityMertens, (EntityIndex)params->param1, kAction202558662); + + setCallback(2); + setup_function20(); + break; + + case 2: + getSavePoints()->push(kEntityMertens, (EntityIndex)params->param1, kAction155853632); + getEntities()->drawSequenceLeft(kEntityMertens, "601K"); + break; + + case 3: + getSavePoints()->push(kEntityMertens, (EntityIndex)params->param1, kAction202558662); + getSavePoints()->push(kEntityMertens, (EntityIndex)params->param1, kAction155853632); + getEntities()->drawSequenceLeft(kEntityMertens, "601K"); + getScenes()->loadSceneFromItemPosition(kItem7); + break; + + case 4: + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + + case kAction125499160: + if (params->param1 == kEntityVerges) + ENTITY_PARAM(0, 8) = 0; + + setCallback(5); + setup_function18(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(15, Mertens, function15, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_4070); + break; + + case 2: + getSound()->playSound(kEntityMertens, params->param1 ? "CON1059A" : "CON1059"); + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_7500); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("601Xb", kObjectCompartment2); + break; + + case 4: + getSavePoints()->push(kEntityMertens, kEntityAlexei, kAction135664192); + + setCallback(5); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 5: + setCallback(6); + setup_function17(); + break; + + case 6: + CALLBACK_ACTION();; + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(16, Mertens, function16, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_4070); + break; + + case 2: + switch (rnd(4)) { + default: + break; + + case 0: + getSound()->playSound(kEntityMertens, "AUG2095A"); + break; + + case 1: + getSound()->playSound(kEntityMertens, "AUG2096A"); + break; + + case 2: + getSound()->playSound(kEntityMertens, "AUG2094B"); + break; + + case 3: + getSound()->playSound(kEntityMertens, "AUG2094C"); + break; + } + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case 3: + getSound()->playSound(kEntityMertens, params->param1 ? "AUG2097" : "AUG2098"); + + setCallback(4); + setup_enterExitCompartment("601Xc", kObjectCompartment3); + break; + + case 4: + getSavePoints()->push(kEntityMertens, kEntityAugust, kAction69239528); + + setCallback(5); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 5: + setCallback(6); + setup_function17(); + break; + + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Mertens, function17) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + // FIXME: Check that we are using the correct parameter struct + if (ENTITY_PARAM(0, 6) || ((EntityData::EntityParametersIIII*)_data->getParameters(8, 1))->hasNonNullParameter()) { + getInventory()->setLocationAndProcess(kItem7, kObjectLocation1); + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + } + + if (ENTITY_PARAM(0, 8)) { + getEntities()->drawSequenceLeft(kEntityMertens, "601K"); + getScenes()->loadSceneFromItemPosition(kItem7); + ENTITY_PARAM(2, 1) = 1; + + CALLBACK_ACTION(); + break; + } + + // Mertens sits on his chair at the back of the train + if (!getInventory()->hasItem(kItemPassengerList) || ENTITY_PARAM(0, 2)) { + getEntities()->drawSequenceRight(kEntityMertens, "601A"); + } else { + // Got the passenger list, Mertens is looking for it before sitting + ENTITY_PARAM(0, 2) = 1; + getSound()->playSound(kEntityMertens, "CON1058", SoundManager::kFlagInvalid, 75); + getEntities()->drawSequenceRight(kEntityMertens, "601D"); + } + + getScenes()->loadSceneFromItemPosition(kItem7); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 68)) { + getSound()->playSound(kEntityPlayer, "CON1110"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 25); + } + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityMertens); + ENTITY_PARAM(2, 1) = 1; + setCallback(2); + setup_function11(75); + break; + + case 2: + CALLBACK_ACTION(); + break; + + case 3: + if (!ENTITY_PARAM(0, 3) + && !getInventory()->hasItem(kItemPassengerList) + && ENTITY_PARAM(0, 2)) { + getSavePoints()->push(kEntityMertens, kEntityVerges, kAction158617345); + ENTITY_PARAM(0, 3) = 1; + } + + getEntities()->drawSequenceLeft(kEntityMertens, "601B"); + + ENTITY_PARAM(0, 1) = 0; + getData()->inventoryItem = kItemNone; + + getSavePoints()->push(kEntityMertens, kEntityMertens, kActionDrawScene); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Mertens, function18) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(0, 6) + || ENTITY_PARAM(1, 1) + || ENTITY_PARAM(1, 2) + || ENTITY_PARAM(1, 3) + || ENTITY_PARAM(1, 4) + || ENTITY_PARAM(1, 5) + || ENTITY_PARAM(1, 6) + || ENTITY_PARAM(1, 7) + || ENTITY_PARAM(1, 8)) { + getInventory()->setLocationAndProcess(kItem7, kObjectLocation1); + ENTITY_PARAM(2, 1) = 1; + + CALLBACK_ACTION(); + break; + } + + if (ENTITY_PARAM(0, 8)) { + getScenes()->loadSceneFromItemPosition(kItem7); + ENTITY_PARAM(2, 1) = 1; + + CALLBACK_ACTION(); + break; + } + + if (!getInventory()->hasItem(kItemPassengerList) || ENTITY_PARAM(0, 2)) { + getEntities()->drawSequenceRight(kEntityMertens, "601A"); + } else { + ENTITY_PARAM(0, 2) = 1; + getSound()->playSound(kEntityMertens, "CON1058", SoundManager::kFlagInvalid, 75); + getEntities()->drawSequenceRight(kEntityMertens, "601D"); + } + + getScenes()->loadSceneFromItemPosition(kItem7); + + setCallback(1); + setup_callbackActionOnDirection(); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (!ENTITY_PARAM(0, 3) + && !getInventory()->hasItem(kItemPassengerList) + && ENTITY_PARAM(0, 2)) { + getSavePoints()->push(kEntityMertens, kEntityVerges, kAction158617345); + ENTITY_PARAM(0, 3) = 1; + } + + getEntities()->drawSequenceLeft(kEntityMertens, "601B"); + ENTITY_PARAM(0, 1) = 0; + getData()->inventoryItem = kItemNone; + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Mertens, function19) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(2, 1)) { + getInventory()->setLocationAndProcess(kItem7, kObjectLocation1); + ENTITY_PARAM(2, 1) = 0; + CALLBACK_ACTION(); + } else { + setCallback(1); + setup_bloodJacket("601C"); + } + break; + + case kActionCallback: + if (getCallback() == 1) { + getInventory()->setLocationAndProcess(kItem7, kObjectLocation1); + + if (!getEntities()->isPlayerPosition(kCarGreenSleeping, 2)) + getData()->entityPosition = kPosition_2088; + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Mertens, function20) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getScenes()->loadSceneFromItemPosition(kItem7); + + if (ENTITY_PARAM(2, 1)) { + ENTITY_PARAM(2, 1) = 0; + + CALLBACK_ACTION(); + } else { + setCallback(1); + setup_bloodJacket("601C"); + } + break; + + case kActionCallback: + if (getCallback() == 1) + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(21, Mertens, function21, ObjectIndex, ObjectIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(CURRENT_PARAMS(1, 4), getState()->time, 300) + getSound()->playSound(kEntityPlayer, "ZFX1004", getSound()->getSoundFlag(kEntityMertens)); + UPDATE_PARAM_PROC_END + + UPDATE_PARAM(CURRENT_PARAMS(1, 5), getState()->time, 900); + + // Update objects + getObjects()->updateLocation2((ObjectIndex)params->param1, kObjectLocation1); + if (params->param5 != kObjectLocation2) + getObjects()->update((ObjectIndex)params->param1, (EntityIndex)params->param4, (ObjectLocation)params->param5, (CursorStyle)params->param6, (CursorStyle)params->param7); + + if (params->param2) + getObjects()->update((ObjectIndex)params->param2, (EntityIndex)params->param8, (ObjectLocation)CURRENT_PARAMS(1, 1), (CursorStyle)CURRENT_PARAMS(1, 2), (CursorStyle)CURRENT_PARAMS(1, 3)); + + CALLBACK_ACTION(); + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update((ObjectIndex)params->param1, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); + if (params->param2) + getObjects()->update((ObjectIndex)params->param2, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + params->param3 = 1; + params->param4 = getObjects()->get((ObjectIndex)params->param1).entity; + params->param5 = getObjects()->get((ObjectIndex)params->param1).location; + params->param6 = getObjects()->get((ObjectIndex)params->param1).cursor; + params->param7 = getObjects()->get((ObjectIndex)params->param1).cursor2; + + if (params->param2) { + params->param8 = getObjects()->get((ObjectIndex)params->param2).entity; + CURRENT_PARAMS(1, 1) = getObjects()->get((ObjectIndex)params->param2).location; + CURRENT_PARAMS(1, 2) = getObjects()->get((ObjectIndex)params->param2).cursor; + CURRENT_PARAMS(1, 3) = getObjects()->get((ObjectIndex)params->param2).cursor2; + + getObjects()->update((ObjectIndex)params->param2, kEntityMertens, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + + if (params->param5 != kObjectLocation2) + getObjects()->update((ObjectIndex)params->param1, kEntityMertens, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(params->param3 ? 3 : 4); + setup_playSound(params->param3 ? "Con1017" : "Con1017A"); + break; + + case 3: + case 4: + params->param3 = 0; + getObjects()->update((ObjectIndex)params->param1, kEntityMertens, kObjectLocation1, kCursorHandKnock, kCursorHand); + + if (params->param2) + getObjects()->update((ObjectIndex)params->param2, kEntityMertens, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Mertens, function22) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_2740); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("601Mh", kObjectCompartment8); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMertens, "601Nh"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment8, true); + + setCallback(3); + setup_function11(150); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("601Mh", kObjectCompartment8); + break; + + case 4: + getEntities()->drawSequenceLeft(kEntityMertens, "601Nh"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment8); + getSavePoints()->push(kEntityMertens, kEntityMahmud, kAction225563840); + break; + + case 5: + if (!getSound()->isBuffered(kEntityMertens)) + getSound()->playSound(kEntityMertens, "MAH1170I"); + + setCallback(6); + setup_enterExitCompartment("601Zd", kObjectCompartment4); + break; + + case 6: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + if (!getSound()->isBuffered(kEntityMertens)) + getSound()->playSound(kEntityMertens, "MAH1172", SoundManager::kFlagInvalid, 225); + + setCallback(7); + setup_function21(kObjectCompartment4, kObject20); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment("671Ad", kObjectCompartment4); + break; + + case 8: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityMertens, kEntityMahmud, kAction123852928); + + setCallback(9); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + + break; + + case 9: + CALLBACK_ACTION(); + break; + } + break; + + case kAction102227384: + getEntities()->drawSequenceLeft(kEntityMertens, "671Dh"); + break; + + case kAction156567128: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment8, true); + + setCallback(5); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Mertens, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("601Vd", kObjectCompartment4); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMertens, "601Wd"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment4, true); + + setCallback(3); + setup_function11(150); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("601Zd", kObjectCompartment4); + break; + + case 4: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment4); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + setCallback(5); + setup_function21(kObjectCompartment4, kObject20); + break; + + case 5: + setCallback(6); + setup_enterExitCompartment("671Ad", kObjectCompartment4); + break; + + case 6: + getData()->location = kLocationOutsideCompartment; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Mertens, function24) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + UPDATE_PARAM(params->param2, getState()->timeTicks, 75); + + setCallback(3); + setup_enterExitCompartment3("601Rc", kObjectCompartment3, kPosition_6470, kPosition_6130); + } + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_6470); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("601Mc", kObjectCompartment3); + break; + + case 2: + getSavePoints()->push(kEntityMertens, kEntityAugust, kAction221617184); + getEntities()->drawSequenceLeft(kEntityMertens, "601Nc"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment3, true); + break; + + case 3: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment3, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + setCallback(4); + setup_function21(kObjectCompartment3, kObjectKitchen); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("601Sc", kObjectCompartment3); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + CALLBACK_ACTION(); + break; + + case 6: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment3, true); + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + setCallback(7); + setup_function21(kObjectCompartment3, kObjectKitchen); + break; + + case 7: + getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(8); + setup_enterExitCompartment("601Uc", kObjectCompartment3); + break; + + case 8: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityMertens, kEntityAugust, kAction124697504); + + setCallback(9); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + + case 9: + CALLBACK_ACTION(); + break; + } + break; + + case kAction100906246: + getSavePoints()->push(kEntityMertens, kEntityAugust, kAction192849856); + getEntities()->drawSequenceLeft(kEntityMertens, "601Qc"); + break; + + case kAction102675536: + params->param1 = 1; + break; + + case kAction156567128: + setCallback(6); + setup_enterExitCompartment("601Tc", kObjectCompartment3); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Mertens, function25) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + UPDATE_PARAM(params->param2, getState()->timeTicks, 75); + + setCallback(3); + setup_enterExitCompartment3("601Zb", kObjectCompartment2, kPosition_7500, kPositionNone); + } + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("601Vb", kObjectCompartment2); + break; + + case 2: + getSavePoints()->push(kEntityMertens, kEntityAlexei, kAction221617184); + getEntities()->drawSequenceLeft(kEntityMertens, "601Wb"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment2, true); + break; + + case 3: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment2, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + if (getProgress().chapter == kChapter1 && ENTITY_PARAM(0, 4)) + if (getProgress().field_14 != 29) + getProgress().field_14 = 3; + + setCallback(4); + setup_function21(kObjectCompartment2, kObjectHandleInsideBathroom); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("671Ab", kObjectCompartment2); + break; + + case 5: + getData()->location = kLocationOutsideCompartment; + + CALLBACK_ACTION(); + break; + + case 6: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment2, true); + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + if (getProgress().chapter == kChapter1 && ENTITY_PARAM(0, 4)) + if (getProgress().field_14 != 29) + getProgress().field_14 = 3; + + setCallback(7); + setup_function21(kObjectCompartment2, kObjectHandleInsideBathroom); + break; + + case 7: + getSound()->playSound(kEntityMertens, "CON1024A"); + getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(8); + setup_enterExitCompartment("641Ub", kObjectCompartment2); + break; + + case 8: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityMertens, kEntityAlexei, kAction124697504); + + setCallback(9); + setup_updateEntity(kCarGreenSleeping, kPosition_9460); + break; + + case 9: + CALLBACK_ACTION(); + break; + } + break; + + case kAction100906246: + params->param1 = 1; + break; + + case kAction156567128: + setCallback(6); + setup_enterExitCompartment("641Tb", kObjectCompartment2); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(26, Mertens, function26, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getProgress().eventCorpseThrown + || !params->param1 + || getProgress().chapter != kChapter1 + || getProgress().jacket != kJacketGreen) { + + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + setCallback(3); + setup_playSound16("ZNU1001"); + } else { + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + setCallback(2); + setup_playSound16("CON1062"); + break; + + case 2: + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + + case 3: + if (getProgress().jacket == kJacketBlood) { + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + } else if (getProgress().eventCorpseMovedFromFloor) { + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment1); + getEntities()->drawSequenceRight(kEntityMertens, "601Ra"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 16); + + setCallback(6); + setup_callbackActionOnDirection(); + } else { + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseFloor); + } + break; + + case 4: + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 5: + getAction()->playAnimation(kEventMertensCorpseFloor); + getLogic()->gameOver(kSavegameTypeIndex, 1, getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, true); + break; + + case 6: + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment1); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + setCallback(7); + setup_function21(kObjectCompartment1, kObjectHandleBathroom); + break; + + case 7: + if (getProgress().eventCorpseThrown || getProgress().chapter != kChapter1) { + if (getEntities()->isDistanceBetweenEntities(kEntityMertens, kEntityPlayer, 1000)) { + if (!getEntities()->checkFields10(kEntityPlayer)) + getSound()->playSound(kEntityMertens, "CON1061"); + } + + setCallback(9); + setup_enterExitCompartment("601Sa", kObjectCompartment1); + } else { + if (!getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) + getScenes()->loadSceneFromPosition(kCarNone, 1); + + setCallback(8); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseBed); + } + break; + + case 8: + getAction()->playAnimation(kEventMertensCorpseBed); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(27, Mertens, tylerCompartment, MertensActionType) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().field_14 == 29) { + CALLBACK_ACTION(); + break; + } + + UPDATE_PARAM_PROC(params->param2, getState()->timeTicks, 150) + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + setCallback(10); + setup_playSound16("CON1018A"); + break; + UPDATE_PARAM_PROC_END + +label_callback10: + if (!params->param3) + params->param3 = getState()->timeTicks + 300; + + if (params->param3 >= getState()->timeTicks) { +label_callback11: + UPDATE_PARAM(params->param4, getState()->timeTicks, 375); + + getSound()->playSound(kEntityPlayer, "LIB033"); + + if (getProgress().eventCorpseMovedFromFloor) { + + if (getProgress().jacket == kJacketBlood) { + setCallback(18); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + } + + if (params->param1) { + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + switch (params->param1) { + case 1: + setCallback(20); + setup_savegame(kSavegameTypeEvent, kEventMertensAugustWaitingCompartment); + break; + + case 2: + setCallback(21); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitationCompartment); + break; + + case 3: + getAction()->playAnimation(isNight() ? kEventMertensPushCallNight : kEventMertensPushCall); + // fallback to default case + + default: + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + } + } else { + setCallback(26); + setup_function26(false); + } + + } else { + if (!getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) + getScenes()->loadSceneFromPosition(kCarNone, 1); + + setCallback(17); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseFloor); + } + } else { + params->param3 = kTimeInvalid; + + if (getObjects()->get(kObjectCompartment1).location == kObjectLocation1) { + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(11); + setup_playSound16("CON1018B"); + break; + } + + getSound()->playSound(kEntityPlayer, "LIB014"); + + if (getProgress().eventCorpseMovedFromFloor) { + + if (getProgress().jacket == kJacketBlood) { + setCallback(13); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + } + + if (params->param1) { + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + switch (params->param1) { + case 1: + setCallback(15); + setup_savegame(kSavegameTypeEvent, kEventMertensAugustWaitingCompartment); + break; + + case 2: + setCallback(16); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitationCompartment); + break; + + case 3: + getAction()->playAnimation(isNight() ? kEventMertensPushCallNight : kEventMertensPushCall); + // fallback to default case + + default: + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + } + } else { + setCallback(14); + setup_function26(false); + } + } else { + if (!getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) + getScenes()->loadSceneFromPosition(kCarNone, 1); + + setCallback(12); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseFloor); + } + } + break; + + case kActionKnock: + if (params->param1) { + getObjects()->update(kObjectCompartment1, kEntityMertens, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + switch (params->param1) { + default: + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + + case 1: + setCallback(23); + setup_playSound16("CON1018D"); + break; + + case 2: + setCallback(24); + setup_playSound16("CON1018E"); + break; + + case 3: + setCallback(25); + setup_playSound16("CON1025"); + break; + } + + } else { + setCallback(22); + setup_function26(true); + } + break; + + case kActionOpenDoor: + getSound()->playSound(kEntityPlayer, getObjects()->get(kObjectCompartment1).location == kObjectLocation1 ? "LIB012" : "LIB014"); + + if (getProgress().eventCorpseMovedFromFloor) { + + if (getProgress().jacket == kJacketBlood) { + setCallback(27); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + } + + if (params->param1) { + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + switch (params->param1) { + case 1: + setCallback(29); + setup_savegame(kSavegameTypeEvent, kEventMertensAugustWaitingCompartment); + break; + + case 2: + setCallback(30); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitationCompartment); + break; + + case 3: + getAction()->playAnimation(isNight() ? kEventMertensPushCallNight : kEventMertensPushCall); + // fallback to default case + + default: + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + } + } else { + setCallback(28); + setup_function26(false); + } + } else { + if (!getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) + getScenes()->loadSceneFromPosition(kCarNone, 1); + + setCallback(26); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseFloor); + } + break; + + case kActionDefault: + getData()->inventoryItem = kItemNone; + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_8200) + || getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_7850) + || getEntities()->isOutsideAlexeiWindow()) { + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorNormal, kCursorNormal); + + if (getEntities()->isOutsideAlexeiWindow()) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); + + setCallback(params->param1 ? 9 : 8); + setup_playSound16(params->param1 ? "CON1018" : "CON1060"); + } else { + getSound()->playSound(kEntityMertens, "CON1019"); + + setCallback(1); + setup_enterExitCompartment("601Ma", kObjectCompartment1); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getProgress().eventCorpseMovedFromFloor) { + setCallback(4); + setup_enterExitCompartment("601Ra", kObjectCompartment1); + } else { + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { + setCallback(2); + setup_enterExitCompartment("601Ra", kObjectCompartment1); + } else { + getScenes()->loadSceneFromPosition(kCarNone, 1); + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseFloor); + } + } + break; + + case 2: + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseFloor); + break; + + case 3: + case 12: + case 17: + case 26: + getAction()->playAnimation(kEventMertensCorpseFloor); + getLogic()->gameOver(kSavegameTypeIndex, 1, getProgress().eventCorpseFound ? kSceneGameOverStopPolice : kSceneGameOverPolice, true); + break; + + case 4: + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMertens); + + if (params->param1) { + setCallback(7); + setup_enterExitCompartment("601Sa", kObjectCompartment1); + break; + } + + if (getProgress().eventCorpseThrown || getProgress().chapter != kChapter1) { + setCallback(6); + setup_function21(kObjectCompartment1, kObjectHandleBathroom); + } else { + if (!getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) + getScenes()->loadSceneFromPosition(kCarNone, 1); + + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventMertensCorpseBed); + } + break; + + case 5: + getAction()->playAnimation(kEventMertensCorpseBed); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + break; + + case 6: + setCallback(7); + setup_enterExitCompartment("601Sa", kObjectCompartment1); + break; + + case 7: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + + case 8: + case 9: + getObjects()->update(kObjectCompartment1, kEntityMertens, getObjects()->get(kObjectCompartment1).location, kCursorTalk, kCursorHand); + break; + + case 10: + getObjects()->update(kObjectCompartment1, kEntityMertens, getObjects()->get(kObjectCompartment1).location, kCursorTalk, kCursorHand); + goto label_callback10; + + case 11: + getObjects()->update(kObjectCompartment1, kEntityMertens, getObjects()->get(kObjectCompartment1).location, kCursorTalk, kCursorHand); + goto label_callback11; + + case 13: + case 18: + case 27: + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + break; + + case 14: + case 19: + case 22: + case 28: + CALLBACK_ACTION(); + break; + + case 15: + case 20: + case 29: + getAction()->playAnimation(kEventMertensAugustWaitingCompartment); + getProgress().eventMertensAugustWaiting = true; + + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + + case 16: + case 21: + case 30: + getAction()->playAnimation(kEventMertensKronosInvitationCompartment); + getProgress().eventMertensKronosInvitation = true; + + getSound()->playSound(kEntityPlayer, "LIB015"); + getScenes()->loadScene(kScene41); + + CALLBACK_ACTION(); + break; + + case 23: + getProgress().eventMertensAugustWaiting = true; + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + + case 24: + getProgress().eventMertensKronosInvitation = true; + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + + case 25: + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).location, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(28, Mertens, function28) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param4 && params->param5) { + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction125499160); + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + } + break; + + case kActionEndSound: + params->param4 = 1; + break; + + case kActionDefault: + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_1500); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMertens, "601O"); + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction154005632); + break; + + case 3: + setCallback(4); + setup_function17(); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + + case kAction155853632: + params->param5 = 1; + break; + + case kAction202558662: + getEntities()->drawSequenceLeft(kEntityMertens, "601L"); + getSound()->playSound(kEntityMertens, (char *)¶ms->seq1); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SS(29, Mertens, function29) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param7 > 1 && params->param8) { + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction125499160); + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + } + break; + + case kActionEndSound: + params->param7++; + if (params->param7 == 1) + getSound()->playSound(kEntityMertens, (char *)¶ms->seq2); + break; + + case kActionDefault: + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_1500); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMertens, "601O"); + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction154005632); + break; + + case 3: + setCallback(4); + setup_function17(); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + + case kAction155853632: + params->param8 = 1; + break; + + case kAction202558662: + getEntities()->drawSequenceLeft(kEntityMertens, "601L"); + getSound()->playSound(kEntityMertens, (char *)¶ms->seq1); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(30, Mertens, function30, MertensActionType) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + switch (params->param1) { + default: + CALLBACK_ACTION(); + return; + + case 1: + params->param2 = kPosition_8200; + + if (getProgress().field_14) { + CALLBACK_ACTION(); + return; + } + + getProgress().field_14 = 3; + break; + + case 2: + params->param2 = kPosition_7500; + break; + + case 3: + params->param2 = kPosition_6470; + break; + } + + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, (EntityPosition)params->param2); + break; + + case 2: + switch (params->param1) { + default: + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 1: + if (getProgress().chapter == kChapter4) + getSavePoints()->push(kEntityMertens, kEntityTatiana, kAction238790488); + + setCallback(3); + setup_tylerCompartment(kMertensAction3); + break; + + case 2: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_7500)) { + getObjects()->update(kObjectCompartment2, kEntityPlayer, getObjects()->get(kObjectCompartment2).location, kCursorNormal, kCursorNormal); + params->param3 = 1; + } + + setCallback(4); + setup_enterExitCompartment("601Vb", kObjectCompartment2); + break; + + case 3: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_6470)) { + getObjects()->update(kObjectCompartment3, kEntityPlayer, getObjects()->get(kObjectCompartment3).location, kCursorNormal, kCursorNormal); + params->param3 = 1; + } + + setCallback(6); + setup_enterExitCompartment("601Mc", kObjectCompartment3); + break; + } + break; + + case 3: + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 4: + getEntities()->drawSequenceLeft(kEntityMertens, "601Wb"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment2, true); + + setCallback(5); + setup_playSound("CON3020"); + break; + + case 5: + if (params->param3) + getObjects()->update(kObjectCompartment2, kEntityPlayer, getObjects()->get(kObjectCompartment2).location, kCursorHandKnock, kCursorHand); + + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment2); + + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 6: + getEntities()->drawSequenceLeft(kEntityMertens, "601Nc"); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment3, true); + + setCallback(7); + setup_playSound("CON3020"); + break; + + case 7: + if (params->param3) + getObjects()->update(kObjectCompartment3, kEntityPlayer, getObjects()->get(kObjectCompartment3).location, kCursorHandKnock, kCursorHand); + + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment3); + + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 8: + setCallback(9); + setup_function17(); + break; + + case 9: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(31, Mertens, function31, MertensActionType) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + setCallback(3); + setup_function17(); + break; + + case kActionDefault: + setCallback(1); + setup_bloodJacket("601G"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getSound()->isBuffered(kEntityMertens)) { + getEntities()->drawSequenceLeft(kEntityMertens, "601J"); + } else { + setCallback(2); + setup_function17(); + } + break; + + case 2: + case 3: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Mertens, function32) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_9510); + break; + + case 2: + if (getData()->entityPosition >= kPosition_9460) { + getEntities()->clearSequences(kEntityMertens); + setCallback(3); + setup_function11(900); + break; + } + // Fallback to next case + + case 3: + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 4: + setCallback(5); + setup_function17(); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Mertens, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (ENTITY_PARAM(0, 8) || ENTITY_PARAM(0, 6) + || ENTITY_PARAM(1, 1) || ENTITY_PARAM(1, 2) || ENTITY_PARAM(1, 3) || ENTITY_PARAM(1, 4) || ENTITY_PARAM(1, 5) || ENTITY_PARAM(1, 6) || ENTITY_PARAM(1, 7) + || ENTITY_PARAM(2, 2)) { + ENTITY_PARAM(1, 8) = 1; + + setCallback(ENTITY_PARAM(0, 8) ? 1 : 3); + setup_updateEntity(kCarGreenSleeping, ENTITY_PARAM(0, 8) ? kPosition_1500 : kPosition_540); + } else { + CALLBACK_ACTION(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + ENTITY_PARAM(2, 1) = 1; + + setCallback(2); + setup_function14(kEntityVerges); + break; + + case 2: + ENTITY_PARAM(1, 8) = 0; + + CALLBACK_ACTION(); + break; + + case 3: + getEntities()->clearSequences(kEntityMertens); + + setCallback(4); + setup_function11(75); + break; + + case 4: + if (ENTITY_PARAM(1, 6)) { + setCallback(5); + setup_function16(true); + break; + } + // Fallback to next case + + case 5: + if (ENTITY_PARAM(1, 7)) { + setCallback(6); + setup_function16(false); + break; + } + // Fallback to next case + + case 6: + if (ENTITY_PARAM(1, 5)) { + setCallback(7); + setup_function15(true); + break; + } + // Fallback to next case + + case 7: + if (ENTITY_PARAM(1, 4)) { + setCallback(8); + setup_function15(false); + break; + } + // Fallback to next case + + case 8: + if (ENTITY_PARAM(1, 2)) { + setCallback(9); + setup_function35(); + break; + } + // Fallback to next case + + case 9: + if (ENTITY_PARAM(0, 6)) { + setCallback(10); + setup_function36(); + break; + } + // Fallback to next case + + case 10: + if (ENTITY_PARAM(1, 3)) { + setCallback(11); + setup_function40(); + break; + } + // Fallback to next case + + case 11: + if (ENTITY_PARAM(1, 1)) { + setCallback(12); + setup_function28("CON1200"); + break; + } + + if (ENTITY_PARAM(2, 2)) { + setCallback(13); + setup_function37(); + break; + } + + CALLBACK_ACTION(); + break; + + case 12: + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction168254872); + ENTITY_PARAM(1, 1) = 0; + + if (ENTITY_PARAM(2, 2)) { + setCallback(13); + setup_function37(); + break; + } + + CALLBACK_ACTION(); + break; + + case 13: + ENTITY_PARAM(2, 2) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Mertens, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityMertens, kAction171394341, 7); + getSavePoints()->addData(kEntityMertens, kAction169633856, 9); + getSavePoints()->addData(kEntityMertens, kAction238732837, 10); + getSavePoints()->addData(kEntityMertens, kAction269624833, 12); + getSavePoints()->addData(kEntityMertens, kAction302614416, 11); + getSavePoints()->addData(kEntityMertens, kAction190082817, 8); + getSavePoints()->addData(kEntityMertens, kAction269436673, 13); + getSavePoints()->addData(kEntityMertens, kAction303343617, 14); + getSavePoints()->addData(kEntityMertens, kAction224122407, 17); + getSavePoints()->addData(kEntityMertens, kAction201431954, 18); + getSavePoints()->addData(kEntityMertens, kAction188635520, 19); + getSavePoints()->addData(kEntityMertens, kAction204379649, 4); + + ENTITY_PARAM(0, 1) = 0; + + getData()->entityPosition = kPosition_9460; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + + break; + } + +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Mertens, function35) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getProgress().field_14 == 29) { + CALLBACK_ACTION(); + break; + } else { + getProgress().field_14 = 3; + + setCallback(1); + setup_function19(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case 2: + if (!ENTITY_PARAM(1, 2) || getProgress().eventMetAugust) { + ENTITY_PARAM(1, 2) = 0; + + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + } else { + setCallback(5); + setup_tylerCompartment(kMertensAction1); + } + break; + + case 3: + setCallback(4); + setup_function17(); + break; + + case 4: + CALLBACK_ACTION(); + break; + + case 5: + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + if (getProgress().eventMertensAugustWaiting) + ENTITY_PARAM(1, 2) = 0; + + setCallback(6); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 6: + ENTITY_PARAM(1, 2) = 0; + + setCallback(7); + setup_function17(); + break; + + case 7: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Mertens, function36) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getProgress().field_14 == 29) { + CALLBACK_ACTION(); + } else { + getProgress().field_14 = 3; + + setCallback(1); + setup_function19(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case 2: + if (ENTITY_PARAM(0, 6)) { + if (getEntities()->isPlayerInCar(kCarGreenSleeping) && getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition) { + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_9460); + } else { + setCallback(7); + setup_tylerCompartment(kMertensAction2); + } + } else { + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(5); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + } + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case 4: + if (ENTITY_PARAM(0, 6)) { + setCallback(7); + setup_tylerCompartment(kMertensAction2); + } else { + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(5); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + } + break; + + case 5: + setCallback(6); + setup_function17(); + break; + + case 7: + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + if (!getProgress().eventMertensKronosInvitation) + ENTITY_PARAM(0, 7) = 1; + + ENTITY_PARAM(0, 6) = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 8: + setCallback(9); + setup_function17(); + break; + + case 6: + case 9: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Mertens, function37) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 >= 2 && params->param2) { + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction125499160); + + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + } + break; + + case kActionEndSound: + ++params->param6; + + if (params->param6 == 1) + getSound()->playSound(kEntityMertens, getEntities()->isDistanceBetweenEntities(kEntityMertens, kEntityPlayer, 2000) ? "CON1152" : "CON1151"); + break; + + case kActionDefault: + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_1500); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMertens, "601O"); + getSavePoints()->push(kEntityMertens, kEntityCoudert, kAction154005632); + break; + + case 3: + setCallback(4); + setup_function17(); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + + case kAction155853632: + params->param2 = 1; + break; + + case kAction202558662: + getEntities()->drawSequenceLeft(kEntityMertens, "601L"); + getSound()->playSound(kEntityMertens, "CON1150"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Mertens, function38) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (!ENTITY_PARAM(0, 4)) { + CALLBACK_ACTION(); + break; + } + + if (getProgress().field_14 == 29) { + CALLBACK_ACTION(); + } else { + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (!ENTITY_PARAM(0, 4)) { + CALLBACK_ACTION(); + break; + } + + setCallback(2); + setup_tylerCompartment(kMertensActionNone); + break; + + case 2: + ENTITY_PARAM(0, 4) = 0; + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Mertens, function39) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + ENTITY_PARAM(0, 4) = 1; + + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function22(); + break; + + case 2: + setCallback(3); + setup_function33(); + break; + + case 3: + setCallback(4); + setup_function24(); + break; + + case 4: + setCallback(5); + setup_function33(); + break; + + case 5: + setCallback(6); + setup_function25(); + break; + + case 6: + setCallback(7); + setup_function33(); + break; + + case 7: + setCallback(8); + setup_function38(); + break; + + case 8: + if (getProgress().field_14 == 3) + getProgress().field_14 = 0; + + setCallback(9); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 9: + setCallback(10); + setup_function17(); + break; + + case 10: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Mertens, function40) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + ENTITY_PARAM(1, 3) = 0; + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarKronos, kPosition_9460); + break; + + case 2: + setCallback(3); + setup_function11(1800); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_1500); + break; + + case 4: + setCallback(5); + setup_function17(); + break; + + case 5: + ENTITY_PARAM(0, 6) = 1; + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Mertens, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function17(); + break; + + case 2: + setup_function42(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Mertens, function42) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(2, 3)) { + ENTITY_PARAM(0, 1) = 1; + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + + ENTITY_PARAM(2, 1) = 0; // BUG: is set twice. Maybe a bug? + ENTITY_PARAM(2, 2) = 0; + ENTITY_PARAM(2, 3) = 0; + + params->param1 = 1; + params->param2 = 1; + + getEntities()->drawSequenceLeft(kEntityMertens, "601E"); + } + + if (ENTITY_PARAM(2, 1) || getProgress().eventCorpseFound || getEvent(kEventMertensAskTylerCompartmentD) || getEvent(kEventMertensAskTylerCompartment)) + getData()->inventoryItem = kItemNone; + else + getData()->inventoryItem = kItemInvalid; + + if (!params->param2) { + TIME_CHECK_SAVEPOINT(kTime1125000, params->param3, kEntityMertens, kEntityMahmud, kAction170483072); + + if (params->param4 != kTimeInvalid && getState()->time > kTimeCityChalons) { + + if (getState()->time <= kTime1188000) { + if ((!getEntities()->isPlayerInCar(kCarGreenSleeping) && !getEntities()->isPlayerInCar(kCarRedSleeping)) + || getSound()->isBuffered("REB1205") + || !getEntities()->isInsideCompartment(kEntityMmeBoutarel, kCarRedSleeping, kPosition_5790) + || !params->param4) { + params->param4 = getState()->time; + } + + if (params->param4 >= getState()->time) + break; + } + + ENTITY_PARAM(0, 4) = kTimeInvalid; + getData()->inventoryItem = kItemNone; + + setCallback(8); + setup_function29("CON1210", "CON1210A"); + break; + } + } + +label_callback_8: + if (getState()->time > kTime1215000 && !ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { + UPDATE_PARAM_PROC(params->param5, getState()->time, 2700) + getEntities()->drawSequenceLeft(kEntityMertens, "601E"); + ENTITY_PARAM(0, 1) = 1; + params->param5 = 0; + UPDATE_PARAM_PROC_END + } + + if (ENTITY_PARAM(0, 8)) { + getData()->inventoryItem = kItemNone; + setCallback(9); + setup_function14(kEntityVerges); + break; + } + + if (getProgress().field_14 == 29) + goto label_callback_13; + +label_callback_9: + if (ENTITY_PARAM(1, 6)) { + getData()->inventoryItem = kItemNone; + setCallback(10); + setup_function16(true); + break; + } + +label_callback_10: + if (ENTITY_PARAM(1, 7)) { + getData()->inventoryItem = kItemNone; + setCallback(11); + setup_function16(false); + break; + } + +label_callback_11: + if (ENTITY_PARAM(1, 5)) { + getData()->inventoryItem = kItemNone; + setCallback(12); + setup_function15(true); + break; + } + +label_callback_12: + if (ENTITY_PARAM(1, 4)) { + getData()->inventoryItem = kItemNone; + setCallback(13); + setup_function15(false); + break; + } + +label_callback_13: + if (ENTITY_PARAM(1, 2)) { + getData()->inventoryItem = kItemNone; + setCallback(14); + setup_function35(); + break; + } + +label_callback_14: + if (ENTITY_PARAM(0, 6)) { + getData()->inventoryItem = kItemNone; + setCallback(15); + setup_function36(); + break; + } + +label_callback_15: + if (ENTITY_PARAM(1, 3)) { + getData()->inventoryItem = kItemNone; + setCallback(16); + setup_function40(); + break; + } + +label_callback_16: + if (ENTITY_PARAM(1, 1)) { + ENTITY_PARAM(1, 1) = 0; + getData()->inventoryItem = kItemNone; + setCallback(17); + setup_function28("CON1200"); + break; + } + +label_callback_17: + if (ENTITY_PARAM(2, 2)) { + ENTITY_PARAM(2, 2) = 0; + getData()->inventoryItem = kItemNone; + setCallback(18); + setup_function37(); + break; + } + +label_callback_18: + if (!params->param1 && ENTITY_PARAM(0, 5)) { + getData()->inventoryItem = kItemNone; + setCallback(19); + setup_function39(); + break; + } + +label_callback_19: + if (ENTITY_PARAM(0, 1) && !getSound()->isBuffered(kEntityMertens)) { + if (getProgress().field_18 != 4) + getSound()->playSound(kEntityMertens, "CON1505"); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + setCallback(21); + setup_savegame(kSavegameTypeEvent, kEventMertensAskTylerCompartmentD); + break; + + case kAction11: + if (!ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { + getData()->inventoryItem = kItemNone; + setCallback(20); + setup_function13((bool)savepoint.param.intValue, (bool)savepoint.entity2); + } + break; + + case kActionDefault: + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getScenes()->loadSceneFromItemPosition(kItem7); + break; + + case kActionDrawScene: + if (ENTITY_PARAM(2, 1)) + break; + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23) && ENTITY_PARAM(0, 7) && !getEvent(kEventKronosConversation)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitation); + break; + } + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23) && !getProgress().eventMertensKronosInvitation && !getEvent(kEventMertensLastCar) && !getEvent(kEventMertensLastCarOriginalJacket)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventMertensLastCar); + break; + } + +label_callback_2_4: + if ((getEntities()->isPlayerPosition(kCarGreenSleeping, 1) || getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) && !ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { + getData()->inventoryItem = kItemNone; + setCallback(getEntities()->isPlayerPosition(kCarGreenSleeping, 1) ? 5 : 6); + setup_function13(getEntities()->isPlayerPosition(kCarGreenSleeping, 1), false); + break; + } + +label_callback_5_6: + if (getEntities()->isPlayerInCar(kCarGreenSleeping) && getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition) { + if (getProgress().jacket == kJacketOriginal || ENTITY_PARAM(0, 7)) { + getData()->inventoryItem = kItemNone; + setCallback(7); + setup_function32(); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventMertensKronosInvitation); + getProgress().eventMertensKronosInvitation = true; + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + getEntities()->drawSequenceRight(kEntityMertens, "601A"); + getScenes()->loadSceneFromItemPosition(kItem7); + ENTITY_PARAM(0, 1) = 0; + getData()->inventoryItem = kItemNone; + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + case 4: + getEntities()->drawSequenceLeft(kEntityMertens, "601B"); + goto label_callback_2_4; + + case 3: + getAction()->playAnimation(getProgress().jacket == kJacketOriginal ? kEventMertensLastCarOriginalJacket : kEventMertensLastCar); + getEntities()->drawSequenceRight(kEntityMertens, "601A"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 6); + getScenes()->loadSceneFromItemPosition(kItem7); + ENTITY_PARAM(0, 1) = 0; + getData()->inventoryItem = kItemNone; + + setCallback(4); + setup_callbackActionOnDirection(); + break; + + case 5: + case 6: + goto label_callback_5_6; + + case 8: + goto label_callback_8; + + case 9: + goto label_callback_9; + + case 10: + goto label_callback_10; + + case 11: + goto label_callback_11; + + case 12: + goto label_callback_12; + + case 13: + goto label_callback_13; + + case 14: + goto label_callback_14; + + case 15: + goto label_callback_15; + + case 16: + goto label_callback_16; + + case 17: + goto label_callback_17; + + case 18: + goto label_callback_18; + + case 19: + params->param1 = 1; + goto label_callback_19; + + case 21: + getAction()->playAnimation(kEventMertensAskTylerCompartmentD); + getEntities()->drawSequenceRight(kEntityMertens, "601A"); + getInventory()->get(kItem7)->location = kObjectLocationNone; + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 25); + + setCallback(22); + setup_callbackActionOnDirection(); + break; + + case 22: + getEntities()->drawSequenceLeft(kEntityMertens, "601B"); + break; + } + break; + + case kAction225358684: + if (!ENTITY_PARAM(0, 1)) { + getData()->inventoryItem = kItemNone; + setCallback(23); + setup_function30((MertensActionType)savepoint.param.intValue); + } + break; + + case kAction225932896: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) + getSavePoints()->push(kEntityMertens, kEntityFrancois, kAction205346192); + break; + + case kAction305159806: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + getData()->inventoryItem = kItemNone; + setCallback(24); + setup_function31((MertensActionType)savepoint.param.intValue); + } + break; + + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, Mertens, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function17(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMertens); + + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(0, 1) = 0; + ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 5) = 0; + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function44(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Mertens, function44) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(1, 6)) { + setCallback(1); + setup_function16(true); + break; + } + +label_callback1: + if (ENTITY_PARAM(1, 7)) { + setCallback(2); + setup_function16(false); + break; + } + +label_callback2: + if (ENTITY_PARAM(1, 5)) { + setCallback(3); + setup_function15(true); + break; + } + +label_callback3: + if (ENTITY_PARAM(1, 4)) { + setCallback(4); + setup_function15(false); + break; + } + + break; + + case kAction11: + if (!ENTITY_PARAM(2, 1)) { + setCallback(5); + setup_function13((bool)savepoint.param.intValue, (bool)savepoint.entity2); + } + break; + + case kActionDrawScene: + if (ENTITY_PARAM(2, 1)) + break; + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { + setCallback(6); + setup_function13(true, false); + + } else if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { + setCallback(7); + setup_function13(false, false); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + } + break; + + case kAction225358684: + if (!ENTITY_PARAM(0, 1)) { + setCallback(9); + setup_function30((MertensActionType)savepoint.param.intValue); + } + break; + + case kAction225932896: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) + getSavePoints()->push(kEntityMertens, kEntityFrancois, kAction205346192); + break; + + case kAction226078300: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(8); + setup_playSound("CON2020"); + } + break; + + case kAction305159806: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(10); + setup_function31((MertensActionType)savepoint.param.intValue); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, Mertens, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function17(); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + + ENTITY_PARAM(2, 3) = 0; + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function46(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Mertens, function46) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(1, 6)) { + setCallback(1); + setup_function16(true); + break; + } + +label_callback_1: + if (ENTITY_PARAM(1, 7)) { + setCallback(2); + setup_function16(false); + break; + } + +label_callback_2: + if (ENTITY_PARAM(1, 5)) { + setCallback(3); + setup_function15(true); + break; + } + +label_callback_3: + if (ENTITY_PARAM(1, 4)) { + setCallback(4); + setup_function15(false); + break; + } + +label_callback_4: + if (ENTITY_PARAM(0, 8)) { + setCallback(5); + setup_function14(kEntityVerges); + break; + } + +label_callback_5: + if (ENTITY_PARAM(2, 4) + && (getEvent(kEventKronosVisit) || getState()->time > kTime2052000) + && getState()->time < kTime2133000 + && getEntities()->isPlayerInCar(kCarGreenSleeping)) { + setCallback(6); + setup_function32(); + break; + } + +label_callback_6: + TIME_CHECK_CALLBACK_1(kTime1971000, params->param1, 7, setup_function28, "CON3012"); + +label_callback_7: + TIME_CHECK_CALLBACK(kTime2117700, params->param2, 8, setup_function32); + +label_callback_8: + TIME_CHECK_CALLBACK_1(kTime2124000, params->param3, 9, setup_function28, "CON2010"); + +label_callback_9: + TIME_CHECK_CALLBACK(kTime2146500, params->param4, 10, setup_function32); + +label_callback_10: + TIME_CHECK_CALLBACK(kTime2169000, params->param5, 11, setup_function32); + break; + + case kAction11: + if (!ENTITY_PARAM(2, 1)) { + setCallback(12); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2 != kEntityPlayer); + } + break; + + case kActionDefault: + break; + + case kActionDrawScene: + if (!ENTITY_PARAM(2, 1)) { + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { + setCallback(13); + setup_function13(true, false); + } else if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { + setCallback(14); + setup_function13(false, false); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + + case 9: + goto label_callback_9; + + case 10: + goto label_callback_10; + } + break; + + case kAction225358684: + if (!ENTITY_PARAM(0, 1)) { + setCallback(16); + setup_function30((MertensActionType)savepoint.param.intValue); + } + break; + + case kAction225932896: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) + getSavePoints()->push(kEntityMertens, kEntityFrancois, kAction205346192); + break; + + case kAction226078300: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(15); + setup_playSound("CON2020"); + } + break; + + case kAction305159806: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(17); + setup_function31((MertensActionType)savepoint.param.intValue); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, Mertens, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function17(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMertens); + + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + + ENTITY_PARAM(2, 4) = 0; + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function48(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Mertens, function48) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(2, 3)) { + params->param1 = 1; + + getObjects()->updateLocation2(kObjectCompartment2, kObjectLocation1); + getObjects()->updateLocation2(kObjectCompartment3, kObjectLocation1); + getObjects()->updateLocation2(kObjectCompartment4, kObjectLocation1); + + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(1, 7) = 0; + + getEntities()->drawSequenceLeft(kEntityMertens, "601E"); + + ENTITY_PARAM(2, 3) = 0; + } + + if (ENTITY_PARAM(1, 6)) { + setCallback(1); + setup_function16(true); + break; + } + +label_callback_1: + if (ENTITY_PARAM(1, 7)) { + setCallback(2); + setup_function16(false); + break; + } + +label_callback_2: + if (ENTITY_PARAM(1, 5)) { + setCallback(3); + setup_function15(true); + break; + } + +label_callback_3: + if (ENTITY_PARAM(1, 4)) { + setCallback(4); + setup_function15(false); + break; + } + +label_callback_4: + if (!params->param1) { + TIME_CHECK_CALLBACK(kTime2403000, params->param2, 5, setup_function49); + +label_callback_5: + TIME_CHECK_CALLBACK(kTime2430000, params->param3, 6, setup_function32); + +label_callback_6: + TIME_CHECK_CALLBACK(kTime2439000, params->param4, 7, setup_function32); + +label_callback_7: + TIME_CHECK_CALLBACK(kTime2448000, params->param5, 8, setup_function32); + } + +label_callback_8: + if (getState()->time > kTime2538000 && !ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { + UPDATE_PARAM(params->param6, getState()->time, 2700); + + getEntities()->drawSequenceLeft(kEntityMertens, "601E"); + + ENTITY_PARAM(0, 1) = 1; + params->param6 = 0; + } + break; + + case kAction11: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(9); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2 != kEntityPlayer); + } + break; + + case kActionDefault: + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_1500; + getData()->location = kLocationOutsideCompartment; + + getScenes()->loadSceneFromItemPosition(kItem7); + break; + + case kActionDrawScene: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { + setCallback(10); + setup_function13(true, false); + } else if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { + setCallback(11); + setup_function13(false, false); + } + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + } + break; + + case kAction225358684: + if (!ENTITY_PARAM(0, 1)) { + setCallback(13); + setup_function30((MertensActionType)savepoint.param.intValue); + } + break; + + case kAction226078300: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(12); + setup_playSound("CON2020"); + } + break; + + case kAction305159806: + if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { + setCallback(14); + setup_function31((MertensActionType)savepoint.param.intValue); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(49, Mertens, function49) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function19(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case 2: + setCallback(3); + setup_tylerCompartment(kMertensActionNone); + break; + + case 3: + setCallback(4); + setup_function33(); + break; + + case 4: + setCallback(5); + setup_function25(); + break; + + case 5: + setCallback(6); + setup_function33(); + break; + + case 6: + setCallback(7); + setup_function24(); + break; + + case 7: + setCallback(8); + setup_function33(); + break; + + case 8: + setCallback(9); + setup_function23(); + break; + + case 9: + setCallback(10); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 10: + setCallback(11); + setup_function17(); + break; + + case 11: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(50, Mertens, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMertens); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(51, Mertens, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function52(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(52, Mertens, function52) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 == kTimeInvalid) + break; + + if (params->param1 >= getState()->time) { + + if (!getEntities()->isPlayerInCar(kCarRedSleeping) || !params->param2) + params->param2 = getState()->time; + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + + setCallback(1); + setup_playSound("Mme5010"); + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + params->param1 = getState()->time + 4500; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("671Ad", kObjectCompartmentD); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityMertens, kEntityMmeBoutarel, kAction155604840); + setup_function53(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(53, Mertens, function53) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM(params->param4, getState()->timeTicks, 75); + + params->param1 = 0; + params->param2 = 0; + + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param4 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (params->param1) { + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); + params->param1 = 0; + + setCallback(3); + setup_playSound(getSound()->justCheckingCath()); + } + + setCallback(savepoint.action == kActionKnock ? 4 : 5); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_5790); + break; + + case kActionDrawScene: + if (params->param2 || params->param1) { + params->param1 = 0; + params->param2 = 0; + params->param3 = 0; + + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("601ZD", kObjectCompartment4); + break; + + case 2: + getEntities()->clearSequences(kEntityMertens); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_5790; + // Fallback to next case + + case 3: + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case 4: + case 5: + params->param3++; + + if (params->param3 == 1) { + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(6); + setup_playSound("Con5002"); + + } else if (params->param3 == 2) { + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(7); + setup_playSound("Con5002A"); + } + break; + + case 6: + params->param1 = 1; + getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorTalk, kCursorNormal); + break; + + case 7: + params->param2 = 1; + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(54, Mertens) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/mertens.h b/engines/lastexpress/entities/mertens.h new file mode 100644 index 0000000000..c6b800f1ff --- /dev/null +++ b/engines/lastexpress/entities/mertens.h @@ -0,0 +1,220 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_MERTENS_H +#define LASTEXPRESS_MERTENS_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Mertens : public Entity { +private: + // The type of action when entering Tyler compartment + enum MertensActionType { + kMertensActionNone = 0, + kMertensAction1 = 1, + kMertensAction2 = 2, + kMertensAction3 = 3 + }; + +public: + Mertens(LastExpressEngine *engine); + ~Mertens() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Handle meeting Coudert with the blooded jacket + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(bloodJacket, const char *sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + * @param entityPosition1 The entity position + * @param entityPosition1 The entity position to check + * + * @note We are not using the shared function due to too many differences + */ + DECLARE_FUNCTION_4(enterExitCompartment3, const char* sequence, ObjectIndex compartment, EntityPosition entityPosition1, EntityPosition entityPosition2) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound16, const char* filename) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_1(function11, uint32 time) + + /** + * Says "Bonsoir" to another character + * + * @param entity The entity + */ + DECLARE_FUNCTION_1(bonsoir, EntityIndex entity) + DECLARE_FUNCTION_2(function13, bool, bool) + DECLARE_FUNCTION_1(function14, EntityIndex entity) + DECLARE_FUNCTION_1(function15, bool) + DECLARE_FUNCTION_1(function16, bool) + DECLARE_FUNCTION(function17) + DECLARE_FUNCTION(function18) + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + + /** + * ??? + * + * @param object1 First object index + * @param object2 Second object index + */ + DECLARE_FUNCTION_2(function21, ObjectIndex object1, ObjectIndex object2) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION_1(function26, bool) + DECLARE_FUNCTION_1(tylerCompartment, MertensActionType action) + DECLARE_FUNCTION_1(function28, const char *soundName) + DECLARE_FUNCTION_2(function29, const char *soundName1, const char *soundName2) + DECLARE_FUNCTION_1(function30, MertensActionType action) + DECLARE_FUNCTION_1(function31, MertensActionType action) + DECLARE_FUNCTION(function32) + DECLARE_FUNCTION(function33) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + DECLARE_FUNCTION(function35) + DECLARE_FUNCTION(function36) + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + DECLARE_FUNCTION(function39) + DECLARE_FUNCTION(function40) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function42) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + DECLARE_FUNCTION(function44) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + DECLARE_FUNCTION(function46) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + DECLARE_FUNCTION(function48) + DECLARE_FUNCTION(function49) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function52) + DECLARE_FUNCTION(function53) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_MERTENS_H diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp new file mode 100644 index 0000000000..30ed546106 --- /dev/null +++ b/engines/lastexpress/entities/milos.cpp @@ -0,0 +1,1077 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/milos.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Milos::Milos(LastExpressEngine *engine) : Entity(engine, kEntityMilos) { + ADD_CALLBACK_FUNCTION(Milos, reset); + ADD_CALLBACK_FUNCTION(Milos, draw); + ADD_CALLBACK_FUNCTION(Milos, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Milos, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Milos, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Milos, playSound); + ADD_CALLBACK_FUNCTION(Milos, playSound16); + ADD_CALLBACK_FUNCTION(Milos, savegame); + ADD_CALLBACK_FUNCTION(Milos, updateFromTime); + ADD_CALLBACK_FUNCTION(Milos, enterCompartmentDialog); + ADD_CALLBACK_FUNCTION(Milos, function11); + ADD_CALLBACK_FUNCTION(Milos, chapter1); + ADD_CALLBACK_FUNCTION(Milos, function13); + ADD_CALLBACK_FUNCTION(Milos, function14); + ADD_CALLBACK_FUNCTION(Milos, chapter1Handler); + ADD_CALLBACK_FUNCTION(Milos, function16); + ADD_CALLBACK_FUNCTION(Milos, function17); + ADD_CALLBACK_FUNCTION(Milos, function18); + ADD_CALLBACK_FUNCTION(Milos, chapter2); + ADD_CALLBACK_FUNCTION(Milos, chapter2Handler); + ADD_CALLBACK_FUNCTION(Milos, function21); + ADD_CALLBACK_FUNCTION(Milos, chapter3); + ADD_CALLBACK_FUNCTION(Milos, function23); + ADD_CALLBACK_FUNCTION(Milos, function24); + ADD_CALLBACK_FUNCTION(Milos, function25); + ADD_CALLBACK_FUNCTION(Milos, function26); + ADD_CALLBACK_FUNCTION(Milos, function27); + ADD_CALLBACK_FUNCTION(Milos, chapter4); + ADD_CALLBACK_FUNCTION(Milos, chapter4Handler); + ADD_CALLBACK_FUNCTION(Milos, function30); + ADD_CALLBACK_FUNCTION(Milos, function31); + ADD_CALLBACK_FUNCTION(Milos, function32); + ADD_CALLBACK_FUNCTION(Milos, chapter5); + ADD_CALLBACK_FUNCTION(Milos, chapter5Handler); + ADD_CALLBACK_FUNCTION(Milos, function35); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Milos, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Milos, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Milos, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(4, Milos, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Milos, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Milos, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(7, Milos, playSound16) + Entity::playSound(savepoint, false, SoundManager::kFlagDefault); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Milos, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(9, Milos, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Milos, enterCompartmentDialog, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + case kActionDefault: + if (getEntities()->updateEntity(kEntityMilos, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + case kActionExcuseMe: + if (getEvent(kEventMilosTylerCompartmentDefeat)) { + // Robert saying: "Milos" + switch(rnd(3)) { + default: + case 0: + getSound()->playSound(kEntityPlayer, "CAT1014"); + break; + + case 1: + getSound()->playSound(kEntityPlayer, "CAT1014A"); + break; + + case 2: + getSound()->playSound(kEntityPlayer, "CAT1014B"); + break; + } + } else { + getSound()->excuseMeCath(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(11, Milos, function11, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + error("Milos: callback function 11 not implemented!"); + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorNormal, kCursorNormal); + + if (params->param2) { + if (getInventory()->hasItem(kItemPassengerList)) { + setCallback(10); + setup_playSound((rnd(2) ? "CAT1504" : getSound()->wrongDoorCath())); + } else { + setCallback(11); + setup_playSound(getSound()->wrongDoorCath()); + } + } else { + if (savepoint.action == kActionKnock) { + setCallback(7); + setup_playSound("LIB012"); + } else { + setCallback(8); + setup_playSound("LIB013"); + } + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param3 || params->param2) { + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param3 = 0; + params->param2 = 0; + } + break; + + case kActionCallback: + switch(getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + setCallback(2); + setup_enterCompartmentDialog(kCarGreenSleeping, kPosition_8200); + break; + + case 2: + setCallback(3); + setup_function14(); + break; + + case 3: + if (getProgress().field_14 == 14) + getProgress().field_14 = 0; + + params->param6 = 1; + setCallback(4); + setup_enterCompartmentDialog(kCarRedSleeping, kPosition_3050); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("609Bg", kObjectCompartmentG); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMilos); + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction101687594); + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case 6: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case 7: + case 8: + setCallback(9); + // Milos asking: "Yeah? Who is it?" + setup_playSound("MIL1117A"); + break; + + case 9: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorTalk, kCursorNormal); + params->param2 = 1; + break; + + case 10: + case 11: + params->param2 = 0; + params->param3 = 1; + break; + + case 12: + getEntities()->drawSequenceLeft(kEntityMilos, "611Cg"); + getEntities()->enterCompartment(kEntityMilos, kObjectCompartmentG, true); + getSavePoints()->push(kEntityMilos, kEntityCoudert, kAction88652208); + break; + + case 13: + getEntities()->exitCompartment(kEntityMilos, kObjectCompartmentG, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMilos); + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + params->param5 = 0; + break; + + } + break; + + case kAction122865568: + getData()->location = kLocationOutsideCompartment; + setCallback(12); + setup_enterExitCompartment("611Bg", kObjectCompartmentG); + break; + + case kAction123852928: + params->param1 = 13; + setup_enterExitCompartment("611Dg", kObjectCompartmentG); + break; + + case kAction221683008: + params->param5 = 1; + getSavePoints()->push(kEntityMilos, kEntityCoudert, kAction123199584); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Milos, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject46, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_4689; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + + getSavePoints()->addData(kEntityMilos, kAction157691176, 0); + getSavePoints()->addData(kEntityMilos, kAction208228224, 2); + getSavePoints()->addData(kEntityMilos, kAction259125998, 3); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Milos, function13) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getSavePoints()->push(kEntityMilos, kEntityTables2, kActionDrawTablesWithChairs, "009E"); + getEntities()->clearSequences(kEntityVesna); + getEntities()->clearSequences(kEntityIvo); + getEntities()->clearSequences(kEntitySalko); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntitySalko, "009D5"); + getEntities()->drawSequenceRight(kEntityTables2, "009D4"); + getEntities()->drawSequenceRight(kEntityIvo, "009D3"); + getEntities()->drawSequenceRight(kEntityVesna, "009D2"); + getEntities()->drawSequenceRight(kEntityMilos, "009D1"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Milos, function14) + error("Milos: callback function 14 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Milos, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_SAVEPOINT(kTime1071000, params->param3, kEntityMilos, kEntityServers1, kAction223002560); + + if (getState()->time > kTime1089000 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + setup_function16(); + break; + } + + if (getEntities()->isPlayerPosition(kCarRestaurant, 61) && !params->param1) { + UPDATE_PARAM_PROC(params->param4, getState()->timeTicks, 45) + setCallback(1); + setup_draw("009C"); + break; + UPDATE_PARAM_PROC_END + } + + if (getEntities()->isPlayerPosition(kCarRestaurant, 70) && !params->param2) { + UPDATE_PARAM(params->param5, getState()->timeTicks, 45); + + setCallback(2); + setup_draw("009C"); + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityMilos, kEntityTables2, kAction136455232); + getEntities()->drawSequenceLeft(kEntityMilos, "009A"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityMilos, "009A"); + params->param1 = 1; + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMilos, "009A"); + params->param2 = 1; + break; + } + break; + } + +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Milos, function16) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + if (getEntities()->isDistanceBetweenEntities(kEntityMilos, kEntityVesna, 750) + || getEntities()->checkDistanceFromPosition(kEntityVesna, kPosition_3050, 500)) { + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction123668192); + + setCallback(5); + setup_enterExitCompartment("611Ag", kObjectCompartmentG); + } + } + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_function13(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityMilos, kEntityServers1, kAction269485588); + getSavePoints()->push(kEntityMilos, kEntityIvo, kAction125242096); + getEntities()->drawSequenceRight(kEntityMilos, "807DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityMilos); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + getEntities()->clearSequences(kEntityMilos); + break; + + case 3: + if (getEntities()->isDistanceBetweenEntities(kEntityMilos, kEntityVesna, 750) + || getEntities()->checkDistanceFromPosition(kEntityVesna, kPosition_3050, 500)) { + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction123668192); + + setCallback(4); + setup_enterExitCompartment("611Ag", kObjectCompartmentG); + } else { + params->param1 = 1; + + getEntities()->drawSequenceLeft(kEntityMilos, "609Dg"); + getEntities()->enterCompartment(kEntityMilos, kObjectCompartmentG, true); + } + break; + + case 4: + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMilos); + + setup_function17(); + break; + + case 5: + getEntities()->exitCompartment(kEntityMilos, kObjectCompartmentG, true); + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMilos); + + setup_function17(); + break; + } + break; + + case kAction135024800: + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction204832737); + + setCallback(3); + setup_enterCompartmentDialog(kCarRedSleeping, kPosition_3050); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Milos, function17) + if (savepoint.action == kActionDefault) { + setCallback(1); + setup_function11(kTimeBedTime); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Milos, function18) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityMilos); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Milos, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMilos); + + getData()->entityPosition = kPosition_4689; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject46, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Milos, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction137165825); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerInCar(kCarRedSleeping) && !getEntities()->isPlayerPosition(kCarRedSleeping, 1)) { + setCallback(1); + setup_enterCompartmentDialog(kCarRedSleeping, kPosition_3050); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("609Bg", kObjectCompartmentG); + break; + + case 2: + getEntities()->clearSequences(kEntityMilos); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction101687594); + + setup_function21(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Milos, function21) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param2, getState()->time, 4500); + + params->param1 = 1; + break; + + case kActionKnock: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_playSound("LIB012"); + break; + + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorNormal, kCursorNormal); + + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventMilosCompartmentVisitAugust); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (!getEvent(kEventMilosCompartmentVisitAugust) + && !getEntities()->isInsideTrainCar(kEntityPlayer, kCarRedSleeping) + && params->param1) + setup_chapter2Handler(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_playSound("Mil1118"); + break; + + case 2: + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case 3: + getAction()->playAnimation(kEventMilosCompartmentVisitAugust); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 5); + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction135024800); + + setCallback(4); + setup_function11(kTimeEnd); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Milos, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->events[kEventMilosCompartmentVisitAugust]) + setup_function24(); + else + setup_function23(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMilos); + + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorHandKnock, kCursorHand); + + ENTITY_PARAM(0, 1) = 0; + ENTITY_PARAM(0, 4) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Milos, function23) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2106000 && !params->param1) { + params->param1 = 1; + + setCallback(1); + setup_enterCompartmentDialog(kCarRedSleeping, kPosition_3050); + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction137165825); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerInCar(kCarRedSleeping) + && !getEntities()->isPlayerPosition(kCarRedSleeping, 1)) { + setCallback(3); + setup_enterCompartmentDialog(kCarRedSleeping, kPosition_3050); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("609Bg", kObjectCompartmentG); + break; + + case 2: + case 4: + getEntities()->clearSequences(kEntityMilos); + getData()->location = kLocationInsideCompartment; + getSavePoints()->push(kEntityMilos, kEntityVesna, kAction101687594); + + setup_function24(); + break; + + case 3: + setCallback(4); + setup_enterExitCompartment("609Bg", kObjectCompartmentG); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Milos, function24) + error("Milos: callback function 24 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Milos, function25) + error("Milos: callback function 25 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(26, Milos, function26, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 < getState()->time && !params->param2) { + CALLBACK_ACTION(); + break; + } + + if (getEntities()->isPlayerInCar(kCarGreenSleeping) || getEntities()->isPlayerInCar(kCarRedSleeping)) { + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { + setCallback(2); + setup_function27(kCarGreenSleeping, kPosition_540); + } else { + setCallback(3); + setup_function27(kCarRedSleeping, kPosition_9460); + } + } + break; + + case kActionDefault: + ENTITY_PARAM(0, 2) = 0; + + setCallback(1); + setup_function27(kCarRedSleeping, kPosition_540); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (ENTITY_PARAM(0, 2)) { + CALLBACK_ACTION(); + break; + } + + getEntities()->clearSequences(kEntityMilos); + break; + + case 2: + case 3: + if (ENTITY_PARAM(0, 2)) { + CALLBACK_ACTION(); + break; + } + + getEntities()->clearSequences(kEntityMilos); + + setCallback(4); + setup_updateFromTime(450); + break; + + case 4: + setCallback(5); + setup_function27(kCarRedSleeping, kPosition_540); + break; + + case 5: + if (ENTITY_PARAM(0, 2)) { + CALLBACK_ACTION(); + break; + } + + getEntities()->clearSequences(kEntityMilos); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(27, Milos, function27, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->updateEntity(kEntityMilos, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + + if (getEntities()->isDistanceBetweenEntities(kEntityMilos, kEntityPlayer, 1000) + && !getEntities()->isInGreenCarEntrance(kEntityPlayer) + && !getEntities()->isInsideCompartments(kEntityPlayer) + && !getEntities()->checkFields10(kEntityPlayer)) { + if (getData()->car == kCarRedSleeping || getData()->car == kCarGreenSleeping) { + ENTITY_PARAM(0, 2) = 1; + + CALLBACK_ACTION(); + } + } + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityMilos, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Milos, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMilos); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Milos, chapter4Handler) +#define TIME_CHECK_PLAYSOUND_MILOS(timeValue, parameter, sound) \ + if (getState()->time > timeValue && !parameter) { \ + parameter = 1; \ + getSound()->playSound(kEntityMilos, sound); \ + if (getEntities()->isDistanceBetweenEntities(kEntityMilos, kEntityPlayer, 2000)) \ + getProgress().field_94 = 1; \ + break; \ + } + + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) + break; + + if (params->param2) { + setup_function30(); + break; + } + + TIME_CHECK_PLAYSOUND_MILOS(kTime2356200, params->param3, "Mil4013"); + + TIME_CHECK_PLAYSOUND_MILOS(kTime2360700, params->param4, "Mil4014"); + + TIME_CHECK_PLAYSOUND_MILOS(kTime2370600, params->param5, "Mil4015"); + + TIME_CHECK_SAVEPOINT(kTime2407500, params->param6, kEntityMilos, kEntityVesna, kAction55996766); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getEntities()->drawSequenceLeft(kEntityMilos, "611Cg"); + getEntities()->enterCompartment(kEntityMilos, kObjectCompartmentG, true); + getSavePoints()->push(kEntityMilos, kEntityCoudert, kAction88652208); + break; + + case 2: + getEntities()->exitCompartment(kEntityMilos, kObjectCompartmentG); + + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_3050; + + getEntities()->clearSequences(kEntityMilos); + + params->param1 = 0; + break; + } + break; + + case kAction122865568: + setCallback(1); + setup_enterExitCompartment("611Bg", kObjectCompartmentG); + break; + + case kAction123852928: + setCallback(2); + setup_enterExitCompartment("611Dg", kObjectCompartmentG); + break; + + case kAction135600432: + params->param2 = 1; + break; + + case kAction221683008: + if (getSound()->isBuffered(kEntityMilos)) + getSound()->processEntry(kEntityMilos); + + params->param1 = 1; + getSavePoints()->push(kEntityMilos, kEntityCoudert, kAction123199584); + break; + } + +#undef TIME_CHECK_PLAYSOUND_MILOS +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Milos, function30) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function11(kTime2410200); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityMilos, kEntityIvo, kAction55996766); + + setCallback(2); + setup_function11(kTime2412000); + break; + + case 2: + getSavePoints()->push(kEntityMilos, kEntitySalko, kAction55996766); + + setCallback(3); + setup_function11(kTime2415600); + break; + + case 3: + setup_function31(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Milos, function31) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_enterExitCompartment("609CG", kObjectCompartmentG); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_enterCompartmentDialog(kCarGreenSleeping, kPosition_540); + break; + + case 2: + setup_function32(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Milos, function32) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityMilos); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_540; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarCoalTender; + getData()->inventoryItem = kItemNone; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Milos, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMilos); + + getData()->entityPosition = kPosition_540; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarCoalTender; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) + error("Milos: callback function 34 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Milos, function35) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityMilos); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/milos.h b/engines/lastexpress/entities/milos.h new file mode 100644 index 0000000000..4bbafaaaa7 --- /dev/null +++ b/engines/lastexpress/entities/milos.h @@ -0,0 +1,175 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_MILOS_H +#define LASTEXPRESS_MILOS_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Milos : public Entity { +public: + Milos(LastExpressEngine *engine); + ~Milos() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound16, const char* filename) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + DECLARE_FUNCTION_2(enterCompartmentDialog, CarIndex car, EntityPosition entityPosition) + DECLARE_FUNCTION_1(function11, TimeValue timeValue) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION(function13) + DECLARE_FUNCTION(function14) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function16) + DECLARE_FUNCTION(function17) + DECLARE_FUNCTION(function18) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function21) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION_1(function26, TimeValue timeValue) + DECLARE_FUNCTION_2(function27, CarIndex car, EntityPosition entityPosition) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function30) + DECLARE_FUNCTION(function31) + DECLARE_FUNCTION(function32) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function35) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_MILOS_H diff --git a/engines/lastexpress/entities/mmeboutarel.cpp b/engines/lastexpress/entities/mmeboutarel.cpp new file mode 100644 index 0000000000..ce9ebf3abd --- /dev/null +++ b/engines/lastexpress/entities/mmeboutarel.cpp @@ -0,0 +1,939 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/mmeboutarel.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +MmeBoutarel::MmeBoutarel(LastExpressEngine *engine) : Entity(engine, kEntityMmeBoutarel) { + ADD_CALLBACK_FUNCTION(MmeBoutarel, reset); + ADD_CALLBACK_FUNCTION(MmeBoutarel, playSound); + ADD_CALLBACK_FUNCTION(MmeBoutarel, draw); + ADD_CALLBACK_FUNCTION(MmeBoutarel, updateFromTime); + ADD_CALLBACK_FUNCTION(MmeBoutarel, enterExitCompartment); + ADD_CALLBACK_FUNCTION(MmeBoutarel, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(MmeBoutarel, updateEntity); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function8); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function9); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter1); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function11); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter1Handler); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function13); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function14); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function15); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function16); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter2); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter2Handler); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function19); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter3); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter3Handler); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter4); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter4Handler); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function24); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function25); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter5); + ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter5Handler); + ADD_CALLBACK_FUNCTION(MmeBoutarel, function28); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, MmeBoutarel, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, MmeBoutarel, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, MmeBoutarel, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(4, MmeBoutarel, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(5, MmeBoutarel, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(6, MmeBoutarel, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_5790, kPosition_6130, kCarRedSleeping, kObjectCompartmentD, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, MmeBoutarel, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + getInventory()->hasItem(kItemPassengerList) ? getSound()->playSound(kEntityPlayer, "CAT1021") : getSound()->excuseMeCath(); + + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(8, MmeBoutarel, function8) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param4 && params->param5) { + getSavePoints()->push(kEntityMmeBoutarel, kEntityCoudert, kAction125499160); + + if (!getEntities()->isPlayerPosition(kCarRedSleeping, 2)) + getData()->entityPosition = kPosition_2088; + + CALLBACK_ACTION(); + } + break; + + case kActionEndSound: + params->param5 = 1; + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "606U"); + getSavePoints()->push(kEntityMmeBoutarel, kEntityCoudert, kAction169557824); + break; + + case kAction155853632: + params->param4 = 1; + break; + + case kAction202558662: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "606L"); + getSound()->playSound(kEntityMmeBoutarel, (char *)¶ms->seq1); + + if (getEntities()->hasValidFrame(kEntityMmeBoutarel) || getEntities()->isDistanceBetweenEntities(kEntityMmeBoutarel, kEntityPlayer, 2000)) { + if (getProgress().chapter == kChapter1) + getProgress().field_A8 = 1; + else if (getProgress().chapter == kChapter3) + getProgress().field_A4 = 1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, MmeBoutarel, function9) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + getData()->entityPosition = getEntityData(kEntityBoutarel)->entityPosition; + getData()->location = getEntityData(kEntityBoutarel)->location; + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_enterExitCompartment("606Rd", kObjectCompartmentD); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getEntities()->clearSequences(kEntityMmeBoutarel); + getSavePoints()->push(kEntityMmeBoutarel, kEntityBoutarel, kAction203520448); + break; + + case 3: + if (getEntities()->isInsideCompartment(kEntityFrancois, kCarRedSleeping, kPosition_5790)) { + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(4); + setup_enterExitCompartment2("606Ad", kObjectCompartmentD); + } else { + params->param1 = 1; + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "606Md"); + getEntities()->enterCompartment(kEntityMmeBoutarel, kObjectCompartmentD, true); + } + break; + + case 4: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMmeBoutarel); + + CALLBACK_ACTION(); + break; + + case 5: + getEntities()->exitCompartment(kEntityMmeBoutarel, kObjectCompartmentD, true); + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityMmeBoutarel); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction100901266: + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case kAction100957716: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(5); + setup_enterExitCompartment2("606Ad", kObjectCompartmentD); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, MmeBoutarel, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityMmeBoutarel, kAction242526416, 0); + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, MmeBoutarel, function11) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 == kTimeInvalid) + break; + + if (params->param1 >= getState()->time) { + if (!getEntities()->isDistanceBetweenEntities(kEntityMmeBoutarel, kEntityPlayer, 1000) || !params->param2) + params->param2 = getState()->time + 150; + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + + setCallback(1); + setup_playSound("MME1040"); + break; + + case kActionDefault: + params->param1 = getState()->time + 1800; + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_playSound("MME1040A"); + break; + + case 2: + setCallback(3); + setup_playSound("MME1041"); + break; + + case 3: + setCallback(4); + setup_updateFromTime(900); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, MmeBoutarel, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + params->param1 = 1; + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRedSleeping, 44)) { + setCallback(1); + setup_draw("502B"); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "502A"); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "606Qd"); + getEntities()->enterCompartment(kEntityMmeBoutarel, kObjectCompartmentD, true); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + params->param1 = 1; + getEntities()->clearSequences(kEntityMmeBoutarel); + setup_function13(); + break; + } + break; + + case kAction102484312: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + params->param1 = 1; + break; + + case kAction134289824: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "502A"); + params->param1 = 0; + break; + + case kAction168986720: + getSavePoints()->push(kEntityMmeBoutarel, kEntityFrancois, kAction102752636); + getSound()->playSound(kEntityMmeBoutarel, "MME1036"); + getEntities()->exitCompartment(kEntityMmeBoutarel, kObjectCompartmentD, true); + + setCallback(3); + setup_enterExitCompartment("606Fd", kObjectCompartmentD); + break; + + case kAction202221040: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationOutsideCompartment; + + getSound()->playSound(kEntityMmeBoutarel, "MME1035A"); + + if (getEntities()->hasValidFrame(kEntityMmeBoutarel) || getEntities()->isDistanceBetweenEntities(kEntityMmeBoutarel, kEntityPlayer, 2000) ) + getProgress().field_AC = 1; + + setCallback(2); + setup_enterExitCompartment("606Ed", kObjectCompartmentD); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, MmeBoutarel, function13) + error("MmeBoutarel: callback function 13 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, MmeBoutarel, function14) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("606Dd", kObjectCompartmentD); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "503"); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "503"); + + setCallback(3); + setup_playSound("MRB1080"); + break; + + case 3: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(4); + setup_enterExitCompartment("606Cd", kObjectCompartmentD); + break; + + case 4: + getEntities()->clearSequences(kEntityMmeBoutarel); + + setup_function15(); + break; + } + break; + + case kAction101107728: + setCallback(2); + setup_function9(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, MmeBoutarel, function15) + error("MmeBoutarel: callback function 15 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, MmeBoutarel, function16) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getEntities()->clearSequences(kEntityMmeBoutarel); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, MmeBoutarel, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMmeBoutarel); + + getData()->entityPosition = kPosition_4689; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject43, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, MmeBoutarel, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEntities()->isInsideCompartment(kEntityFrancois, kCarRedSleeping, kPosition_5790)) { + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(2); + setup_enterExitCompartment2("606Ad", kObjectCompartmentD); + } else { + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "606Md"); + getEntities()->enterCompartment(kEntityMmeBoutarel, kObjectCompartmentD, true); + } + break; + + case 2: + case 3: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getData()->location = kLocationInsideCompartment; + setup_function19(); + break; + } + break; + + case kAction100901266: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case kAction100957716: + getEntities()->exitCompartment(kEntityMmeBoutarel, kObjectCompartmentD, true); + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(3); + setup_enterExitCompartment2("606Ad", kObjectCompartmentD); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, MmeBoutarel, function19) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isPlayerPosition(kCarRedSleeping, 44) && !params->param2) { + if (params->param1) { + setCallback(1); + setup_draw("502B"); + } else { + params->param1 = 1; + } + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + params->param2 = 1; + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (getEntities()->isPlayerPosition(kCarRedSleeping , 44)) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 11); + } + break; + + case kAction102484312: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + params->param2 = 1; + break; + + case kAction134289824: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "502A"); + params->param2 = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, MmeBoutarel, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMmeBoutarel); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, MmeBoutarel, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(0, 1) && params->param2 != kTimeInvalid) { + + if (getState()->time <= kTime2038500) { + if (!getEntities()->isPlayerInCar(kCarRedSleeping) + || !params->param1 + || getSound()->isBuffered("FRA2012") + || getSound()->isBuffered("FRA2010") + ||!params->param2) + params->param2 = getState()->time; + + if (params->param2 >= getState()->time) + break; + } + + params->param2 = kTimeInvalid; + + getSavePoints()->push(kEntityMmeBoutarel, kEntityFrancois, kAction189872836); + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_enterExitCompartment("606Cd", kObjectCompartmentD); + } + break; + + case kActionDefault: + params->param1 = 1; + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject43, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("606Rd", kObjectCompartmentD); + break; + + case 2: + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 3: + setCallback(4); + setup_function8("MME3001"); + break; + + case 4: + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_5790); + break; + + case 5: + setCallback(6); + setup_enterExitCompartment2("606Td", kObjectCompartmentD); + break; + + case 6: + getEntities()->clearSequences(kEntityMmeBoutarel); + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setCallback(7); + setup_updateFromTime(150); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment("606Dd", kObjectCompartmentD); + break; + + case 8: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + getSavePoints()->push(kEntityMmeBoutarel, kEntityFrancois, kAction190390860); + break; + + case 9: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + params->param1 = 1; + break; + } + break; + + case kAction101107728: + setCallback(9); + setup_function9(); + break; + + case kAction102484312: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + params->param1 = 1; + break; + + case kAction134289824: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "502A"); + params->param1 = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, MmeBoutarel, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMmeBoutarel); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, MmeBoutarel, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM(params->param2, getState()->time, 900); + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); + + setCallback(1); + setup_enterExitCompartment("606Cd", kObjectCompartmentD); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityMmeBoutarel); + setup_function24(); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + params->param1 = 1; + break; + } + break; + + case kAction101107728: + setCallback(2); + setup_function9(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, MmeBoutarel, function24) + error("MmeBoutarel: callback function 24 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, MmeBoutarel, function25) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityMmeBoutarel); + + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, MmeBoutarel, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityMmeBoutarel); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, MmeBoutarel, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function28(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, MmeBoutarel, function28) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM(params->param3, getState()->timeTicks, 75); + + params->param1 = 0; + params->param2 = 1; + + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param3 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (params->param1) { + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + params->param1 = 0; + + setCallback(1); + setup_playSound(getSound()->justCheckingCath()); + break; + } + + setCallback(savepoint.action == kActionKnock ? 2 : 3); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_5790; + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityMmeBoutarel); + break; + + case kActionDrawScene: + if (params->param1 || params->param2) { + params->param1 = 0; + params->param2 = 0; + + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case 2: + case 3: + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(4); + setup_playSound("Mme5001"); + break; + + case 4: + params->param1 = 1; + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorTalk, kCursorNormal); + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + + case kAction155604840: + getObjects()->update(kObjectCompartmentD, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject51, kEntityMmeBoutarel, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(29, MmeBoutarel) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/mmeboutarel.h b/engines/lastexpress/entities/mmeboutarel.h new file mode 100644 index 0000000000..548a0635cb --- /dev/null +++ b/engines/lastexpress/entities/mmeboutarel.h @@ -0,0 +1,164 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_MMEBOUTAREL_H +#define LASTEXPRESS_MMEBOUTAREL_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class MmeBoutarel : public Entity { +public: + MmeBoutarel(LastExpressEngine *engine); + ~MmeBoutarel() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_1(function8, const char *soundName) + + DECLARE_FUNCTION(function9) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION(function11) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function13) + DECLARE_FUNCTION(function14) + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION(function16) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function19) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function28) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_MMEBOUTAREL_H diff --git a/engines/lastexpress/entities/pascale.cpp b/engines/lastexpress/entities/pascale.cpp new file mode 100644 index 0000000000..dfb0854eda --- /dev/null +++ b/engines/lastexpress/entities/pascale.cpp @@ -0,0 +1,1232 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/pascale.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Pascale::Pascale(LastExpressEngine *engine) : Entity(engine, kEntityPascale) { + ADD_CALLBACK_FUNCTION(Pascale, draw); + ADD_CALLBACK_FUNCTION(Pascale, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Pascale, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Pascale, updateFromTime); + ADD_CALLBACK_FUNCTION(Pascale, updatePosition); + ADD_CALLBACK_FUNCTION(Pascale, playSound); + ADD_CALLBACK_FUNCTION(Pascale, draw2); + ADD_CALLBACK_FUNCTION(Pascale, welcomeSophieAndRebecca); + ADD_CALLBACK_FUNCTION(Pascale, sitSophieAndRebecca); + ADD_CALLBACK_FUNCTION(Pascale, welcomeCath); + ADD_CALLBACK_FUNCTION(Pascale, function11); + ADD_CALLBACK_FUNCTION(Pascale, chapter1); + ADD_CALLBACK_FUNCTION(Pascale, getMessageFromAugustToTyler); + ADD_CALLBACK_FUNCTION(Pascale, sitAnna); + ADD_CALLBACK_FUNCTION(Pascale, welcomeAnna); + ADD_CALLBACK_FUNCTION(Pascale, serveTatianaVassili); + ADD_CALLBACK_FUNCTION(Pascale, chapter1Handler); + ADD_CALLBACK_FUNCTION(Pascale, function18); + ADD_CALLBACK_FUNCTION(Pascale, function19); + ADD_CALLBACK_FUNCTION(Pascale, chapter2); + ADD_CALLBACK_FUNCTION(Pascale, chapter3); + ADD_CALLBACK_FUNCTION(Pascale, chapter3Handler); + ADD_CALLBACK_FUNCTION(Pascale, function23); + ADD_CALLBACK_FUNCTION(Pascale, welcomeAbbot); + ADD_CALLBACK_FUNCTION(Pascale, chapter4); + ADD_CALLBACK_FUNCTION(Pascale, chapter4Handler); + ADD_CALLBACK_FUNCTION(Pascale, function27); + ADD_CALLBACK_FUNCTION(Pascale, messageFromAnna); + ADD_CALLBACK_FUNCTION(Pascale, function29); + ADD_CALLBACK_FUNCTION(Pascale, function30); + ADD_CALLBACK_FUNCTION(Pascale, chapter5); + ADD_CALLBACK_FUNCTION(Pascale, chapter5Handler); + ADD_CALLBACK_FUNCTION(Pascale, function33); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(1, Pascale, draw) + Entity::draw(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(2, Pascale, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Pascale, callbackActionOnDirection) + if (savepoint.action == kActionExcuseMeCath) { + if (!params->param1) { + getSound()->excuseMe(kEntityPascale); + params->param1 = 1; + } + + return; + } + + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(4, Pascale, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(5, Pascale, updatePosition) + Entity::updatePosition(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Pascale, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(7, Pascale, draw2) + Entity::draw2(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Pascale, welcomeSophieAndRebecca) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_850; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("901"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + switch (getProgress().chapter) { + default: + break; + + case kChapter1: + getSound()->playSound(kEntityPascale, "REB1198", SoundManager::kFlagInvalid, 30); + break; + + case kChapter3: + getSound()->playSound(kEntityPascale, "REB3001", SoundManager::kFlagInvalid, 30); + break; + + case kChapter4: + getSound()->playSound(kEntityPascale, "REB4001", SoundManager::kFlagInvalid, 30); + break; + } + + setCallback(2); + setup_sitSophieAndRebecca(); + break; + + case 2: + getSavePoints()->push(kEntityPascale, kEntityRebecca, kAction157370960); + + setCallback(3); + setup_draw("905"); + break; + + case 3: + getEntities()->clearSequences(kEntityPascale); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 4) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Pascale, sitSophieAndRebecca) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityPascale, "012C1"); + getEntities()->drawSequenceLeft(kEntityRebecca, "012C2"); + getEntities()->drawSequenceLeft(kEntityTables3, "012C3"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Pascale, welcomeCath) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 && !getSound()->isBuffered(kEntityPascale)) + getEntities()->updatePositionExit(kEntityPascale, kCarRestaurant, 64); + break; + + case kActionExitCompartment: + if (!params->param2) { + params->param2 = 1; + + getSound()->playSound(kEntityPascale, "HED1001A"); + getSound()->playSound(kEntityPlayer, "LIB004"); + + getScenes()->loadSceneFromPosition(kCarRestaurant, 69); + } + + CALLBACK_ACTION(); + break; + + case kAction4: + if (!params->param1) { + params->param1 = 1; + getSound()->playSound(kEntityPascale, "HED1001"); + } + break; + + case kActionDefault: + getEntities()->updatePositionEnter(kEntityPascale, kCarRestaurant, 64); + getEntities()->drawSequenceRight(kEntityPascale, "035A"); + break; + + case kActionDrawScene: + if (params->param1 && getEntities()->isPlayerPosition(kCarRestaurant, 64)) { + getSound()->playSound(kEntityPascale, "HED1001A"); + getSound()->playSound(kEntityPlayer, "LIB004"); + + getScenes()->loadSceneFromPosition(kCarRestaurant, 69); + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Pascale, function11) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + getSavePoints()->push(kEntityPascale, kEntityAugust, kAction168046720); + getSavePoints()->push(kEntityPascale, kEntityAnna, kAction168046720); + getSavePoints()->push(kEntityPascale, kEntityAlexei, kAction168046720); + getEntities()->updatePositionEnter(kEntityPascale, kCarRestaurant, 55); + + setCallback(1); + setup_welcomeCath(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityPascale, kEntityAugust, kAction168627977); + getSavePoints()->push(kEntityPascale, kEntityAnna, kAction168627977); + getSavePoints()->push(kEntityPascale, kEntityAlexei, kAction168627977); + getEntities()->updatePositionExit(kEntityPascale, kCarRestaurant, 55); + + setCallback(2); + setup_draw("905"); + break; + + case 2: + getEntities()->clearSequences(kEntityPascale); + getData()->entityPosition = kPosition_5900; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Pascale, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter1Handler(); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityPascale, kAction239072064, 0); + getSavePoints()->addData(kEntityPascale, kAction257489762, 2); + getSavePoints()->addData(kEntityPascale, kAction207769280, 6); + getSavePoints()->addData(kEntityPascale, kAction101824388, 7); + getSavePoints()->addData(kEntityPascale, kAction136059947, 8); + getSavePoints()->addData(kEntityPascale, kAction223262556, 1); + getSavePoints()->addData(kEntityPascale, kAction269479296, 3); + getSavePoints()->addData(kEntityPascale, kAction352703104, 4); + getSavePoints()->addData(kEntityPascale, kAction352768896, 5); + getSavePoints()->addData(kEntityPascale, kAction191604416, 10); + getSavePoints()->addData(kEntityPascale, kAction190605184, 11); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Pascale, getMessageFromAugustToTyler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("902"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (!ENTITY_PARAM(1, 3)) { + getEntities()->drawSequenceLeft(kEntityPascale, "010E"); + getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + + setCallback(2); + setup_playSound("AUG1001"); + break; + } + + setCallback(3); + setup_draw("905"); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityPascale, "010B"); + + setCallback(3); + setup_draw("905"); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityPascale); + getSavePoints()->push(kEntityPascale, kEntityVerges, kActionDeliverMessageToTyler); + ENTITY_PARAM(0, 1) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Pascale, sitAnna) + switch (savepoint.action) { + default: + break; + + case kActionExitCompartment: + getEntities()->updatePositionExit(kEntityPascale, kCarRestaurant, 62); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + getEntities()->drawSequenceRight(kEntityTables0, "001C3"); + getEntities()->drawSequenceRight(kEntityAnna, "001C2"); + getEntities()->drawSequenceRight(kEntityPascale, "001C1"); + + getEntities()->updatePositionEnter(kEntityPascale, kCarRestaurant, 62); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Pascale, welcomeAnna) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("901"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSound()->playSound(kEntityPascale, "ANN1047"); + + setCallback(2); + setup_sitAnna(); + break; + + case 2: + getSavePoints()->push(kEntityPascale, kEntityAnna, kAction157370960); + + setCallback(3); + setup_draw("904"); + break; + + case 3: + getEntities()->clearSequences(kEntityPascale); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 2) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Pascale, serveTatianaVassili) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("903"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityPascale, kEntityTatiana, kAction122358304); + getEntities()->drawSequenceLeft(kEntityPascale, "014B"); + getEntities()->updatePositionEnter(kEntityPascale, kCarRestaurant, 67); + + if (getSound()->isBuffered("TAT1069A")) + getSound()->processEntry("TAT1069A"); + else if (getSound()->isBuffered("TAT1069B")) + getSound()->processEntry("TAT1069B"); + + setCallback(2); + setup_playSound("TAT1066"); + break; + + case 2: + getEntities()->updatePositionExit(kEntityPascale, kCarRestaurant, 67); + getSavePoints()->push(kEntityPascale, kEntityTatiana, kAction122288808); + + setCallback(3); + setup_draw("906"); + break; + + case 3: + getEntities()->clearSequences(kEntityPascale); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 3) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Pascale, chapter1Handler) +switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param2) { + if (getEntities()->isPlayerPosition(kCarRestaurant, 69) + || getEntities()->isPlayerPosition(kCarRestaurant, 70) + || getEntities()->isPlayerPosition(kCarRestaurant, 71)) + params->param2 = 1; + + if (!params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 61)) + params->param1 = 1; + } + + if (!getEntities()->isInKitchen(kEntityPascale)) + break; + + if (ENTITY_PARAM(0, 5) && ENTITY_PARAM(0, 6)) { + setup_function18(); + break; + } + + if (!getEntities()->isSomebodyInsideRestaurantOrSalon()) + goto label_callback3; + + if (params->param1 && !params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 61)) { + setCallback(1); + setup_function11(); + break; + } + +label_callback1: + if (ENTITY_PARAM(0, 1) && !ENTITY_PARAM(1, 3)) { + setCallback(2); + setup_getMessageFromAugustToTyler(); + break; + } + +label_callback2: + if (ENTITY_PARAM(0, 3)) { + setCallback(3); + setup_serveTatianaVassili(); + break; + } + +label_callback3: + if (ENTITY_PARAM(0, 2)) { + setCallback(4); + setup_welcomeAnna(); + break; + } + +label_callback4: + if (ENTITY_PARAM(0, 4)) { + setCallback(5); + setup_welcomeSophieAndRebecca(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 0; + params->param2 = 1; + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + + case 4: + goto label_callback4; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Pascale, function18) + if (savepoint.action != kActionNone) + return; + + if (getState()->time > kTime1242000 && !params->param1) { + params->param1 = 1; + + getSavePoints()->push(kEntityPascale, kEntityServers0, kAction101632192); + getSavePoints()->push(kEntityPascale, kEntityServers1, kAction101632192); + getSavePoints()->push(kEntityPascale, kEntityCooks, kAction101632192); + getSavePoints()->push(kEntityPascale, kEntityVerges, kAction101632192); + + setup_function19(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Pascale, function19) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1 && getEntityData(kEntityPlayer)->entityPosition < kPosition_3650) { + getObjects()->update(kObject65, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getSavePoints()->push(kEntityPascale, kEntityTables0, kActionDrawTablesWithChairs, "001P"); + getSavePoints()->push(kEntityPascale, kEntityTables1, kActionDrawTablesWithChairs, "005J"); + getSavePoints()->push(kEntityPascale, kEntityTables2, kActionDrawTablesWithChairs, "009G"); + getSavePoints()->push(kEntityPascale, kEntityTables3, kActionDrawTablesWithChairs, "010M"); + getSavePoints()->push(kEntityPascale, kEntityTables4, kActionDrawTablesWithChairs, "014F"); + getSavePoints()->push(kEntityPascale, kEntityTables5, kActionDrawTablesWithChairs, "024D"); + + params->param1 = 1; + } + break; + + case kActionDefault: + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + + getEntities()->clearSequences(kEntityPascale); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Pascale, chapter2) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityPascale); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObject65, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Pascale, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityPascale); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 7) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Pascale, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getEntities()->isInKitchen(kEntityPascale)) + break; + + if (ENTITY_PARAM(0, 7)) { + setCallback(1); + setup_function23(); + break; + } + +label_callback: + if (ENTITY_PARAM(0, 4)) { + setCallback(2); + setup_welcomeSophieAndRebecca(); + } + break; + + case kActionCallback: + if (getCallback() == 1) + goto label_callback; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Pascale, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + getEntities()->updatePositionEnter(kEntityPascale, kCarRestaurant, 67); + + setCallback(1); + setup_welcomeAbbot(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->updatePositionExit(kEntityPascale, kCarRestaurant, 67); + getSavePoints()->push(kEntityPascale, kEntityAbbot, kAction122288808); + + setCallback(2); + setup_draw("906"); + break; + + case 2: + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 7) = 0; + getEntities()->clearSequences(kEntityPascale); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Pascale, welcomeAbbot) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + getSound()->playSound(kEntityPascale, "ABB3015A"); + params->param1 = 1; + } + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kAction10: + getSavePoints()->push(kEntityPascale, kEntityTables4, kAction136455232); + break; + + case kActionDefault: + getSound()->playSound(kEntityPascale, "ABB3015", SoundManager::kFlagInvalid, 105); + getEntities()->drawSequenceRight(kEntityPascale, "029A1"); + getEntities()->drawSequenceRight(kEntityAbbot, "029A2"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Pascale, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityPascale); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 8) = 0; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Pascale, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2511000 && !params->param4) { + params->param2 = 1; + params->param4 = 1; + } + + if (!getEntities()->isInKitchen(kEntityPascale)) + break; + + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + if (ENTITY_PARAM(0, 8)) { + setCallback(1); + setup_function27(); + break; + } + +label_callback1: + if (ENTITY_PARAM(1, 2) && ENTITY_PARAM(1, 4)) { + if (!params->param3) + params->param3 = getState()->time + 9000; + + if (params->param5 != kTimeInvalid) { + + if (params->param3 < getState()->time) { + params->param5 = kTimeInvalid; + setCallback(2); + setup_messageFromAnna(); + break; + } + + if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param5) + params->param5 = getState()->time; + + if (params->param5 < getState()->time) { + params->param5 = kTimeInvalid; + setCallback(2); + setup_messageFromAnna(); + break; + } + } + } + +label_callback2: + if (params->param1 && !params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 61)) { + setCallback(3); + setup_function11(); + break; + } + } + +label_callback3: + if (ENTITY_PARAM(0, 4)) { + setCallback(4); + setup_welcomeSophieAndRebecca(); + } + break; + + case kActionDefault: + if (getEntities()->isPlayerPosition(kCarRestaurant, 69) + || getEntities()->isPlayerPosition(kCarRestaurant, 70) + || getEntities()->isPlayerPosition(kCarRestaurant, 71)) + params->param2 = 1; + break; + + case kActionDrawScene: + if (!params->param2) { + if (getEntities()->isPlayerPosition(kCarRestaurant, 69) + || getEntities()->isPlayerPosition(kCarRestaurant, 70) + || getEntities()->isPlayerPosition(kCarRestaurant, 71)) + params->param2 = 1; + + if (!params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 61)) + params->param1 = 1; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + params->param1 = 0; + params->param2 = 1; + goto label_callback3; + } + break; + + case kAction201431954: + ENTITY_PARAM(0, 4) = 0; + ENTITY_PARAM(0, 8) = 0; + + getSavePoints()->push(kEntityPascale, kEntityTables0, kActionDrawTablesWithChairs, "001P"); + getSavePoints()->push(kEntityPascale, kEntityTables1, kActionDrawTablesWithChairs, "005J"); + getSavePoints()->push(kEntityPascale, kEntityTables2, kActionDrawTablesWithChairs, "009G"); + getSavePoints()->push(kEntityPascale, kEntityTables3, kActionDrawTablesWithChairs, "010M"); + getSavePoints()->push(kEntityPascale, kEntityTables4, kActionDrawTablesWithChairs, "014F"); + getSavePoints()->push(kEntityPascale, kEntityTables5, kActionDrawTablesWithChairs, "024D"); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Pascale, function27) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(1, 1)) { + setCallback(2); + setup_updateFromTime(450); + } + break; + + case kActionDefault: + setCallback(1); + setup_function29(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityPascale); + break; + + case 2: + getSavePoints()->push(kEntityPascale, kEntityCoudert, kAction123712592); + + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + setCallback(4); + setup_function30(); + break; + + case 4: + getEntities()->clearSequences(kEntityPascale); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 8) = 0; + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 1; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Pascale, messageFromAnna) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("902"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityPascale, kEntityAugust, kAction122358304); + getEntities()->drawSequenceLeft(kEntityPascale, "010E2"); + + setCallback(2); + setup_playSound("Aug4001"); + break; + + case 2: + getSavePoints()->push(kEntityPascale, kEntityAugust, kAction123793792); + + setCallback(3); + setup_draw("905"); + break; + + case 3: + getEntities()->clearSequences(kEntityPascale); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(1, 2) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Pascale, function29) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("817DD"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceRight(kEntityPascale, "817DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityPascale); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + getData()->entityPosition = kPosition_850; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Pascale, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_9270; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("817US"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceRight(kEntityPascale, "817UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityPascale); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + getData()->entityPosition = kPosition_5900; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Pascale, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityPascale); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Pascale, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function33(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Pascale, function33) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param4) { + UPDATE_PARAM_PROC(params->param5, getState()->time, 4500) + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_playSound("Wat5010"); + break; + UPDATE_PARAM_PROC_END + } + +label_callback1: + if (params->param1) { + UPDATE_PARAM(params->param6, getState()->timeTicks, 75); + + params->param1 = 0; + params->param2 = 2; + + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param6 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (params->param1) { + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorNormal, kCursorNormal); + params->param1 = 0; + + setCallback(2); + setup_playSound(getSound()->justCheckingCath()); + } else { + setCallback(savepoint.action == kActionKnock ? 3 : 4); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param2 || params->param1) { + params->param1 = 0; + params->param2 = 0; + params->param3 = 0; + + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorHandKnock, kCursorHand); + goto label_callback1; + + case 2: + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case 3: + case 4: + params->param3++; + + if (params->param3 == 1 || params->param3 == 2) { + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorNormal, kCursorNormal); + setCallback(params->param3 == 1 ? 5 : 6); + setup_playSound(params->param3 == 1 ? "Wat5001" : "Wat5002"); + } + break; + + case 5: + params->param1 = 1; + getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorTalk, kCursorNormal); + break; + + case 6: + params->param2 = 1; + break; + + case 7: + params->param4 = 1; + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + + case kAction169750080: + if (getSound()->isBuffered(kEntityPascale)) { + params->param4 = 1; + } else { + setCallback(7); + setup_playSound("Wat5002"); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(34, Pascale) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/pascale.h b/engines/lastexpress/entities/pascale.h new file mode 100644 index 0000000000..d899037c0b --- /dev/null +++ b/engines/lastexpress/entities/pascale.h @@ -0,0 +1,166 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_PASCALE_H +#define LASTEXPRESS_PASCALE_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Pascale : public Entity { +public: + Pascale(LastExpressEngine *engine); + ~Pascale() {}; + + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates the position + * + * @param savepoint The savepoint + * - The sequence to draw + * - The car + * - The position + */ + DECLARE_FUNCTION_NOSETUP(updatePosition) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Draws the entity along with another one + * + * @param savepoint The savepoint + * - The sequence to draw + * - The sequence to draw for the second entity + * - The EntityIndex of the second entity + */ + DECLARE_FUNCTION_NOSETUP(draw2) + + DECLARE_FUNCTION(welcomeSophieAndRebecca) + DECLARE_FUNCTION(sitSophieAndRebecca) + DECLARE_FUNCTION(welcomeCath) + DECLARE_FUNCTION(function11) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION(getMessageFromAugustToTyler) + DECLARE_FUNCTION(sitAnna) + DECLARE_FUNCTION(welcomeAnna) + DECLARE_FUNCTION(serveTatianaVassili) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function18) + DECLARE_FUNCTION(function19) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(welcomeAbbot) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(messageFromAnna) + DECLARE_FUNCTION(function29) + DECLARE_FUNCTION(function30) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function33) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_PASCALE_H diff --git a/engines/lastexpress/entities/rebecca.cpp b/engines/lastexpress/entities/rebecca.cpp new file mode 100644 index 0000000000..b9c3f23401 --- /dev/null +++ b/engines/lastexpress/entities/rebecca.cpp @@ -0,0 +1,1732 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/rebecca.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Rebecca::Rebecca(LastExpressEngine *engine) : Entity(engine, kEntityRebecca) { + ADD_CALLBACK_FUNCTION(Rebecca, reset); + ADD_CALLBACK_FUNCTION(Rebecca, updateFromTime); + ADD_CALLBACK_FUNCTION(Rebecca, playSound); + ADD_CALLBACK_FUNCTION(Rebecca, playSound16); + ADD_CALLBACK_FUNCTION(Rebecca, callSavepoint); + ADD_CALLBACK_FUNCTION(Rebecca, draw); + ADD_CALLBACK_FUNCTION(Rebecca, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Rebecca, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Rebecca, enterExitCompartment3); + ADD_CALLBACK_FUNCTION(Rebecca, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Rebecca, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Rebecca, updateEntity); + ADD_CALLBACK_FUNCTION(Rebecca, updatePosition); + ADD_CALLBACK_FUNCTION(Rebecca, draw2); + ADD_CALLBACK_FUNCTION(Rebecca, function15); + ADD_CALLBACK_FUNCTION(Rebecca, function16); + ADD_CALLBACK_FUNCTION(Rebecca, function17); + ADD_CALLBACK_FUNCTION(Rebecca, function18); + ADD_CALLBACK_FUNCTION(Rebecca, function19); + ADD_CALLBACK_FUNCTION(Rebecca, function20); + ADD_CALLBACK_FUNCTION(Rebecca, chapter1); + ADD_CALLBACK_FUNCTION(Rebecca, chapter1Handler); + ADD_CALLBACK_FUNCTION(Rebecca, function23); + ADD_CALLBACK_FUNCTION(Rebecca, function24); + ADD_CALLBACK_FUNCTION(Rebecca, function25); + ADD_CALLBACK_FUNCTION(Rebecca, function26); + ADD_CALLBACK_FUNCTION(Rebecca, function27); + ADD_CALLBACK_FUNCTION(Rebecca, chapter2); + ADD_CALLBACK_FUNCTION(Rebecca, chapter2Handler); + ADD_CALLBACK_FUNCTION(Rebecca, function30); + ADD_CALLBACK_FUNCTION(Rebecca, function31); + ADD_CALLBACK_FUNCTION(Rebecca, chapter3); + ADD_CALLBACK_FUNCTION(Rebecca, chapter3Handler); + ADD_CALLBACK_FUNCTION(Rebecca, function34); + ADD_CALLBACK_FUNCTION(Rebecca, function35); + ADD_CALLBACK_FUNCTION(Rebecca, function36); + ADD_CALLBACK_FUNCTION(Rebecca, function37); + ADD_CALLBACK_FUNCTION(Rebecca, function38); + ADD_CALLBACK_FUNCTION(Rebecca, function39); + ADD_CALLBACK_FUNCTION(Rebecca, function40); + ADD_CALLBACK_FUNCTION(Rebecca, function41); + ADD_CALLBACK_FUNCTION(Rebecca, chapter4); + ADD_CALLBACK_FUNCTION(Rebecca, chapter4Handler); + ADD_CALLBACK_FUNCTION(Rebecca, function44); + ADD_CALLBACK_FUNCTION(Rebecca, function45); + ADD_CALLBACK_FUNCTION(Rebecca, chapter5); + ADD_CALLBACK_FUNCTION(Rebecca, chapter5Handler); + ADD_CALLBACK_FUNCTION(Rebecca, function48); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Rebecca, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(2, Rebecca, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Rebecca, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(4, Rebecca, playSound16) + Entity::playSound(savepoint, false, getSound()->getSoundFlag(kEntityCoudert)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(5, Rebecca, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Rebecca, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(7, Rebecca, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(8, Rebecca, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_4840, kPosition_4455, kCarRedSleeping, kObjectCompartmentE, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(9, Rebecca, enterExitCompartment3, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Rebecca, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Rebecca, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(12, Rebecca, updateEntity, CarIndex, EntityPosition) + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(13, Rebecca, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SSI(14, Rebecca, draw2, EntityIndex) + Entity::draw2(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Rebecca, function15) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (getEntities()->isOutsideAnnaWindow()) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + + setCallback(1); + setup_enterExitCompartment2("624Ae", kObjectCompartmentE); + break; + + case kActionCallback: + if (getCallback() == 1) { + getObjects()->update(kObjectOutsideBetweenCompartments, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityRebecca); + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(16, Rebecca, function16, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param2) { + if (getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntitySophie, 750)) { + if (!getEntities()->hasValidFrame(kEntitySophie)) { + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + } + } + } + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment(params->param1 ? "624Be" : "623Ee", kObjectCompartmentE); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction125242096); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getEntities()->clearSequences(kEntityRebecca); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("810US"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityRebecca, "012B"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityRebecca); + + setCallback(4); + setup_callbackActionOnDirection(); + break; + + case 5: + getEntities()->drawSequenceLeft(kEntityRebecca, "012A"); + if (getProgress().chapter == kChapter3) + getSound()->playSound(kEntityRebecca, "REB3000"); + + getSavePoints()->push(kEntityRebecca, kEntityPascale, kAction269479296); + + params->param2 = 1; + break; + } + break; + + case kAction157370960: + getSavePoints()->push(kEntityRebecca, kEntityTables3, kAction136455232); + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(17, Rebecca, function17, bool) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntitySophie, 750) + && !getEntities()->hasValidFrame(kEntitySophie)) { + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + + setCallback(3); + setup_updateFromTime(0); + } + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("624Be", kObjectCompartmentE); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getData()->location = kLocationOutsideCompartment; + + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction125242096); + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getEntities()->clearSequences(kEntitySophie); + break; + + case 3: + setCallback(4); + setup_callbackActionRestaurantOrSalon(); + break; + + case 4: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + if (getProgress().chapter == kChapter3) + getSound()->playSound(kEntityRebecca, "Reb3005", SoundManager::kFlagInvalid, 75); + + if (params->param1) { + setCallback(5); + setup_updatePosition("118A", kCarRestaurant, 52); + } else { + getEntities()->updatePositionEnter(kEntityRebecca, kCarRestaurant, 57); + + setCallback(6); + setup_draw2("107A1", "107A2", kEntitySophie); + } + break; + + case 5: + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + + case 6: + getEntities()->updatePositionExit(kEntityRebecca, kCarRestaurant, 57); + getEntities()->clearSequences(kEntitySophie); + + getData()->location = kLocationInsideCompartment; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Rebecca, function18) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntitySophie, 750) + || getEntities()->checkDistanceFromPosition(kEntitySophie, kPosition_4840, 500)) { + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + getEntities()->exitCompartment(kEntityRebecca, kObjectCompartmentE, true); + + setCallback(3); + setup_function15(); + } + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_9270; + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction136654208); + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntitySophie, 750) + || getEntities()->checkDistanceFromPosition(kEntitySophie, kPosition_4840, 500)) { + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + + setCallback(2); + setup_function15(); + } else { + getEntities()->drawSequenceLeft(kEntityRebecca, "623Ge"); + getEntities()->enterCompartment(kEntityRebecca, kObjectCompartmentE, true); + } + break; + + case 2: + case 3: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Rebecca, function19) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntitySophie, 750) + || getEntities()->checkDistanceFromPosition(kEntitySophie, kPosition_4840, 500)) { + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + getEntities()->exitCompartment(kEntityRebecca, kObjectCompartmentE, true); + + setCallback(6); + setup_function15(); + } + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_callSavepoint("012H", kEntityTables3, kActionDrawTablesWithChairs, "010M"); + break; + + case 2: + getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction337548856); + getEntities()->drawSequenceRight(kEntityRebecca, "810DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityRebecca); + + setCallback(4); + setup_callbackActionOnDirection(); + break; + + case 3: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_9270; + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction136654208); + + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case 4: + if (getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntitySophie, 750) + || getEntities()->checkDistanceFromPosition(kEntitySophie, kPosition_4840, 500)) { + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + + setCallback(5); + setup_function15(); + } else { + getEntities()->drawSequenceLeft(kEntityRebecca, "623Ge"); + getEntities()->enterCompartment(kEntityRebecca, kObjectCompartmentE, true); + } + break; + + case 5: + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(20, Rebecca, function20, TimeValue) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 < getState()->time && !params->param5) { + params->param5 = 1; + + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + + if (!params->param2) { + params->param6 = 0; + } else { + UPDATE_PARAM_PROC(params->param6, getState()->timeTicks, 75) + params->param2 = 0; + params->param3 = 1; + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + + params->param6 = 0; + UPDATE_PARAM_PROC_END + } + + if (getProgress().chapter == kChapter1 && !ENTITY_PARAM(0, 3)) { + if (params->param7 != kTimeInvalid && getState()->time > kTime1174500) { + if (getState()->time <= kTime1183500) { + if (!getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntityPlayer, 2000) || getSound()->isBuffered("CON1210") || !params->param7) + params->param7 = getState()->time; + + if (params->param7 >= getState()->time) + goto label_callback; + } + + params->param7 = kTimeInvalid; + ENTITY_PARAM(0, 3) = 1; + + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(1); + setup_playSound("REB1205"); + break; + } + goto label_callback; + } + + if (getProgress().chapter == kChapter3 && !ENTITY_PARAM(0, 4) && params->param8 != kTimeInvalid && getState()->time > kTime2097000) { + if (getState()->time <= kTime2106000) { + if (!getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntityPlayer, 1000) || !params->param8) + params->param8 = getState()->time; + + if (params->param8 >= getState()->time) + goto label_callback; + } + + params->param8 = kTimeInvalid; + ENTITY_PARAM(0, 4) = 1; + + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(2); + setup_playSound("REB3010"); + break; + } + +label_callback: + if (ENTITY_PARAM(0, 2) && getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntityPlayer, 1000)) { + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(3); + setup_playSound("REB1040"); + } + break; + + case kActionKnock: + case kActionOpenDoor: + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + + break; + + case kActionDrawScene: + if (params->param3 || params->param2) { + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param2 = 0; + params->param3 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + case 3: + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + + if (getCallback() != 2) + ENTITY_PARAM(0, 2) = 0; + + if (getCallback() != 3) + goto label_callback; + break; + + case 4: + case 5: + if (rnd(2)) { + setCallback(6); + setup_playSound("REB1039"); + } else { + setCallback(7); + setup_playSound(rnd(2) ? "SOP1039" : "SOP1039A"); + } + break; + + case 6: + case 7: + params->param4 = (getCallback() == 6 ? 0 : 1); + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorTalk, kCursorNormal); + params->param2 = 1; + break; + + case 8: + case 9: + case 10: + case 11: + params->param2 = 0; + params->param3 = 1; + break; + + case 12: + setCallback(13); + setup_playSound16("JAC1012B"); + break; + + case 13: + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } + break; + + case kAction254915200: + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(12); + setup_playSound("REB1039A"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Rebecca, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityRebecca, kAction224253538, 0); + + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectOutsideBetweenCompartments, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getObjects()->updateLocation2(kObject110, kObjectLocation1); + + getData()->entityPosition = kPosition_2830; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + + ENTITY_PARAM(0, 2) = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Rebecca, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_PLAYSOUND(kTime1084500, params->param3, 1, "REB1015"); + + if (params->param4 == kTimeInvalid) + goto label_callback_4; + + if (getState()->time > kTime1080000) + goto label_playConversation; + + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param4) + params->param4 = getState()->time + 150; + + if (params->param4 >= getState()->time) { +label_callback_4: + if (params->param1) { + UPDATE_PARAM_CHECK(params->param5, getState()->time, 900) + if (getEntities()->isInSalon(kEntityPlayer)) { + setCallback(5); + setup_playSound("REB1013"); + break; + } + } + } + +label_callback_5: + if (params->param2) { + UPDATE_PARAM(params->param6, getState()->timeTicks, 90); + getScenes()->loadSceneFromPosition(kCarRestaurant, 55); + } else { + params->param6 = 0; + } + } else { +label_playConversation: + params->param4 = kTimeInvalid; + + if (getEntities()->isInSalon(kEntityPlayer)) + getProgress().field_B8 = 1; + + setCallback(4); + setup_playSound("REB1012"); + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityRebecca, "107B"); + break; + + case kActionDrawScene: + params->param2 = (getEntities()->isPlayerPosition(kCarRestaurant, 57) ? 1 : 0); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updatePosition("107C", kCarRestaurant, 57); + break; + + case 2: + setCallback(3); + setup_function18(); + break; + + case 3: + setup_function23(); + break; + + case 4: + params->param1 = 1; + goto label_callback_4; + + case 5: + getProgress().field_B4 = 1; + params->param1 = 0; + goto label_callback_5; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Rebecca, function23) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_2(kTime1111500, params->param2, 3, setup_enterExitCompartment, "623De", kObjectCompartmentE); + break; + + case kActionDefault: + setCallback(1); + setup_updateFromTime(900); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("623Ce", kObjectCompartmentE); + break; + + case 2: + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getEntities()->drawSequenceLeft(kEntityRebecca, "504"); + break; + + case 3: + case 6: + getEntities()->clearSequences(kEntityRebecca); + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + + setCallback((byte)(getCallback() + 1)); + setup_function20(kTime1120500); + break; + + case 4: + case 5: + if (ENTITY_PARAM(0, 1)) { + setup_function24(); + } else { + setCallback(5); + setup_function20((TimeValue)(getState()->time + 900)); + } + break; + + case 7: + case 8: + if (ENTITY_PARAM(0, 1)) { + setup_function24(); + } else { + setCallback(8); + setup_function20((TimeValue)(getState()->time + 900)); + } + break; + } + break; + + case kAction285528346: + setCallback(6); + setup_enterExitCompartment("623De", kObjectCompartmentE); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Rebecca, function24) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_SAVEPOINT(kTime1134000, params->param2, kEntityRebecca, kEntityServers0, kAction223712416); + + if (!params->param1) + break; + + TIME_CHECK_CALLBACK(kTime1165500, params->param3, 6, setup_function19); + + if (params->param4 != kTimeInvalid) { + if (getState()->time <= kTime1161000) { + if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param4) + params->param4 = getState()->time + 150; + + if (params->param4 >= getState()->time) + break; + } + + params->param4 = kTimeInvalid; + + setCallback(7); + setup_playSound("REB1200A"); + } + break; + + case kActionDefault: + setCallback(1); + setup_function16(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityRebecca, "012D"); + + setCallback(2); + setup_playSound("REB1199"); + break; + + case 2: + if (getEntities()->isInRestaurant(kEntityPlayer)) { + setCallback(3); + setup_playSound("REB1199A"); + break; + } + // Fallback to next case + + case 3: + if (getCallback() == 3) + getProgress().field_BC = 1; + + if (getEntities()->isInRestaurant(kEntityAnna)) { + setCallback(4); + setup_playSound("REB1199B"); + break; + } + // Fallback to next case + + case 4: + setCallback(5); + setup_playSound("REB1199C"); + break; + + case 6: + setup_function25(); + break; + + case 8: + getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction136702400); + getEntities()->drawSequenceLeft(kEntityRebecca, "012G"); + params->param1 = 1; + break; + } + break; + + case kAction123712592: + getEntities()->drawSequenceLeft(kEntityServers0, "BLANK"); + getEntities()->drawSequenceLeft(kEntityRebecca, "012E"); + + setCallback(8); + setup_playSound("REB1200"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Rebecca, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(kTime1184400); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function17(false); + break; + + case 2: + setup_function26(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Rebecca, function26) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_3(kTime1224000, params->param2, 1, setup_updatePosition, "118H", kCarRestaurant, 52); + + if (params->param1) { + UPDATE_PARAM(params->param3, getState()->timeTicks, 90); + + getScenes()->loadSceneFromPosition(kCarRestaurant, 51); + } + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityRebecca, "118D"); + break; + + case kActionDrawScene: + params->param1 = getEntities()->isPlayerPosition(kCarRestaurant, 52); + params->param3 = 0; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function18(); + break; + + case 2: + setup_function27(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Rebecca, function27) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getEntities()->clearSequences(kEntityRebecca); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Rebecca, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityRebecca); + + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getObjects()->updateLocation2(kObject110, kObjectLocation2); + + ENTITY_PARAM(0, 2) = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Rebecca, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(kTime1764000); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function17(false); + break; + + case 2: + setup_function30(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Rebecca, function30) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1 && params->param4 != kTimeInvalid) { + + if (getState()->time <= kTimeEnd) + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param4) + params->param4 = getState()->time + 450; + + if (params->param4 < getState()->time || getState()->time > kTimeEnd) { + params->param4 = kTimeInvalid; + + getSound()->playSound(kEntityRebecca, "Reb2001"); + getProgress().field_B0 = 1; + params->param2 = 1; + } + } + + if (!params->param3 && !params->param2 && params->param5 != kTimeInvalid) { + + if (getState()->time <= kTime10881000) { + if (!getEntities()->isInSalon(kEntityPlayer) || !params->param5) + params->param5 = getState()->time + 450; + + if (params->param5 >= getState()->time) + break; + } + + params->param5 = kTimeInvalid; + + getSavePoints()->push(kEntityRebecca, kEntityAugust, kAction169358379); + } + break; + + case kActionEndSound: + params->param2 = 0; + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityRebecca, "107B"); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function31(); + break; + + case kAction125496184: + setCallback(1); + setup_function18(); + break; + + case kAction155465152: + getEntities()->drawSequenceLeft(kEntityRebecca, "BLANK"); + break; + + case kAction155980128: + params->param1 = 1; + params->param3 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Rebecca, function31) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateFromTime(900); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("623CE", kObjectCompartmentE); + break; + + case 2: + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation2, kCursorNormal, kCursorNormal); + getEntities()->drawSequenceLeft(kEntityRebecca, "504"); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Rebecca, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityRebecca); + + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Rebecca, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(kTime2016000); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function34(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Rebecca, function34) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 == kTimeInvalid) { + if (getState()->time <= kTime1386000) { + if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param2) + params->param2 = getState()->time; + + if (params->param2 >= getState()->time) { + TIME_CHECK_CALLBACK(kTime2052000, params->param3, 1, setup_function19); + break; + } + } + + params->param2 = kTimeInvalid; + + getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction223712416); + } + + TIME_CHECK_CALLBACK(kTime2052000, params->param3, 1, setup_function19); + break; + + case kActionEndSound: + setCallback(5); + setup_playSound("Reb3004"); + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_function16(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityRebecca, "012D"); + getData()->location = kLocationInsideCompartment; + + setCallback(2); + setup_playSound("Reb3002"); + break; + + case 3: + setup_function35(); + break; + + case 4: + getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction136702400); + getEntities()->drawSequenceLeft(kEntityRebecca, "012G"); + params->param1 = 1; + break; + } + break; + + case kAction123712592: + getEntities()->drawSequenceLeft(kEntityServers0, "BLANK"); + getSound()->playSound(kEntityRebecca, "Reb3003"); + + setCallback(4); + setup_draw("012E"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Rebecca, function35) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(kTime2070000); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function36(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Rebecca, function36) + error("Rebecca: callback function 36 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Rebecca, function37) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(kTime2110500); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function38(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Rebecca, function38) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_enterExitCompartment3("624Be", kObjectCompartmentE); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction259921280); + + setCallback(2); + setup_updateEntity(kCarKronos, kPosition_9270); + break; + + case 2: + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + setup_function39(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Rebecca, function39) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityRebecca); + + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarKronos; + break; + + case kAction191668032: + setup_function40(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Rebecca, function40) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_9270; + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_2740); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction292775040); + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + break; + + case 2: + getSavePoints()->push(kEntityRebecca, kEntityAnna, kAction191668032); + setCallback(3); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case 3: + getSavePoints()->push(kEntityRebecca, kEntitySophie, kAction123668192); + setCallback(4); + setup_function15(); + break; + + case 4: + setup_function41(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Rebecca, function41) + if (savepoint.action == kActionDefault) { + ENTITY_PARAM(0, 2) = 1; + + setCallback(1); + setup_function20(kTimeEnd); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Rebecca, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityRebecca); + + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->updateLocation2(kObject110, kObjectLocation3); + + ENTITY_PARAM(0, 1) = 0; + ENTITY_PARAM(0, 2) = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, Rebecca, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function20(kTime2385000); + break; + + case kActionCallback: + if (getCallback() == 1 || getCallback() == 2) { + if (ENTITY_PARAM(0, 1)) { + setup_function44(); + } else { + setCallback(2); + setup_function20((TimeValue)(getState()->time + 900)); + } + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Rebecca, function44) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param3 != kTimeInvalid) { + if (getState()->time <= kTime2412000) { + if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param3) + params->param3 = getState()->time; + + if (params->param3 >= getState()->time) + goto label_next; + } + + params->param3 = kTimeInvalid; + + getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction223712416); + } + +label_next: + if (params->param1 && params->param4 != kTimeInvalid) { + if (getState()->time <= kTime2430000) { + if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param4) + params->param4 = getState()->time + 150; + + if (params->param4 >= getState()->time) + goto label_callback_2; + } + + params->param4 = kTimeInvalid; + + setCallback(2); + setup_playSound("Reb4004"); + break; + } + +label_callback_2: + if (params->param2) + TIME_CHECK_CALLBACK(kTime2443500, params->param5, 3, setup_function19); + break; + + case kActionEndSound: + if (getEntities()->isInRestaurant(kEntityPlayer)) { + setCallback(5); + setup_playSound("Reb4004"); + break; + } + + params->param1 = 1; + break; + + case kActionDefault: + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_function16(true); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityRebecca, "012D"); + getData()->location = kLocationInsideCompartment; + break; + + case 2: + goto label_callback_2; + + case 3: + setup_function45(); + break; + + case 4: + getSavePoints()->push(kEntityRebecca, kEntityServers0, kAction136702400); + getEntities()->drawSequenceLeft(kEntityRebecca, "012G"); + params->param2 = 1; + break; + } + break; + + case kAction123712592: + getEntities()->drawSequenceLeft(kEntityRebecca, "BLANK"); + getSound()->playSound(kEntityRebecca, "Reb4003"); + + setCallback(4); + setup_draw("012E"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, Rebecca, function45) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject52, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getEntities()->clearSequences(kEntityRebecca); + break; + + case kActionCallback: + if (getCallback() == 1) + params->param1 = 1; + break; + + case kAction205034665: + if (!params->param1 && getState()->time < kTime2511000) { + setCallback(1); + setup_playSound("Reb6969"); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Rebecca, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityRebecca); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + getObjects()->updateLocation2(kObject110, kObjectLocation4); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, Rebecca, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function48(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Rebecca, function48) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + UPDATE_PARAM(params->param3, getState()->timeTicks, 75); + + params->param1 = 0; + params->param2 = 1; + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param3 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (params->param1) { + params->param1 = 0; + + setCallback(2); + setup_playSound(getSound()->justCheckingCath()); + } else { + setCallback(savepoint.action == kActionKnock ? 3 : 4); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + + setCallback(1); + setup_enterExitCompartment("624AE", kObjectCompartmentE); + break; + + case kActionDrawScene: + if (params->param1 || params->param2) { + params->param1 = 0; + params->param2 = 0; + + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityRebecca); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_4840; + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case 3: + case 4: + setCallback(5); + setup_playSound("Reb5001"); + break; + + case 5: + params->param1 = 1; + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorTalk, kCursorNormal); + break; + } + break; + + case kAction135800432: + setup_nullfunction(); + break; + + case kAction155604840: + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(49, Rebecca) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/rebecca.h b/engines/lastexpress/entities/rebecca.h new file mode 100644 index 0000000000..bf836b1fa3 --- /dev/null +++ b/engines/lastexpress/entities/rebecca.h @@ -0,0 +1,230 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_REBECCA_H +#define LASTEXPRESS_REBECCA_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Rebecca : public Entity { +public: + Rebecca(LastExpressEngine *engine); + ~Rebecca() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound16, const char* filename) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment3, const char* sequence, ObjectIndex compartment) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Draws the entity along with another one + * + * @param sequence1 The sequence to draw + * @param sequence2 The sequence to draw for the second entity + * @param entity The EntityIndex of the second entity + */ + DECLARE_FUNCTION_3(draw2, const char* sequence1, const char* sequence2, EntityIndex entity) + + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION_1(function16, bool) + DECLARE_FUNCTION_1(function17, bool) + DECLARE_FUNCTION(function18) + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION_1(function20, TimeValue timeValue) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function30) + DECLARE_FUNCTION(function31) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + DECLARE_FUNCTION(function36) + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + DECLARE_FUNCTION(function39) + DECLARE_FUNCTION(function40) + DECLARE_FUNCTION(function41) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function44) + DECLARE_FUNCTION(function45) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function48) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_REBECCA_H diff --git a/engines/lastexpress/entities/salko.cpp b/engines/lastexpress/entities/salko.cpp new file mode 100644 index 0000000000..688208f30a --- /dev/null +++ b/engines/lastexpress/entities/salko.cpp @@ -0,0 +1,642 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/salko.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/fight.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Salko::Salko(LastExpressEngine *engine) : Entity(engine, kEntitySalko) { + ADD_CALLBACK_FUNCTION(Salko, reset); + ADD_CALLBACK_FUNCTION(Salko, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Salko, draw); + ADD_CALLBACK_FUNCTION(Salko, updateEntity); + ADD_CALLBACK_FUNCTION(Salko, updateFromTime); + ADD_CALLBACK_FUNCTION(Salko, savegame); + ADD_CALLBACK_FUNCTION(Salko, function7); + ADD_CALLBACK_FUNCTION(Salko, function8); + ADD_CALLBACK_FUNCTION(Salko, chapter1); + ADD_CALLBACK_FUNCTION(Salko, chapter1Handler); + ADD_CALLBACK_FUNCTION(Salko, function11); + ADD_CALLBACK_FUNCTION(Salko, chapter2); + ADD_CALLBACK_FUNCTION(Salko, function13); + ADD_CALLBACK_FUNCTION(Salko, chapter3); + ADD_CALLBACK_FUNCTION(Salko, chapter3Handler); + ADD_CALLBACK_FUNCTION(Salko, function16); + ADD_CALLBACK_FUNCTION(Salko, function17); + ADD_CALLBACK_FUNCTION(Salko, chapter4); + ADD_CALLBACK_FUNCTION(Salko, chapter4Handler); + ADD_CALLBACK_FUNCTION(Salko, function20); + ADD_CALLBACK_FUNCTION(Salko, function21); + ADD_CALLBACK_FUNCTION(Salko, function22); + ADD_CALLBACK_FUNCTION(Salko, chapter5); + ADD_CALLBACK_FUNCTION(Salko, chapter5Handler); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Salko, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(2, Salko, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(3, Salko, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(4, Salko, updateEntity, CarIndex, EntityPosition) + Entity::updateEntity(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(5, Salko, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(6, Salko, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, Salko, function7, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: { + params->param3 = 0; + + EntityDirection direction = getData()->direction; + CarIndex carSalko = getData()->car; + CarIndex carIvo = getEntityData(kEntityIvo)->car; + EntityPosition positionSalko = getData()->entityPosition; + EntityPosition positionIvo = getEntityData(kEntityIvo)->entityPosition; + + if (getEntities()->isDistanceBetweenEntities(kEntitySalko, kEntityIvo, 500) + || (direction == kDirectionUp && (carSalko > carIvo || (carSalko == carIvo && positionSalko > positionIvo))) + || (direction == kDirectionDown && (carSalko < carIvo || (carSalko == carIvo && positionSalko < positionIvo)))) { + getData()->field_49B = 0; + params->param3 = 1; + } + + if (!params->param3) + getEntities()->updateEntity(kEntitySalko, (CarIndex)params->param1, (EntityPosition)params->param2); + + } + break; + + case kActionExcuseMeCath: + case kActionExcuseMe: + getSound()->playSound(kEntityPlayer, "ZFX1002", getSound()->getSoundFlag(kEntitySalko)); + getSound()->playSound(kEntityPlayer, "CAT1127A"); + break; + + case kActionDefault: + getEntities()->updateEntity(kEntitySalko, (CarIndex)params->param1, (EntityPosition)params->param2); + break; + + case kAction123668192: + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Salko, function8) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Salko, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4691; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Salko, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->entityPosition = getEntityData(kEntityIvo)->entityPosition; + getData()->location = getEntityData(kEntityIvo)->location; + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->clearSequences(kEntitySalko); + setup_function8(); + } + break; + + case kAction125242096: + setCallback(1); + setup_function7(kCarRedSleeping, kPosition_2740); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Salko, function11) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntitySalko); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Salko, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntitySalko); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + + case kAction136184016: + setCallback(1); + setup_function13(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Salko, function13) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("612DH", kObjectCompartmentH); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getSavePoints()->push(kEntitySalko, kEntityIvo, kAction102675536); + getEntities()->clearSequences(kEntitySalko); + break; + + case 3: + getEntities()->drawSequenceLeft(kEntitySalko, "BLANK"); + getData()->location = kLocationInsideCompartment; + + setup_function8(); + break; + } + break; + + case kAction125242096: + setCallback(3); + setup_function7(kCarRedSleeping, kPosition_2740); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Salko, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntitySalko); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Salko, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time < kTime2200500) { + UPDATE_PARAM(params->param1, getState()->time, 81000); + + setCallback(1); + setup_function16(); + } + break; + + case kActionCallback: + if (getCallback() == 1) + params->param1 = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Salko, function16) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->hasValidFrame(kEntitySalko) && getEntities()->isDistanceBetweenEntities(kEntitySalko, kEntityPlayer, 5000)) { + getSavePoints()->push(kEntitySalko, kEntityMax, kAction158007856); + + setCallback(3); + setup_updateFromTime(75); + break; + } + +label_callback3: + UPDATE_PARAM(params->param1, getState()->time, 4500); + + getSavePoints()->push(kEntitySalko, kEntitySalko, kAction101169464); + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("612DH", kObjectCompartmentH); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + break; + + case 2: + break; + + case 3: + getSavePoints()->push(kEntitySalko, kEntitySalko, kAction101169464); + goto label_callback3; + + case 4: + getEntities()->exitCompartment(kEntitySalko, kObjectCompartmentF, true); + + setCallback(5); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 5: + setCallback(6); + setup_updateFromTime(4500); + break; + + case 6: + setCallback(7); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + break; + + case 7: + setCallback(8); + setup_enterExitCompartment("612Ch", kObjectCompartmentH); + break; + + case 8: + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_2740; + getEntities()->clearSequences(kEntitySalko); + + CALLBACK_ACTION(); + break; + } + break; + + case kAction101169464: + setCallback(4); + setup_enterExitCompartment("612Bf", kObjectCompartmentF); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Salko, function17) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_6470; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_2740); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("612Ch", kObjectCompartmentH); + break; + + case 2: + getEntities()->clearSequences(kEntitySalko); + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getSavePoints()->push(kEntitySalko, kEntityMilos, kAction157691176); + + setup_chapter3Handler(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Salko, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntitySalko); + + getData()->entityPosition = kPosition_5420; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Salko, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->drawSequenceLeft(kEntitySalko, "BLANK"); + + getData()->location = kLocationInsideCompartment; + + setup_function20(); + } + break; + + case kAction125242096: + setCallback(1); + setup_function7(kCarRedSleeping, kPosition_2740); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Salko, function20) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + getEntities()->clearSequences(kEntitySalko); + setup_function21(); + break; + } + break; + + case kAction55996766: + setCallback(1); + setup_enterExitCompartment("612Dh", kObjectCompartmentH); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Salko, function21) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2422800 && !params->param1) { + params->param1 = 1; + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_2740); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("612Ch", kObjectCompartmentH); + break; + + case 2: + setup_function22(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Salko, function22) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntitySalko); + getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_2740; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Salko, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntitySalko); + + getData()->entityPosition = kPosition_9460; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Salko, chapter5Handler) + switch (savepoint.action) { + default: + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getSound()->isBuffered("MUS050")) + getSound()->processEntry("MUS050"); + + getAction()->playAnimation(kEventCathSalkoTrainTopFight); + + setCallback(2); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case 2: + params->param1 = getFight()->setup(kFightSalko); + + if (params->param1 == Fight::kFightEndWin) { + getState()->time += 1800; + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventCathSalkoTrainTopWin); + } else { + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, params->param1 == Fight::kFightEndLost); + } + break; + + case 3: + getAction()->playAnimation(kEventCathSalkoTrainTopWin); + getSavePoints()->push(kEntitySalko, kEntityVesna, kAction134427424); + + getScenes()->loadSceneFromPosition(kCarRestaurant, 10); + setup_nullfunction(); + break; + } + break; + + case kAction167992577: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCathSalkoTrainTopFight); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(25, Salko) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/salko.h b/engines/lastexpress/entities/salko.h new file mode 100644 index 0000000000..49059c4b40 --- /dev/null +++ b/engines/lastexpress/entities/salko.h @@ -0,0 +1,149 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_SALKO_H +#define LASTEXPRESS_SALKO_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Salko : public Entity { +public: + Salko(LastExpressEngine *engine); + ~Salko() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Draws the entity + * + * @param savepoint The savepoint + * - The sequence to draw + */ + DECLARE_FUNCTION_NOSETUP(draw) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + DECLARE_FUNCTION_2(function7, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION(function8) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function11) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + DECLARE_FUNCTION(function13) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function16) + DECLARE_FUNCTION(function17) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SALKO_H diff --git a/engines/lastexpress/entities/servers0.cpp b/engines/lastexpress/entities/servers0.cpp new file mode 100644 index 0000000000..33f2943c43 --- /dev/null +++ b/engines/lastexpress/entities/servers0.cpp @@ -0,0 +1,1039 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/servers0.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +#define HANDLE_TABLE(index, param, callback, function) \ + if (ENTITY_PARAM(index, param)) { \ + setCallback(callback); \ + function(); \ + break; \ + } + +Servers0::Servers0(LastExpressEngine *engine) : Entity(engine, kEntityServers0) { + ADD_CALLBACK_FUNCTION(Servers0, callSavepoint); + ADD_CALLBACK_FUNCTION(Servers0, updateFromTime); + ADD_CALLBACK_FUNCTION(Servers0, draw); + ADD_CALLBACK_FUNCTION(Servers0, updatePosition); + ADD_CALLBACK_FUNCTION(Servers0, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Servers0, playSound); + ADD_CALLBACK_FUNCTION(Servers0, function7); + ADD_CALLBACK_FUNCTION(Servers0, function8); + ADD_CALLBACK_FUNCTION(Servers0, function9); + ADD_CALLBACK_FUNCTION(Servers0, function10); + ADD_CALLBACK_FUNCTION(Servers0, chapter1); + ADD_CALLBACK_FUNCTION(Servers0, function12); + ADD_CALLBACK_FUNCTION(Servers0, function13); + ADD_CALLBACK_FUNCTION(Servers0, function14); + ADD_CALLBACK_FUNCTION(Servers0, function15); + ADD_CALLBACK_FUNCTION(Servers0, function16); + ADD_CALLBACK_FUNCTION(Servers0, function17); + ADD_CALLBACK_FUNCTION(Servers0, function18); + ADD_CALLBACK_FUNCTION(Servers0, function19); + ADD_CALLBACK_FUNCTION(Servers0, chapter1Handler); + ADD_CALLBACK_FUNCTION(Servers0, function21); + ADD_CALLBACK_FUNCTION(Servers0, function22); + ADD_CALLBACK_FUNCTION(Servers0, chapter2); + ADD_CALLBACK_FUNCTION(Servers0, chapter2Handler); + ADD_CALLBACK_FUNCTION(Servers0, function25); + ADD_CALLBACK_FUNCTION(Servers0, function26); + ADD_CALLBACK_FUNCTION(Servers0, chapter3); + ADD_CALLBACK_FUNCTION(Servers0, chapter3Handler); + ADD_CALLBACK_FUNCTION(Servers0, augustAnnaDateOrder); + ADD_CALLBACK_FUNCTION(Servers0, function30); + ADD_CALLBACK_FUNCTION(Servers0, chapter4); + ADD_CALLBACK_FUNCTION(Servers0, chapter4Handler); + ADD_CALLBACK_FUNCTION(Servers0, augustOrderSteak); + ADD_CALLBACK_FUNCTION(Servers0, augustServeDuck); + ADD_CALLBACK_FUNCTION(Servers0, function35); + ADD_CALLBACK_FUNCTION(Servers0, chapter5); + ADD_CALLBACK_FUNCTION(Servers0, chapter5Handler); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(1, Servers0, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(2, Servers0, updateFromTime) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Servers0, draw) + Entity::draw(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(4, Servers0, updatePosition) + Entity::updatePosition(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(5, Servers0, callbackActionOnDirection) + EXPOSE_PARAMS(EntityData::EntityParametersIIII); + + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getData()->direction != kDirectionRight) + CALLBACK_ACTION(); + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + if (!params->param1) { + getSound()->excuseMe(kEntityServers0); + params->param1 = 1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Servers0, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Servers0, function7) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + ENTITY_PARAM(0, 3) = 0; + + setCallback(1); + setup_draw("911"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityServers0); + getSavePoints()->push(kEntityServers0, kEntityRebecca, kAction123712592); + break; + + case 2: + getEntities()->clearSequences(kEntityServers0); + getData()->entityPosition = kPosition_5900; + CALLBACK_ACTION(); + break; + } + break; + + case kAction136702400: + setCallback(2); + setup_draw("913"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Servers0, function8) + serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "913", &ENTITY_PARAM(1, 2)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Servers0, function9) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("915"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122358304); + getEntities()->drawSequenceLeft(kEntityServers0, "029D"); + + setCallback(2); + setup_playSound(getProgress().chapter == kChapter3 ? "Abb3016" : "Abb4001"); + break; + + case 2: + getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122288808); + + setCallback(3); + setup_draw("917"); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers0); + ENTITY_PARAM(2, 2) = 0; + ENTITY_PARAM(1, 6) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Servers0, function10) + serveTable(savepoint, "916", kEntityTables4, "014E", "014F", "918", &ENTITY_PARAM(2, 3), false); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Servers0, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter1Handler(); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityServers0, kAction270410280, 0); + getSavePoints()->addData(kEntityServers0, kAction304061224, 1); + getSavePoints()->addData(kEntityServers0, kAction252568704, 10); + getSavePoints()->addData(kEntityServers0, kAction286534136, 11); + getSavePoints()->addData(kEntityServers0, kAction218983616, 12); + getSavePoints()->addData(kEntityServers0, kAction218586752, 13); + getSavePoints()->addData(kEntityServers0, kAction207330561, 14); + getSavePoints()->addData(kEntityServers0, kAction286403504, 16); + getSavePoints()->addData(kEntityServers0, kAction218128129, 17); + getSavePoints()->addData(kEntityServers0, kAction270068760, 18); + getSavePoints()->addData(kEntityServers0, kAction223712416, 2); + getSavePoints()->addData(kEntityServers0, kAction237485916, 5); + getSavePoints()->addData(kEntityServers0, kAction188893625, 8); + getSavePoints()->addData(kEntityServers0, kAction204704037, 6); + getSavePoints()->addData(kEntityServers0, kAction292758554, 7); + getSavePoints()->addData(kEntityServers0, kAction337548856, 9); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Servers0, function12) + handleServer(savepoint, "907", kEntityAnna, kAction268773672, &ENTITY_PARAM(0, 1)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Servers0, function13) + handleServer(savepoint, "911", kEntityAugust, kAction268773672, &ENTITY_PARAM(0, 2), "010F"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Servers0, function14) + handleServer(savepoint, "908", kEntityAnna, kAction170016384, &ENTITY_PARAM(0, 4)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Servers0, function15) + handleServer(savepoint, "912", kEntityAugust, kAction170016384, &ENTITY_PARAM(0, 5)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Servers0, function16) + serveTable(savepoint, "907", kEntityTables0, "001N", "001P", "909", &ENTITY_PARAM(0, 6)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Servers0, function17) + serveTable(savepoint, "915", kEntityTables4, "014E", "014F", "917", &ENTITY_PARAM(1, 1), true, false, 67); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Servers0, function18) + serveTable(savepoint, "911", kEntityTables3, "010L", "010H", "913", &ENTITY_PARAM(0, 7)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Servers0, function19) + serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "913", &ENTITY_PARAM(0, 8), true, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Servers0, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2) { + UPDATE_PARAM_PROC(params->param3, getState()->time, 2700); + ENTITY_PARAM(0, 4) = 1; + params->param2 = 0; + UPDATE_PARAM_PROC_END + } + + if (params->param1) { + UPDATE_PARAM_PROC(params->param4, getState()->time, 4500) + ENTITY_PARAM(0, 5) = 1; + params->param1 = 0; + UPDATE_PARAM_PROC_END + } + + if (!getEntities()->isInKitchen(kEntityServers0) && !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + HANDLE_TABLE(0, 1, 1, setup_function12); + HANDLE_TABLE(0, 2, 2, setup_function13); + HANDLE_TABLE(0, 3, 3, setup_function7); + HANDLE_TABLE(0, 4, 4, setup_function14); + HANDLE_TABLE(0, 5, 5, setup_function15); + HANDLE_TABLE(0, 6, 6, setup_function16); + HANDLE_TABLE(1, 1, 7, setup_function17); + HANDLE_TABLE(0, 7, 8, setup_function18); + HANDLE_TABLE(0, 8, 9, setup_function19); + HANDLE_TABLE(1, 2, 10, setup_function8); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 10: + getSavePoints()->push(kEntityServers0, kEntityPascale, kAction352703104); + setup_function21(); + break; + + case 11: + case 12: + getEntities()->clearSequences(kEntityServers0); + getData()->entityPosition = kPosition_5900; + + if (getCallback() == 11) + params->param2 = 1; + else + params->param1 = 1; + break; + + case 13: + case 14: + getEntities()->clearSequences(kEntityServers0); + getData()->entityPosition = kPosition_5900; + break; + } + break; + + case kAction136702400: + setCallback(savepoint.entity2 == kEntityAnna ? 13 : 14); + setup_draw(savepoint.entity2 == kEntityAnna ? "909" : "913"); + break; + + case kAction203859488: + setCallback(savepoint.entity2 == kEntityAnna ? 11 : 12); + setup_draw(savepoint.entity2 == kEntityAnna ? "910" : "913"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Servers0, function21) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5900; + break; + + case kAction101632192: + setup_function22(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Servers0, function22) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + + getEntities()->clearSequences(kEntityServers0); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Servers0, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers0); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Servers0, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getEntities()->isInKitchen(kEntityServers0) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + HANDLE_TABLE(1, 3, 1, setup_function25); + HANDLE_TABLE(1, 4, 2, setup_function26); + break; + + case kActionCallback: + if (getCallback() == 1) + HANDLE_TABLE(1, 4, 2, setup_function26); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Servers0, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("957"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityServers0, kEntityAugust, kAction123712592); + getEntities()->drawSequenceLeft(kEntityServers0, "BLANK"); + break; + + case 2: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers0); + ENTITY_PARAM(1, 3) = 0; + + CALLBACK_ACTION(); + break; + } + break; + + case kAction219522616: + setCallback(2); + setup_draw("959"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Servers0, function26) + serveTable(savepoint, "957", kEntityTables0, "016E", "016D", "959", &ENTITY_PARAM(1, 4)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Servers0, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers0); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 5) = 0; + ENTITY_PARAM(1, 6) = 0; + ENTITY_PARAM(2, 3) = 0; + ENTITY_PARAM(2, 4) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Servers0, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + if (ENTITY_PARAM(1, 5)) { + setCallback(1); + setup_augustAnnaDateOrder(); + break; + } + +label_callback_1: + if (ENTITY_PARAM(1, 6)) { + setCallback(2); + setup_function9(); + break; + } + +label_callback_2: + if (ENTITY_PARAM(2, 4)) { + setCallback(3); + setup_function30(); + break; + } + +label_callback_3: + if (ENTITY_PARAM(2, 3)) { + setCallback(4); + setup_function10(); + break; + } + +label_callback_4: + if (ENTITY_PARAM(0, 3)) { + setCallback(5); + setup_function7(); + break; + } + +label_callback_5: + if (ENTITY_PARAM(1, 2)) { + setCallback(6); + setup_function8(); + break; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Servers0, augustAnnaDateOrder) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("911"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityServers0, kEntityAnna, kAction122358304); + getEntities()->drawSequenceLeft(kEntityServers0, "026D"); + + setCallback(2); + setup_playSound("Ann3138"); + break; + + case 2: + getSavePoints()->push(kEntityServers0, kEntityAnna, kAction122288808); + + setCallback(3); + setup_draw("913"); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers0); + ENTITY_PARAM(1, 5) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Servers0, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("916"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122358304); + getEntities()->drawSequenceLeft(kEntityServers0, "029D"); + + setCallback(2); + setup_playSound("Abb3016a"); + break; + + case 2: + getSavePoints()->push(kEntityServers0, kEntityAbbot, kAction122288808); + + setCallback(3); + setup_draw("918"); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers0); + ENTITY_PARAM(2, 4) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Servers0, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers0); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 8) = 0; + ENTITY_PARAM(2, 1) = 0; + ENTITY_PARAM(2, 2) = 0; + ENTITY_PARAM(2, 3) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Servers0, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM_PROC(params->param2, getState()->time, 3600) + ENTITY_PARAM(1, 8) = 1; + params->param1 = 0; + UPDATE_PARAM_PROC_END + + if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + if (ENTITY_PARAM(1, 7)) { + setCallback(1); + setup_augustOrderSteak(); + break; + } + +label_callback_1: + if (ENTITY_PARAM(1, 8)) { + setCallback(2); + setup_augustServeDuck(); + break; + } + +label_callback_2: + if (ENTITY_PARAM(2, 1)) { + setCallback(3); + setup_function35(); + break; + } + +label_callback_3: + if (ENTITY_PARAM(2, 2)) { + setCallback(4); + setup_function9(); + break; + } + +label_callback_4: + if (ENTITY_PARAM(2, 3)) { + setCallback(5); + setup_function10(); + break; + } + +label_callback_5: + if (ENTITY_PARAM(0, 3)) { + setCallback(6); + setup_function7(); + break; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 1; + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + } + break; + + case kAction201431954: + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(1, 7) = 0; + ENTITY_PARAM(1, 8) = 0; + ENTITY_PARAM(2, 1) = 0; + ENTITY_PARAM(2, 3) = 0; + params->param1 = 0; + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Servers0, augustOrderSteak) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_draw("911"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityServers0, "010F3"); + getEntities()->drawSequenceLeft(kEntityAugust, "010D3"); + + setCallback(2); + setup_playSound("AUG4002"); + break; + + case 2: + getSavePoints()->push(kEntityServers0, kEntityAugust, kAction122288808); + + setCallback(3); + setup_draw("913"); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers0); + ENTITY_PARAM(1, 7) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Servers0, augustServeDuck) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_draw("912"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityServers0, kEntityAugust, kAction122358304); + getSound()->playSound(kEntityServers0, "AUG1053"); + + setCallback(2); + setup_draw("010G3"); + break; + + case 2: + getSavePoints()->push(kEntityServers0, kEntityAugust, kAction201964801); + + setCallback(3); + setup_draw("914"); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers0); + ENTITY_PARAM(1, 8) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Servers0, function35) + serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "914", &ENTITY_PARAM(2, 1), false, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Servers0, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers0); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Servers0, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_nullfunction(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(38, Servers0) + + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Servers0::handleServer(const SavePoint &savepoint, const char* name, EntityIndex entity, ActionIndex action, uint *parameter, const char* name2) { + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw(name); + break; + + case kActionCallback: + if (getCallback() == 1) { + // Prepare or draw sequences depending of value of string + if (strcmp(name2, "")) + getEntities()->clearSequences(kEntityServers0); + else + getEntities()->drawSequenceLeft(kEntityServers0, name2); + + getSavePoints()->push(kEntityServers0, entity, action); + *parameter = 0; + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +void Servers0::serveTable(const SavePoint &savepoint, const char* seq1, EntityIndex entity, const char* seq2, const char* seq3, const char* seq4, uint *parameter, bool shouldUpdatePosition, bool pushSavepoint, Position position) { + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (shouldUpdatePosition) { + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + } + + setCallback(1); + setup_draw(seq1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (position) + getEntities()->updatePositionEnter(kEntityServers0, kCarRestaurant, position); + + getSavePoints()->push(kEntityServers0, entity, kAction136455232); + + setCallback(2); + setup_callSavepoint(seq2, entity, kActionDrawTablesWithChairs, seq3); + break; + + case 2: + if (position) + getEntities()->updatePositionExit(kEntityServers0, kCarRestaurant, position); + + setCallback(3); + setup_draw(seq4); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + + // Special case for functions 19 & 35 + if (pushSavepoint) + getSavePoints()->push(kEntityServers0, kEntityRebecca, kAction224253538); + + getEntities()->clearSequences(kEntityServers0); + *parameter = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/servers0.h b/engines/lastexpress/entities/servers0.h new file mode 100644 index 0000000000..61a060f0c2 --- /dev/null +++ b/engines/lastexpress/entities/servers0.h @@ -0,0 +1,173 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_SERVERS0_H +#define LASTEXPRESS_SERVERS0_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Servers0 : public Entity { +public: + Servers0(LastExpressEngine *engine); + ~Servers0() {}; + + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint + * - Time to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTime) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION_NOSETUP(callbackActionOnDirection) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + DECLARE_FUNCTION(function7) + DECLARE_FUNCTION(function8) + DECLARE_FUNCTION(function9) + DECLARE_FUNCTION(function10) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION(function13) + DECLARE_FUNCTION(function14) + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION(function16) + DECLARE_FUNCTION(function17) + DECLARE_FUNCTION(function18) + DECLARE_FUNCTION(function19) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(augustAnnaDateOrder) + DECLARE_FUNCTION(function30) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(augustOrderSteak) + DECLARE_FUNCTION(augustServeDuck) + DECLARE_FUNCTION(function35) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_NULL_FUNCTION() + +private: + void handleServer(const SavePoint &savepoint, const char* name, EntityIndex entity, ActionIndex action, uint *parameter, const char* name2 = ""); + void serveTable(const SavePoint &savepoint, const char* seq1, EntityIndex entity, const char* seq2, const char* seq3, const char* seq4, uint *parameter, bool shouldUpdatePosition = true, bool pushSavepoint = false, Position position = 0); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SERVERS0_H diff --git a/engines/lastexpress/entities/servers1.cpp b/engines/lastexpress/entities/servers1.cpp new file mode 100644 index 0000000000..ea383dbacb --- /dev/null +++ b/engines/lastexpress/entities/servers1.cpp @@ -0,0 +1,787 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/servers1.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Servers1::Servers1(LastExpressEngine *engine) : Entity(engine, kEntityServers1) { + ADD_CALLBACK_FUNCTION(Servers1, updateFromTime); + ADD_CALLBACK_FUNCTION(Servers1, draw); + ADD_CALLBACK_FUNCTION(Servers1, updatePosition); + ADD_CALLBACK_FUNCTION(Servers1, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Servers1, callSavepoint); + ADD_CALLBACK_FUNCTION(Servers1, playSound); + ADD_CALLBACK_FUNCTION(Servers1, function7); + ADD_CALLBACK_FUNCTION(Servers1, chapter1); + ADD_CALLBACK_FUNCTION(Servers1, function9); + ADD_CALLBACK_FUNCTION(Servers1, function10); + ADD_CALLBACK_FUNCTION(Servers1, function11); + ADD_CALLBACK_FUNCTION(Servers1, function12); + ADD_CALLBACK_FUNCTION(Servers1, function13); + ADD_CALLBACK_FUNCTION(Servers1, chapter1Handler); + ADD_CALLBACK_FUNCTION(Servers1, function15); + ADD_CALLBACK_FUNCTION(Servers1, function16); + ADD_CALLBACK_FUNCTION(Servers1, chapter2); + ADD_CALLBACK_FUNCTION(Servers1, chapter2Handler); + ADD_CALLBACK_FUNCTION(Servers1, function19); + ADD_CALLBACK_FUNCTION(Servers1, function20); + ADD_CALLBACK_FUNCTION(Servers1, function21); + ADD_CALLBACK_FUNCTION(Servers1, chapter3); + ADD_CALLBACK_FUNCTION(Servers1, chapter3Handler); + ADD_CALLBACK_FUNCTION(Servers1, function24); + ADD_CALLBACK_FUNCTION(Servers1, chapter4); + ADD_CALLBACK_FUNCTION(Servers1, chapter4Handler); + ADD_CALLBACK_FUNCTION(Servers1, function27); + ADD_CALLBACK_FUNCTION(Servers1, function28); + ADD_CALLBACK_FUNCTION(Servers1, function29); + ADD_CALLBACK_FUNCTION(Servers1, chapter5); + ADD_CALLBACK_FUNCTION(Servers1, chapter5Handler); + ADD_NULL_FUNCTION() +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(1, Servers1, updateFromTime) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Servers1, draw) + Entity::draw(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(3, Servers1, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Servers1, callbackActionOnDirection) + if (savepoint.action == kActionExcuseMeCath) { + if (!params->param1) { + getSound()->excuseMe(kEntityServers1); + params->param1 = 1; + } + } + + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(5, Servers1, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(6, Servers1, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Servers1, function7) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("924"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getSavePoints()->push(kEntityServers1, kEntityBoutarel, kAction122358304); + setCallback(2); + setup_draw("008C"); + break; + + case 2: + getSavePoints()->push(kEntityServers1, kEntityBoutarel, kAction122288808); + setCallback(2); + setup_draw("926"); + break; + + case 3: + getEntities()->clearSequences(kEntityServers1); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(1, 2) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Servers1, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter1Handler(); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityServers1, kAction223002560, 0); + getSavePoints()->addData(kEntityServers1, kAction302996448, 2); + getSavePoints()->addData(kEntityServers1, kAction269485588, 3); + getSavePoints()->addData(kEntityServers1, kAction326144276, 4); + getSavePoints()->addData(kEntityServers1, kAction302203328, 5); + getSavePoints()->addData(kEntityServers1, kAction189688608, 6); + getSavePoints()->addData(kEntityServers1, kAction236237423, 7); + getSavePoints()->addData(kEntityServers1, kAction219377792, 8); + getSavePoints()->addData(kEntityServers1, kAction256200848, 9); + getSavePoints()->addData(kEntityServers1, kAction291721418, 10); + getSavePoints()->addData(kEntityServers1, kAction258136010, 11); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Servers1, function9) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("924"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityMilos, "BLANK"); + getEntities()->drawSequenceLeft(kEntityServers1, "009B"); + + setCallback(2); + setup_playSound("WAT1001"); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityMilos, "009A"); + + setCallback(3); + setup_draw("926"); + break; + + case 3: + getEntities()->clearSequences(kEntityServers1); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 1) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Servers1, function10) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("924"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityBoutarel, "BLANK"); + getEntities()->drawSequenceLeft(kEntityServers1, "008C"); + + setCallback(2); + setup_playSound("MRB1077"); + break; + + case 2: + getSavePoints()->push(kEntityServers1, kEntityBoutarel, kAction168717392); + + setCallback(3); + setup_draw("926"); + break; + + case 3: + getEntities()->clearSequences(kEntityServers1); + getData()->entityPosition = kPosition_5900; + ENTITY_PARAM(0, 2) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Servers1, function11) + serveTable(savepoint, "919", kEntityTables1, "005H", "005J", "921", &ENTITY_PARAM(0, 3), 63); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Servers1, function12) + serveTable(savepoint, "923", kEntityTables2, "009F", "009G", "926", &ENTITY_PARAM(0, 4)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Servers1, function13) + serveTable(savepoint, "923", kEntityTables2, "009F", "009G", "926", &ENTITY_PARAM(0, 5)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Servers1, chapter1Handler) +switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + if (ENTITY_PARAM(0, 1)) { + setCallback(1); + setup_function9(); + break; + } + + if (ENTITY_PARAM(1, 2)) { + setCallback(2); + setup_function10(); + break; + } + + if (ENTITY_PARAM(0, 3)) { + setCallback(3); + setup_function11(); + break; + } + + if (ENTITY_PARAM(0, 4)) { + setCallback(4); + setup_function12(); + break; + } + + if (ENTITY_PARAM(0, 5)) { + setCallback(5); + setup_function13(); + } + break; + + case kActionCallback: + if (getCallback() == 5) { + getSavePoints()->push(kEntityServers1, kEntityPascale, kAction352768896); + setup_function15(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Servers1, function15) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5900; + break; + + case kAction101632192: + setup_function16(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Servers1, function16) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + + getEntities()->clearSequences(kEntityServers1); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Servers1, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers1); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 6) = 0; + ENTITY_PARAM(0, 7) = 0; + ENTITY_PARAM(0, 8) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Servers1, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + if (ENTITY_PARAM(0, 6)) { + setCallback(1); + setup_function19(); + break; + } + +label_callback_1: + if (ENTITY_PARAM(0, 7)) { + setCallback(2); + setup_function20(); + break; + } + +label_callback_2: + if (ENTITY_PARAM(0, 8) || ENTITY_PARAM(0, 5)) { + setCallback(3); + setup_function21(); + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 4: + getEntities()->clearSequences(kEntityServers1); + getData()->entityPosition = kPosition_5900; + break; + } + break; + + case kAction101106391: + setCallback(4); + setup_draw("975"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Servers1, function19) + serveTable(savepoint, "969", kEntityTables1, "005H2", "018A", "971", &ENTITY_PARAM(0, 6), 63); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Servers1, function20) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("973"); + break; + + case kActionCallback: + if (getCallback() == 1) { + getSavePoints()->push(kEntityServers1, kEntityIvo, kAction123712592); + getEntities()->drawSequenceLeft(kEntityServers1, "BLANK"); + ENTITY_PARAM(0, 7) = 0; + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Servers1, function21) + serveTable(savepoint, "974", kEntityTables2, "009F2", "009G", "976", &ENTITY_PARAM(0, 8), 0, true, &ENTITY_PARAM(0, 5)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Servers1, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers1); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes1; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(1, 1) = 0; + ENTITY_PARAM(1, 2) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Servers1, chapter3Handler) + if (savepoint.action != kActionNone) + return; + + if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + return; + + if (ENTITY_PARAM(1, 1)) { + setCallback(1); + setup_function24(); + return; + } + + if (ENTITY_PARAM(1, 2)) { + setCallback(2); + setup_function7(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Servers1, function24) + serveSalon(savepoint, "927", "Ann3143A", kEntityAnna, "Ann31444", "112C", kAction122288808, "928", &ENTITY_PARAM(1, 1)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Servers1, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers1); + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + getEntities()->clearSequences(kEntityServers1); + + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Servers1, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2) { + UPDATE_PARAM_PROC(params->param2, getState()->time, 900) + ENTITY_PARAM(1, 5) = 1; + params->param1 = 0; + UPDATE_PARAM_PROC_END + } + + if (!getEntities()->isInKitchen(kEntityServers1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + break; + + if (ENTITY_PARAM(1, 5)) { + setCallback(2); + setup_function28(); + break; + } + + if (ENTITY_PARAM(1, 4)) { + setCallback(3); + setup_function29(); + break; + } + + if (ENTITY_PARAM(1, 2)) { + setCallback(4); + setup_function7(); + } + break; + + case kActionCallback: + if (getCallback() == 1) + params->param1 = 1; + break; + + case kAction201431954: + ENTITY_PARAM(1, 2) = 0; + ENTITY_PARAM(1, 3) = 0; + ENTITY_PARAM(1, 4) = 0; + ENTITY_PARAM(1, 5) = 0; + + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationOutsideCompartment; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Servers1, function27) + serveSalon(savepoint, "929", "", kEntityAugust, "Aug4003", "122D", kAction134486752, "930", &ENTITY_PARAM(1, 3)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Servers1, function28) + serveSalon(savepoint, "931", "", kEntityAugust, "Aug4004", "122E", kAction125826561, "930", &ENTITY_PARAM(1, 5)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Servers1, function29) + serveSalon(savepoint, "932", "", kEntityAnna, "Ann4151", "127D", kAction122288808, "930", &ENTITY_PARAM(1, 4)); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Servers1, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityServers1); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Servers1, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_nullfunction(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(32, Servers1) + + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Servers1::serveTable(const SavePoint &savepoint, const char* seq1, EntityIndex entity, const char* seq2, const char* seq3, const char* seq4, uint *parameter, Position position, bool shouldUpdatePosition, uint* parameter2) { + switch (savepoint.action) { + default: + break; + + case kActionDefault: + if (shouldUpdatePosition) { + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + } + + setCallback(1); + setup_draw(seq1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (position) + getEntities()->updatePositionEnter(kEntityServers1, kCarRestaurant, position); + + getSavePoints()->push(kEntityServers1, entity, kAction136455232); + + setCallback(2); + setup_callSavepoint(seq2, entity, kActionDrawTablesWithChairs, seq3); + break; + + case 2: + if (position) + getEntities()->updatePositionExit(kEntityServers1, kCarRestaurant, position); + + setCallback(3); + setup_draw(seq4); + break; + + case 3: + getData()->entityPosition = kPosition_5900; + getEntities()->clearSequences(kEntityServers1); + *parameter = 0; + + if (parameter2 != NULL) + *parameter2 = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +void Servers1::serveSalon(const SavePoint &savepoint, const char* seq1, const char* snd1, EntityIndex entity, const char* snd2, const char* seq2, ActionIndex action, const char* seq3, uint *parameter) { + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_draw("816DD"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceRight(kEntityServers1, seq1); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityServers1); + + if (!strcmp(snd1, "")) + getSound()->playSound(kEntityServers1, snd1); + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + getSavePoints()->push(kEntityServers1, entity, kAction122358304); + + getSound()->playSound(kEntityServers1, snd2); + + setCallback(3); + setup_updatePosition(seq2, kCarRestaurant, 57); + break; + + case 3: + getSavePoints()->push(kEntityServers1, entity, action); + + setCallback(4); + setup_draw(seq3); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityServers1, "816UD"); + + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityServers1); + + setCallback(5); + setup_callbackActionOnDirection(); + break; + + case 5: + getEntities()->clearSequences(kEntityServers1); + getData()->entityPosition = kPosition_5900; + *parameter = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/servers1.h b/engines/lastexpress/entities/servers1.h new file mode 100644 index 0000000000..f05d994d21 --- /dev/null +++ b/engines/lastexpress/entities/servers1.h @@ -0,0 +1,167 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_SERVERS1_H +#define LASTEXPRESS_SERVERS1_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Servers1 : public Entity { +public: + Servers1(LastExpressEngine *engine); + ~Servers1() {}; + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint + * - Time to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTime) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char *sequence, CarIndex car, Position position) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + DECLARE_FUNCTION(function7) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION(function9) + DECLARE_FUNCTION(function10) + DECLARE_FUNCTION(function11) + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION(function13) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION(function16) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function19) + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function24) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_NULL_FUNCTION() + +private: + void serveTable(const SavePoint &savepoint, const char* seq1, EntityIndex entity, const char* seq2, const char* seq3, const char* seq4, uint *parameter, Position position = 0, bool updatePosition = true, uint *parameter2 = NULL); + void serveSalon(const SavePoint &savepoint, const char* seq1, const char* snd1, EntityIndex entity, const char* snd2, const char* seq2, ActionIndex action, const char* seq3, uint *parameter); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SERVERS1_H diff --git a/engines/lastexpress/entities/sophie.cpp b/engines/lastexpress/entities/sophie.cpp new file mode 100644 index 0000000000..bab74ad1f2 --- /dev/null +++ b/engines/lastexpress/entities/sophie.cpp @@ -0,0 +1,279 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/sophie.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +#define CHAPTER_IMPLEMENTATION() \ + switch (savepoint.action) { \ + default: \ + break; \ + case kActionNone: \ + setup_chaptersHandler(); \ + break; \ + case kActionDefault: \ + getEntities()->clearSequences(kEntitySophie); \ + getData()->entityPosition = kPosition_4840; \ + getData()->location = kLocationInsideCompartment; \ + getData()->car = kCarRedSleeping; \ + getData()->clothes = kClothesDefault; \ + getData()->inventoryItem = kItemNone; \ + break; \ + } + +#define DEFAULT_ACTION_IMPLEMENTATION() \ + if (savepoint.action == kActionDefault) { \ + getData()->entityPosition = kPosition_4840; \ + getData()->location = kLocationInsideCompartment; \ + getData()->car = kCarRedSleeping; \ + getEntities()->clearSequences(kEntitySophie); \ + } + +Sophie::Sophie(LastExpressEngine *engine) : Entity(engine, kEntitySophie) { + ADD_CALLBACK_FUNCTION(Sophie, reset); + ADD_CALLBACK_FUNCTION(Sophie, updateEntity); + ADD_CALLBACK_FUNCTION(Sophie, chaptersHandler); + ADD_CALLBACK_FUNCTION(Sophie, chapter1); + ADD_CALLBACK_FUNCTION(Sophie, function5); + ADD_CALLBACK_FUNCTION(Sophie, chapter2); + ADD_CALLBACK_FUNCTION(Sophie, chapter3); + ADD_CALLBACK_FUNCTION(Sophie, chapter4); + ADD_CALLBACK_FUNCTION(Sophie, function9); + ADD_CALLBACK_FUNCTION(Sophie, chapter5); + ADD_CALLBACK_FUNCTION(Sophie, chapter5Handler); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Sophie, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(2, Sophie, updateEntity, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: { + params->param3 = 0; + + // Sophie + byte direction = getData()->direction; + EntityPosition position = getData()->entityPosition; + CarIndex car = getData()->car; + + // Rebecca + EntityPosition rebecca_position = getEntityData(kEntityRebecca)->entityPosition; + CarIndex rebeccaCar = getEntityData(kEntityRebecca)->car; + + if (getEntities()->isDistanceBetweenEntities(kEntitySophie, kEntityRebecca, 500) + || (direction == kDirectionUp && car >= rebeccaCar && position > rebecca_position) + || (direction == kDirectionDown && car <= rebeccaCar && position < rebecca_position)) { + getData()->field_49B = 0; + params->param3 = 1; + } + + if (!params->param3) + getEntities()->updateEntity(kEntitySophie, (CarIndex)params->param1, (EntityPosition)params->param2); + + break; + } + + case kActionExcuseMeCath: + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntitySophie); + break; + + case kActionDefault: + getEntities()->updateEntity(kEntitySophie, (CarIndex)params->param1, (EntityPosition)params->param2); + break; + + case kAction123668192: + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Sophie, chaptersHandler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->entityPosition = getEntityData(kEntityRebecca)->entityPosition; + getData()->car = getEntityData(kEntityRebecca)->car; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntitySophie); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntitySophie, "BLANK"); + break; + + case 3: + getEntities()->clearSequences(kEntitySophie); + break; + + case 4: + getEntities()->drawSequenceLeft(kEntitySophie, "BLANK"); + break; + } + break; + + case kAction125242096: + getData()->entityPosition = (EntityPosition)(getEntityData(kEntityRebecca)->entityPosition - 100); + getData()->location = getEntityData(kEntityRebecca)->location; + getData()->car = getEntityData(kEntityRebecca)->car; + + setCallback(1); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case kAction136654208: + getData()->entityPosition = (EntityPosition)(getEntityData(kEntityRebecca)->entityPosition + 100); + getData()->location = getEntityData(kEntityRebecca)->location; + getData()->car = getEntityData(kEntityRebecca)->car; + + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + + case kAction259921280: + getData()->entityPosition = (EntityPosition)(getEntityData(kEntityRebecca)->entityPosition + 100); + getData()->location = getEntityData(kEntityRebecca)->location; + getData()->car = getEntityData(kEntityRebecca)->car; + + setCallback(3); + setup_updateEntity(kCarKronos, kPosition_9460); + break; + + case kAction292775040: + getData()->entityPosition = kPosition_9270; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarKronos; + + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_4840); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Sophie, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chaptersHandler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Sophie, function5) + DEFAULT_ACTION_IMPLEMENTATION() +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Sophie, chapter2) + CHAPTER_IMPLEMENTATION() +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Sophie, chapter3) + CHAPTER_IMPLEMENTATION() +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Sophie, chapter4) + CHAPTER_IMPLEMENTATION() +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Sophie, function9) + DEFAULT_ACTION_IMPLEMENTATION() +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Sophie, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntitySophie); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Sophie, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_nullfunction(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(12, Sophie) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/sophie.h b/engines/lastexpress/entities/sophie.h new file mode 100644 index 0000000000..51d3d084b6 --- /dev/null +++ b/engines/lastexpress/entities/sophie.h @@ -0,0 +1,98 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_SOPHIE_H +#define LASTEXPRESS_SOPHIE_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Sophie : public Entity { +public: + Sophie(LastExpressEngine *engine); + ~Sophie() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Handle chapters events + */ + DECLARE_FUNCTION(chaptersHandler) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION(function5) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + DECLARE_FUNCTION(function9) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SOPHIE_H diff --git a/engines/lastexpress/entities/tables.cpp b/engines/lastexpress/entities/tables.cpp new file mode 100644 index 0000000000..eca60a536b --- /dev/null +++ b/engines/lastexpress/entities/tables.cpp @@ -0,0 +1,221 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/tables.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Tables::Tables(LastExpressEngine *engine, EntityIndex id) : Entity(engine, id) { + _id = id; + + ADD_CALLBACK_FUNCTION(Tables, chapter1); + ADD_CALLBACK_FUNCTION(Tables, chapter2); + ADD_CALLBACK_FUNCTION(Tables, chapter3); + ADD_CALLBACK_FUNCTION(Tables, chapter4); + ADD_CALLBACK_FUNCTION(Tables, chapter5); + ADD_CALLBACK_FUNCTION(Tables, draw); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Tables, chapter1) + if (savepoint.action == kActionDefault) { + if (_id == kEntityTables2) + getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + + setup_draw(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(2, Tables, chapter2) + if (savepoint.action == kActionDefault) { + if (_id == kEntityTables2) + getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + + setup_draw(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Tables, chapter3) + if (savepoint.action == kActionDefault) { + if (_id == kEntityTables2) + getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + + setup_draw(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Tables, chapter4) + if (savepoint.action == kActionDefault) { + if (_id == kEntityTables2) + getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + + setup_draw(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Tables, chapter5) + if (savepoint.action == kActionDefault) { + if (_id == kEntityTables2 && getSound()->isBuffered(kEntityTables2)) + getSound()->processEntry(kEntityTables2); + + setup_draw(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Tables, draw) + switch (savepoint.action) { + default: + break; + + case kActionNone: + // Only applicable to Tables2 entity + if (_id != kEntityTables2) + break; + + switch (getProgress().chapter) { + default: + break; + + case kChapter1: + if (getState()->time > kTime1165500 && !params->param1) { + params->param1 = 1; + getSound()->processEntry(kEntityTables2); + } + break; + + case kChapter3: + if (getState()->time > kTime2052000 && !params->param2) { + params->param2 = 1; + getSound()->processEntry(kEntityTables2); + } + break; + + case kChapter4: + if (getState()->time > kTime2488500 && !params->param3) { + params->param3 = 1; + getSound()->processEntry(kEntityTables2); + } + break; + + } + break; + + case kActionDefault: + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + switch(_id) { + default: + break; + + case kEntityTables0: + getData()->entityPosition = kPosition_3970; + getEntities()->drawSequenceLeft(_id, "001P"); + break; + + case kEntityTables1: + getData()->entityPosition = kPosition_3970; + getEntities()->drawSequenceLeft(_id, "005J"); + break; + + case kEntityTables2: + getData()->entityPosition = kPosition_4690; + getEntities()->drawSequenceLeft(_id, "009G"); + break; + + case kEntityTables3: + getData()->entityPosition = kPosition_4690; + getEntities()->drawSequenceLeft(_id, "010M"); + break; + + case kEntityTables4: + getData()->entityPosition = kPosition_5420; + getEntities()->drawSequenceLeft(_id, "014F"); + break; + + case kEntityTables5: + getData()->entityPosition = kPosition_5420; + getEntities()->drawSequenceLeft(_id, "024D"); + break; + } + + break; + + case kActionDrawTablesWithChairs: + if (!strcmp(savepoint.param.charValue, "")) { + getEntities()->drawSequenceLeft(_id, savepoint.param.charValue); + } else { + switch(_id) { + default: + break; + + case kEntityTables0: + getEntities()->drawSequenceLeft(_id, "001P"); + break; + + case kEntityTables1: + getEntities()->drawSequenceLeft(_id, "005J"); + break; + + case kEntityTables2: + getEntities()->drawSequenceLeft(_id, "009G"); + break; + + case kEntityTables3: + getEntities()->drawSequenceLeft(_id, "010M"); + break; + + case kEntityTables4: + getEntities()->drawSequenceLeft(_id, "014F"); + break; + + case kEntityTables5: + getEntities()->drawSequenceLeft(_id, "024D"); + break; + } + } + break; + + case kAction136455232: + getEntities()->drawSequenceLeft(_id, "BLANK"); + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/tables.h b/engines/lastexpress/entities/tables.h new file mode 100644 index 0000000000..e7f51da66a --- /dev/null +++ b/engines/lastexpress/entities/tables.h @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_TABLES_H +#define LASTEXPRESS_TABLES_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Tables : public Entity { +public: + Tables(LastExpressEngine *engine, EntityIndex id); + ~Tables() {}; + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Draws tables + */ + DECLARE_FUNCTION(draw) + +private: + EntityIndex _id; ///< Table entity id +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_TABLES_H diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp new file mode 100644 index 0000000000..14567f8afa --- /dev/null +++ b/engines/lastexpress/entities/tatiana.cpp @@ -0,0 +1,1711 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/tatiana.h" + +#include "lastexpress/entities/alexei.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Tatiana::Tatiana(LastExpressEngine *engine) : Entity(engine, kEntityTatiana) { + ADD_CALLBACK_FUNCTION(Tatiana, reset); + ADD_CALLBACK_FUNCTION(Tatiana, playSound); + ADD_CALLBACK_FUNCTION(Tatiana, draw); + ADD_CALLBACK_FUNCTION(Tatiana, updatePosition); + ADD_CALLBACK_FUNCTION(Tatiana, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Tatiana, enterExitCompartment2); + ADD_CALLBACK_FUNCTION(Tatiana, callSavepoint); + ADD_CALLBACK_FUNCTION(Tatiana, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Tatiana, updateFromTicks); + ADD_CALLBACK_FUNCTION(Tatiana, updateFromTime); + ADD_CALLBACK_FUNCTION(Tatiana, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Tatiana, savegame); + ADD_CALLBACK_FUNCTION(Tatiana, updateEntity); + ADD_CALLBACK_FUNCTION(Tatiana, function14); + ADD_CALLBACK_FUNCTION(Tatiana, function15); + ADD_CALLBACK_FUNCTION(Tatiana, function16); + ADD_CALLBACK_FUNCTION(Tatiana, chapter1); + ADD_CALLBACK_FUNCTION(Tatiana, function18); + ADD_CALLBACK_FUNCTION(Tatiana, chapter1Handler); + ADD_CALLBACK_FUNCTION(Tatiana, function20); + ADD_CALLBACK_FUNCTION(Tatiana, function21); + ADD_CALLBACK_FUNCTION(Tatiana, function22); + ADD_CALLBACK_FUNCTION(Tatiana, function23); + ADD_CALLBACK_FUNCTION(Tatiana, function24); + ADD_CALLBACK_FUNCTION(Tatiana, chapter2); + ADD_CALLBACK_FUNCTION(Tatiana, chapter2Handler); + ADD_CALLBACK_FUNCTION(Tatiana, function27); + ADD_CALLBACK_FUNCTION(Tatiana, function28); + ADD_CALLBACK_FUNCTION(Tatiana, function29); + ADD_CALLBACK_FUNCTION(Tatiana, function30); + ADD_CALLBACK_FUNCTION(Tatiana, chapter3); + ADD_CALLBACK_FUNCTION(Tatiana, chapter3Handler); + ADD_CALLBACK_FUNCTION(Tatiana, function33); + ADD_CALLBACK_FUNCTION(Tatiana, function34); + ADD_CALLBACK_FUNCTION(Tatiana, function35); + ADD_CALLBACK_FUNCTION(Tatiana, function36); + ADD_CALLBACK_FUNCTION(Tatiana, function37); + ADD_CALLBACK_FUNCTION(Tatiana, function38); + ADD_CALLBACK_FUNCTION(Tatiana, function39); + ADD_CALLBACK_FUNCTION(Tatiana, function40); + ADD_CALLBACK_FUNCTION(Tatiana, function41); + ADD_CALLBACK_FUNCTION(Tatiana, function42); + ADD_CALLBACK_FUNCTION(Tatiana, chapter4); + ADD_CALLBACK_FUNCTION(Tatiana, chapter4Handler); + ADD_CALLBACK_FUNCTION(Tatiana, function45); + ADD_CALLBACK_FUNCTION(Tatiana, function46); + ADD_CALLBACK_FUNCTION(Tatiana, function47); + ADD_CALLBACK_FUNCTION(Tatiana, function48); + ADD_CALLBACK_FUNCTION(Tatiana, function49); + ADD_CALLBACK_FUNCTION(Tatiana, function50); + ADD_CALLBACK_FUNCTION(Tatiana, function51); + ADD_CALLBACK_FUNCTION(Tatiana, chapter5); + ADD_CALLBACK_FUNCTION(Tatiana, chapter5Handler); + ADD_CALLBACK_FUNCTION(Tatiana, function54); + ADD_CALLBACK_FUNCTION(Tatiana, function55); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Tatiana, reset) + Entity::reset(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Tatiana, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Tatiana, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SII(4, Tatiana, updatePosition, CarIndex, Position) + Entity::updatePosition(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(5, Tatiana, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(6, Tatiana, enterExitCompartment2, ObjectIndex) + Entity::enterExitCompartment(savepoint, kPosition_7500, kPosition_7850, kCarRedSleeping, kObjectCompartmentB); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SIIS(7, Tatiana, callSavepoint, EntityIndex, ActionIndex) + Entity::callSavepoint(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Tatiana, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(9, Tatiana, updateFromTicks) + Entity::updateFromTicks(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(10, Tatiana, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Tatiana, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(12, Tatiana, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(13, Tatiana, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + if (getEvent(kEventTatianaAskMatchSpeakRussian) || getEvent(kEventTatianaAskMatch) || getEvent(kEventVassiliSeizure)) { + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1010" : "CAT1010A"); + } else { + getSound()->excuseMeCath(); + } + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Tatiana, function14) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityTatiana, kEntityCoudert, kAction326348944); + getEntities()->drawSequenceLeft(kEntityTatiana, getProgress().chapter == kChapter1 ? "603Fb" : "673Fb"); + getEntities()->enterCompartment(kEntityTatiana, kObjectCompartmentB, true); + break; + + case kActionCallback: + if (getCallback() == 1 || getCallback() == 2) { + getEntities()->exitCompartment(kEntityTatiana, kObjectCompartmentB, true); + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityTatiana); + + CALLBACK_ACTION(); + } + break; + + case kAction69239528: + setCallback(getProgress().chapter == kChapter1 ? 1 : 2); + setup_enterExitCompartment2(getProgress().chapter == kChapter1 ? "603Db" : "673Db", kObjectCompartmentB); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Tatiana, function15) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(getProgress().chapter == kChapter1 ? 1 : 2); + setup_enterExitCompartment2(getProgress().chapter == kChapter1 ? "603Bb" : "673Bb", kObjectCompartmentB); + break; + + case kActionCallback: + if (getCallback() == 1 || getCallback() == 2) { + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityTatiana, kEntityCoudert, kAction292048641); + + getEntities()->drawSequenceLeft(kEntityTatiana, getProgress().chapter == kChapter1 ? "603Fb" : "673Fb"); + getEntities()->enterCompartment(kEntityTatiana, kObjectCompartmentB, true); + } + break; + + case kAction69239528: + getEntities()->exitCompartment(kEntityTatiana, kObjectCompartmentB, true); + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(16, Tatiana, function16, uint32) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 < getState()->time && !params->param4) { + params->param4 = 1; + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + CALLBACK_ACTION(); + break; + } + + if (params->param2) { + UPDATE_PARAM(params->param5, getState()->timeTicks, 75); + + params->param2 = 0; + params->param3 = 1; + + getObjects()->update(kObjectCompartmentB, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject49, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + params->param5 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (params->param2) { + getObjects()->update(kObjectCompartmentB, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject49, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorNormal); + + if (savepoint.param.intValue == 49) { + setCallback(4); + setup_playSound(getSound()->justAMinuteCath()); + break; + } + + if (getInventory()->hasItem(kItemPassengerList)) { + setCallback(5); + setup_playSound(rnd(2) ? "CAT1512" : getSound()->wrongDoorCath()); + break; + } + + setCallback(6); + setup_playSound(getSound()->wrongDoorCath()); + } else { + getObjects()->update(kObjectCompartmentB, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject49, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentB, kEntityTatiana, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityTatiana, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (params->param2 || params->param3) { + getObjects()->update(kObjectCompartmentB, kEntityTatiana, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityTatiana, kObjectLocation1, kCursorHandKnock, kCursorHand); + + params->param2 = 0; + params->param3 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound(rnd(2) ? "TAT1133A" : "TAT1133B"); + break; + + case 3: + getObjects()->update(kObjectCompartmentB, kEntityTatiana, kObjectLocation1, kCursorTalk, kCursorNormal); + getObjects()->update(kObject49, kEntityTatiana, kObjectLocation1, kCursorTalk, kCursorNormal); + params->param2 = 1; + break; + + case 4: + case 5: + case 6: + params->param2 = 0; + params->param3 = 1; + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Tatiana, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityTatiana, kAction191198209, 0); + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject41, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_5419; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Tatiana, function18) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + + if (getState()->time > kTime1143000 && !params->param2) { + params->param2 = 1; + getEntities()->drawSequenceRight(kEntityTatiana, "806DS"); + params->param1 = 1; + } + + if (!params->param1) { + UPDATE_PARAM_PROC(params->param3, getState()->time, 4500) + getEntities()->drawSequenceRight(kEntityTatiana, "806DS"); + params->param1 = 1; + UPDATE_PARAM_PROC_END + } + } + + if (getData()->entityPosition <= kPosition_2330) { + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction157159392); + getEntities()->clearSequences(kEntityTatiana); + + CALLBACK_ACTION(); + } + break; + + case kActionExitCompartment: + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction188784532); + + CALLBACK_ACTION(); + break; + + case kActionDefault: + if (getEntities()->isInSalon(kEntityPlayer)) { + getEntities()->drawSequenceRight(kEntityTatiana, "806DS"); + params->param1 = 1; + } else { + getEntities()->clearSequences(kEntityTatiana); + } + break; + + case kActionDrawScene: + if (!params->param1 && getEntities()->isInSalon(kEntityPlayer)) { + getEntities()->drawSequenceRight(kEntityTatiana, "806DS"); + getEntities()->updateFrame(kEntityTatiana); + params->param1 = 1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Tatiana, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getSound()->isBuffered(kEntityTatiana) || !params->param4 || params->param3 == 2 || getSound()->isBuffered("TAT1066")) + goto label_tatiana_chapter1_2; + + UPDATE_PARAM_PROC(params->param5, getState()->timeTicks, 450) + getSound()->playSound(kEntityTatiana, params->param3 ? "TAT1069B" : "TAT1069A"); + getProgress().field_64 = 1; + params->param3++; + params->param5 = 0; + UPDATE_PARAM_PROC_END + + if (getEntities()->isPlayerPosition(kCarRestaurant, 71)) { + UPDATE_PARAM_PROC(params->param6, getState()->timeTicks, 75) + getSound()->playSound(kEntityTatiana, params->param3 ? "TAT1069B" : "TAT1069A"); + getProgress().field_64 = 1; + params->param3++; + params->param6 = 0; + UPDATE_PARAM_PROC_END + } + +label_tatiana_chapter1_2: + TIME_CHECK_SAVEPOINT(kTime1084500, params->param7, kEntityTatiana, kEntityPascale, kAction257489762); + + if (params->param1) { + UPDATE_PARAM(params->param8, getState()->timeTicks, 90); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + } else { + params->param8 = 0; + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityTatiana, kEntityTables4, kAction136455232); + getEntities()->drawSequenceLeft(kEntityTatiana, "014A"); + break; + + case kActionDrawScene: + params->param1 = getEntities()->isPlayerPosition(kCarRestaurant, 67) ? 1 : 0; + params->param4 = getEntities()->isPlayerPosition(kCarRestaurant, 69) + || getEntities()->isPlayerPosition(kCarRestaurant, 70) + || getEntities()->isPlayerPosition(kCarRestaurant, 71); + break; + + case kAction122288808: + getEntities()->drawSequenceLeft(kEntityTatiana, "014A"); + break; + + case kAction122358304: + getEntities()->drawSequenceLeft(kEntityTatiana, "BLANK"); + break; + + case kAction124973510: + setup_function20(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Tatiana, function20) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getSavePoints()->push(kEntityTatiana, kEntityAugust, kAction223183000); + getEntities()->updatePositionEnter(kEntityTatiana, kCarRestaurant, 67); + getSound()->playSound(kEntityTatiana, "TAT1070"); + + setCallback(2); + setup_callSavepoint("014C", kEntityTables4, kActionDrawTablesWithChairs, "014D"); + break; + + case 2: + getEntities()->updatePositionExit(kEntityTatiana, kCarRestaurant, 67); + getSavePoints()->push(kEntityTatiana, kEntityServers0, kAction188893625); + + setCallback(3); + setup_function18(); + break; + + case 3: + getSavePoints()->push(kEntityTatiana, kEntityAugust, kAction268620864); + setup_function21(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Tatiana, function21) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->clothes = kClothes1; + + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_8513); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->clothes = kClothesDefault; + + getSound()->playSound(kEntityTatiana, "TAT1071"); + getEntities()->drawSequenceRight(kEntityTatiana, "604Aa"); + getEntities()->enterCompartment(kEntityTatiana, kObjectCompartmentA); + + getData()->location = kLocationInsideCompartment; + + if (getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_7850)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartmentA, true); + } + + setCallback(2); + setup_callbackActionOnDirection(); + break; + + case 2: + getEntities()->exitCompartment(kEntityTatiana, kObjectCompartmentA); + + getData()->location = kLocationInsideCompartment; + + getEntities()->clearSequences(kEntityTatiana); + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction135854208); + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + // Fallback to next case + + case 3: + if (getSound()->isBuffered(kEntityTatiana)) { + setCallback(3); + setup_updateFromTime(75); + } else { + setCallback(4); + setup_playSound("TAT1071A"); + } + break; + + case 4: + getData()->entityPosition = kPosition_7500; + + getSavePoints()->push(kEntityTatiana, kEntityVassili, kAction168459827); + + setCallback(5); + setup_function16(kTime1156500); + break; + + case 5: + case 6: + if (getProgress().field_14 == 29) { + setCallback(6); + setup_function16(getState()->time + 900); + } else { + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + setup_function22(); + } + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Tatiana, function22) + error("Tatiana: callback function 22 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Tatiana, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function14(); + break; + + case 2: + setup_function24(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Tatiana, function24) + if (savepoint.action == kActionDefault) { + + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObject25, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObjectTrainTimeTable, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getEntities()->updatePositionExit(kEntityTatiana, kCarGreenSleeping, 70); + getEntities()->updatePositionExit(kEntityTatiana, kCarGreenSleeping, 71); + getEntities()->clearSequences(kEntityTatiana); + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject41, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Tatiana, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTatiana); + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject41, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + + getData()->entityPosition = kPosition_5420; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes2; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Tatiana, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime1800000 && params->param1 && getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->inventoryItem = kItemNone; + setup_function28(); + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + setup_function28(); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityTatiana, "024A"); + getSavePoints()->push(kEntityTatiana, kEntityTables5, kAction136455232); + getData()->inventoryItem = kItemInvalid; + break; + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRestaurant, 64) || getEntities()->isPlayerPosition(kCarRestaurant, 65)) { + getData()->inventoryItem = kItemNone; + setup_function27(); + } + break; + + case kAction290869168: + params->param1 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Tatiana, function27) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(getEvent(kEventTatianaGivePoem) ? 1 : 2); + setup_savegame(kSavegameTypeEvent, getEvent(kEventTatianaGivePoem) ? kEventTatianaBreakfastAlexei : kEventTatianaBreakfast); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_function30); + getAction()->playAnimation(kEventTatianaBreakfastAlexei); + getInventory()->addItem(kItemParchemin); + getInventory()->setLocationAndProcess(kItem11, kObjectLocation1); + setup_function28(); + break; + + case 2: + RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_function30); + getAction()->playAnimation(kEventTatianaBreakfast); + if (getInventory()->hasItem(kItemParchemin)) { + getAction()->playAnimation(kEventTatianaBreakfastGivePoem); + getInventory()->removeItem(kItemParchemin); + } else { + getAction()->playAnimation(kEventTatianaAlexei); + } + setup_function28(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Tatiana, function28) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->inventoryItem = kItemNone; + getData()->location = kLocationOutsideCompartment; + + getSavePoints()->push(kEntityTatiana, kEntityTables5, kActionDrawTablesWithChairs, "024D"); + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction236053296, (getEvent(kEventTatianaBreakfastAlexei) || getEvent(kEventTatianaBreakfast)) ? 69 : 0); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function29(); + break; + + case kAction123857088: + getEntities()->drawSequenceLeft(kEntityTatiana, "018G"); + + setCallback(1); + setup_updateFromTime(1800); + break; + + case kAction156444784: + getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityTatiana, "BLANK"); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Tatiana, function29) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getEntities()->updatePositionEnter(kEntityTatiana, kCarRestaurant, 63); + + setCallback(2); + setup_callSavepoint("018H", kEntityTables1, kActionDrawTablesWithChairs, "018A"); + break; + + case 2: + getEntities()->updatePositionExit(kEntityTatiana, kCarRestaurant, 63); + getSavePoints()->push(kEntityTatiana, kEntityServers1, kAction302203328); + getEntities()->drawSequenceRight(kEntityTatiana, "805DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityTatiana); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + setup_function30(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Tatiana, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_function14(); + break; + + case 2: + setCallback(3); + setup_function16(kTimeEnd); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Tatiana, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTatiana); + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_1750; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothes2; + getData()->inventoryItem = kItemNone; + + // Update inventory + getInventory()->get(kItemFirebird)->location = kObjectLocation2; + + if (getEvent(kEventTatianaBreakfastGivePoem) || (getEvent(kEventTatianaGivePoem) && !getEvent(kEventTatianaBreakfastAlexei))) + getInventory()->get(kItemParchemin)->location = kObjectLocation2; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Tatiana, chapter3Handler) + EntityData::EntityParametersI5S *parameters = (EntityData::EntityParametersI5S*)_data->getCurrentParameters(); + EntityData::EntityParametersSIII *parameters1 = (EntityData::EntityParametersSIII*)_data->getCurrentParameters(1); + + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!parameters->param2 && !parameters->param5) { + parameters->param1 -= getState()->timeDelta; + + if (getState()->timeDelta > parameters->param1) { + + getEntities()->drawSequenceLeft(kEntityTatiana, (char *)¶meters1->seq); + getSound()->playSound(kEntityTatiana, (char *)¶meters->seq); + + if (parameters->param3 == 4 && getEntities()->isInSalon(kEntityPlayer)) + getProgress().field_90 = 1; + + parameters->param2 = 1; + } + } + + if (parameters->param4 && parameters->param5) { + UPDATE_PARAM_CHECK(parameters->param4, getState()->time, 6300) + if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updatePosition("110E", kCarRestaurant, 52); + } + } + } + break; + + case kActionEndSound: + parameters->param2 = 0; + ++parameters->param3; + + switch (parameters->param3) { + default: + parameters->param5 = 1; + break; + + case 1: + parameters->param1 = 900; + getEntities()->drawSequenceLeft(kEntityTatiana, "110A"); + strcpy((char *)¶meters->seq, "Tat3160B"); + strcpy((char *)¶meters1->seq, "110A"); + break; + + case 2: + parameters->param1 = 9000; + strcpy((char *)¶meters->seq, "Tat3160C"); + strcpy((char *)¶meters1->seq, "110C"); + break; + + case 3: + parameters->param1 = 13500; + getEntities()->drawSequenceLeft(kEntityTatiana, "110B"); + strcpy((char *)¶meters->seq, "Tat3160D"); + strcpy((char *)¶meters1->seq, "110D"); + break; + + case 4: + parameters->param1 = 9000; + getEntities()->drawSequenceLeft(kEntityTatiana, "110B"); + strcpy((char *)¶meters->seq, "Tat3160E"); + strcpy((char *)¶meters1->seq, "110D"); + break; + + case 5: + parameters->param1 = 4500; + getEntities()->drawSequenceLeft(kEntityTatiana, "110B"); + strcpy((char *)¶meters->seq, "Tat3160G"); + strcpy((char *)¶meters1->seq, "110D"); + break; + + case 6: + parameters->param1 = 4500; + getEntities()->drawSequenceLeft(kEntityTatiana, "110B"); + strcpy((char *)¶meters->seq, "Tat3160B"); + break; + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction122358304); + getSavePoints()->push(kEntityTatiana, kEntityKronos, kAction157159392); + getEntities()->drawSequenceLeft(kEntityTatiana, "110C"); + getSound()->playSound(kEntityTatiana, "Tat3160A"); + + parameters->param2 = 1; + break; + + case kActionCallback: + if (getCallback() == 1) { + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction122288808); + setup_function33(); + } + break; + + case kAction101169422: + parameters->param4 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Tatiana, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTatiana); + setCallback(1); + setup_updateFromTime(75); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_7500); + break; + + case 2: + setCallback(3); + setup_function14(); + break; + + case 3: + setup_function34(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Tatiana, function34) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(kTime2097000); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getInventory()->get(kItemFirebird)->location = kObjectLocation1; + if (getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_7850)) + getScenes()->loadSceneFromObject(kObjectCompartmentB); + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + setup_function15(); + break; + + case 2: + setCallback(3); + setup_updateEntity(kCarKronos, kPosition_9270); + break; + + case 3: + setup_function35(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Tatiana, function35) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1 + && getInventory()->hasItem(kItemFirebird) + && getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_7850) + && (getState()->time < kTime2133000 || getProgress().field_40)) { + setCallback(1); + setup_function41(); + break; + } + +label_callback_1: + if (getState()->time > kTime2133000) { + if (getData()->car >= kCarRedSleeping || (getData()->car == kCarGreenSleeping && getData()->entityPosition > kPosition_5790)) + setup_function36(); + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getEntities()->clearSequences(kEntityTatiana); + + getData()->car = kCarKronos; + getData()->entityPosition = kPosition_6000; + getData()->location = kLocationInsideCompartment; + break; + + case kActionCallback: + if (getCallback() == 1) { + params->param1 = 1; + goto label_callback_1; + } + break; + + case kAction191668032: + setup_function36(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Tatiana, function36) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_850; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (!getEntities()->checkFields19(kEntityPlayer, kCarGreenSleeping, kPosition_7850) || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { + setCallback(2); + setup_function14(); + break; + } + + if (getInventory()->hasItem(kItemFirebird)) { + getAction()->playAnimation(kEventTatianaCompartmentStealEgg); + getInventory()->removeItem(kItemFirebird); + getInventory()->get(kItemFirebird)->location = kObjectLocation2; + } else { + getAction()->playAnimation(kEventTatianaCompartment); + } + + getScenes()->loadSceneFromObject(kObjectCompartmentB); + break; + + case 2: + setup_function37(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Tatiana, function37) + error("Tatiana: callback function 37 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Tatiana, function38) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->time, 450); + + getEntities()->exitCompartment(kEntityTatiana, kObjectCompartmentF, true); + + setCallback(4); + setup_function42(kCarRedSleeping, kPosition_7500); + break; + + case kActionDefault: + getData()->clothes = kClothes3; + + setCallback(1); + setup_enterExitCompartment("673Jb", kObjectCompartmentB); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(2); + setup_function42(kCarRedSleeping, kPosition_4070); + break; + + case 2: + getEntities()->drawSequenceLeft(kEntityTatiana, "673Gf"); + getEntities()->enterCompartment(kEntityTatiana, kObjectCompartmentF, true); + + setCallback(3); + setup_playSound("Tat3164"); + break; + + case 3: + getSavePoints()->push(kEntityTatiana, kEntityAnna, kAction236241630); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment2("673Db", kObjectCompartmentB); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityTatiana); + + setup_function39(); + break; + + case 6: + getEntities()->exitCompartment(kEntityTatiana, kObjectCompartmentF, true); + getEntities()->clearSequences(kEntityTatiana); + getData()->location = kLocationInsideCompartment; + + setCallback(7); + setup_playSound("ANN3011"); + break; + + case 7: + setCallback(8); + setup_updateFromTime(900); + break; + + case 8: + setCallback(9); + setup_enterExitCompartment("673Jf", kObjectCompartmentF); + break; + + case 9: + getData()->location = kLocationOutsideCompartment; + + setCallback(10); + setup_function42(kCarRedSleeping, kPosition_7500); + break; + + case 10: + getSavePoints()->push(kEntityTatiana, kEntityAnna, kAction236517970); + + setCallback(11); + setup_enterExitCompartment2("673Db", kObjectCompartmentB); + break; + + case 11: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityTatiana); + + setup_function39(); + break; + } + break; + + case kAction100906246: + setCallback(6); + setup_enterExitCompartment("673Df", kObjectCompartmentF); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Tatiana, function39) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1 && getEntities()->isDistanceBetweenEntities(kEntityTatiana, kEntityPlayer, 1000)) { + params->param1 = 1; + getSound()->playSound(kEntityTatiana, "Tat3164"); // Tatiana weeping + } + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Tatiana, function40) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos) + || getData()->car != getEntityData(kEntityPlayer)->car + || getEntities()->updateEntity(kEntityTatiana, kCarKronos, kPosition_9270)) + CALLBACK_ACTION(); + break; + + case kActionExcuseMe: + if (getEvent(kEventTatianaAskMatchSpeakRussian) || getEvent(kEventTatianaAskMatch) || getEvent(kEventVassiliSeizure)) + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1001A" : "CAT1010"); + else + getSound()->excuseMeCath(); + break; + + case kActionDefault: + if (getEntities()->updateEntity(kEntityTatiana, kCarKronos, kPosition_9270)) + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Tatiana, function41) + error("Tatiana: callback function 41 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(42, Tatiana, function42, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath || savepoint.action == kActionExcuseMe) { + getSound()->playSound(kEntityPlayer, "Tat3124", getSound()->getSoundFlag(kEntityTatiana)); + return; + } + + Entity::updateEntity(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(43, Tatiana, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTatiana); + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothes2; + getData()->inventoryItem = kItemNone; + + ENTITY_PARAM(0, 1) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(44, Tatiana, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function16(kTime2362500); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function45(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(45, Tatiana, function45) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("673Bb", kObjectCompartmentB); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + + case 2: + if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) { + getSound()->excuseMe(kEntityTatiana); + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 62)) + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 72); + } + + getSavePoints()->push(kEntityTatiana, kEntityAlexei, kAction123712592); + setup_function46(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(46, Tatiana, function46) + error("Tatiana: callback function 46 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(47, Tatiana, function47) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRedSleeping, kPosition_7500); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment2("673Db", kObjectCompartmentB); + break; + + case 2: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityTatiana); + + setCallback(3); + setup_function16(kTime2407500); + break; + + case 3: + case 4: + if (ENTITY_PARAM(0, 1) && getObjects()->get(kObjectCompartment1).location2 == kObjectLocation1) { + setup_function48(); + } else { + setCallback(4); + setup_function16(900); + } + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(48, Tatiana, function48) + error("Tatiana: callback function 48 not implemented!"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(49, Tatiana, function49) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_7500; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kAction169360385: + setup_function50(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(50, Tatiana, function50) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2520000 && !params->param1) { + params->param1 = 1; + setup_function51(); + } + break; + + case kActionEndSound: + getSound()->playSound(kEntityTatiana, "Tat4166"); + break; + + case kActionKnock: + if (!getSound()->isBuffered("LIB012", true)) + getSound()->playSound(kEntityPlayer, "LIB012"); + break; + + case kActionOpenDoor: + getSound()->playSound(kEntityPlayer, "LIB014"); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventVassiliDeadAlexei); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject48, kEntityTatiana, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentA, kEntityTatiana, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + if (!getSound()->isBuffered(kEntityTatiana)) + getSound()->playSound(kEntityTatiana, "Tat4166"); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (getSound()->isBuffered("MUS013")) + getSound()->processEntry("MUS013"); + + getAction()->playAnimation(kEventVassiliDeadAlexei); + getSavePoints()->push(kEntityTatiana, kEntityAbbot, kAction104060776); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 38); + + setup_function51(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(51, Tatiana, function51) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject48, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(52, Tatiana, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTatiana); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(53, Tatiana, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function54(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(54, Tatiana, function54) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param2) { + switch (params->param1) { + default: + break; + + case 0: + getSound()->playSound(kEntityTatiana, "Tat5167A"); + params->param2 = 1; + break; + + case 1: + getSound()->playSound(kEntityTatiana, "Tat5167B"); + params->param2 = 1; + break; + + case 2: + getSound()->playSound(kEntityTatiana, "Tat5167C"); + params->param2 = 1; + break; + + case 3: + getSound()->playSound(kEntityTatiana, "Tat5167D"); + params->param2 = 1; + break; + } + } + + if (params->param1 > 3) { + UPDATE_PARAM(params->param3, getState()->timeTicks, 225); + + params->param1 = 0; + params->param3 = 0; + } + break; + + case kAction1: + getData()->inventoryItem = kItemNone; + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventTatianaVassiliTalk); + break; + + case kActionEndSound: + ++params->param1; + params->param2 = 0; + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityTatiana, "033A"); + getData()->inventoryItem = kItemInvalid; + break; + + case kActionCallback: + if (getCallback() == 1) { + if (getSound()->isBuffered("MUS050")) + getSound()->processEntry("MUS050"); + + if (getSound()->isBuffered(kEntityTatiana)) + getSound()->processEntry(kEntityTatiana); + + getAction()->playAnimation(isNight() ? kEventTatianaVassiliTalkNight : kEventTatianaVassiliTalk); + getScenes()->processScene(); + + params->param1 = 4; + params->param2 = 0; + params->param3 = 0; + } + break; + + case kAction203078272: + getEntities()->drawSequenceLeft(kEntityTatiana, "033E"); + break; + + case kAction236060709: + getData()->inventoryItem = kItemNone; + setup_function55(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(55, Tatiana, function55) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityTatiana); + // fall back to next action + + case kActionDrawScene: + if (getEntities()->isPlayerPosition(kCarRestaurant, 72)) + getScenes()->loadSceneFromPosition(kCarRestaurant, 86); + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/tatiana.h b/engines/lastexpress/entities/tatiana.h new file mode 100644 index 0000000000..8dc5de9b35 --- /dev/null +++ b/engines/lastexpress/entities/tatiana.h @@ -0,0 +1,235 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_TATIANA_H +#define LASTEXPRESS_TATIANA_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Tatiana : public Entity { +public: + Tatiana(LastExpressEngine *engine); + ~Tatiana() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the position + * + * @param sequence1 The sequence to draw + * @param car The car + * @param position The position + */ + DECLARE_FUNCTION_3(updatePosition, const char* sequence1, CarIndex car, Position position) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Handles entering/exiting a compartment and updates position/play animation + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment2, const char* sequence, ObjectIndex compartment) + + /** + * Call a savepoint (or draw sequence in default case) + * + * @param sequence1 The sequence to draw in the default case + * @param entity The entity + * @param action The action + * @param sequence2 The sequence name for the savepoint + */ + DECLARE_FUNCTION_4(callSavepoint, const char* sequence1, EntityIndex entity, ActionIndex action, const char* sequence2) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Updates parameter 2 using ticks value + * + * @param savepoint The savepoint + * - ticks to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTicks) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION(function14) + DECLARE_FUNCTION(function15) + DECLARE_FUNCTION_1(function16, uint32) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION(function18) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(function24) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function27) + DECLARE_FUNCTION(function28) + DECLARE_FUNCTION(function29) + DECLARE_FUNCTION(function30) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + DECLARE_FUNCTION(function36) + DECLARE_FUNCTION(function37) + DECLARE_FUNCTION(function38) + DECLARE_FUNCTION(function39) + DECLARE_FUNCTION(function40) + DECLARE_FUNCTION(function41) + + /** + * ??? + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(function42, CarIndex car, EntityPosition entityPosition) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function45) + DECLARE_FUNCTION(function46) + DECLARE_FUNCTION(function47) + DECLARE_FUNCTION(function48) + DECLARE_FUNCTION(function49) + DECLARE_FUNCTION(function50) + DECLARE_FUNCTION(function51) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function54) + DECLARE_FUNCTION(function55) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_TATIANA_H diff --git a/engines/lastexpress/entities/train.cpp b/engines/lastexpress/entities/train.cpp new file mode 100644 index 0000000000..53f19b1a30 --- /dev/null +++ b/engines/lastexpress/entities/train.cpp @@ -0,0 +1,575 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/train.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savegame.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/state.h" +#include "lastexpress/game/sound.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Train::Train(LastExpressEngine *engine) : Entity(engine, kEntityTrain) { + ADD_CALLBACK_FUNCTION(Train, savegame); + ADD_CALLBACK_FUNCTION(Train, chapter1); + ADD_CALLBACK_FUNCTION(Train, chapter2); + ADD_CALLBACK_FUNCTION(Train, chapter3); + ADD_CALLBACK_FUNCTION(Train, chapter4); + ADD_CALLBACK_FUNCTION(Train, chapter5); + ADD_CALLBACK_FUNCTION(Train, harem); + ADD_CALLBACK_FUNCTION(Train, process); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(1, Train, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(2, Train, chapter1) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Train, chapter2) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Train, chapter3) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Train, chapter4) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Train, chapter5) + if (savepoint.action == kActionDefault) + setup_process(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) + if (savepoint.action != kActionDefault) + return; + + switch (params->param1) { + default: + error("Train::harem: Invalid value for parameter 1: %d", params->param1); + break; + + case kObjectCompartment5: + params->param3 = kPosition_4840; + break; + + case kObjectCompartment6: + params->param3 = kPosition_4070; + break; + + case kObjectCompartment7: + params->param3 = kPosition_3050; + break; + + case kObjectCompartment8: + params->param3 = kPosition_2740; + break; + } + + params->param4 = getEntities()->isInsideCompartment(kEntityAlouan, kCarGreenSleeping, (EntityPosition)params->param3); + params->param5 = (ENTITY_PARAM(0, 7) - params->param3) < 1 ? true : false; + params->param6 = getEntities()->isInsideCompartment(kEntityYasmin, kCarGreenSleeping, (EntityPosition)params->param3); + params->param7 = getEntities()->isInsideCompartment(kEntityHadija, kCarGreenSleeping, (EntityPosition)params->param3); + + getObjects()->update((ObjectIndex)params->param1, kEntityTrain, kObjectLocation3, kCursorNormal, kCursorNormal); + + // Knock / closed door sound + getSound()->playSound(kEntityTables5, (params->param2 == 8) ? "LIB012" : "LIB013", SoundManager::kFlagDefault); + + if (params->param4 && params->param5) { + + ENTITY_PARAM(0, 5)++; + + switch (ENTITY_PARAM(0, 5)) { + default: + params->param8 = 1; + break; + + case 1: + getSound()->playSound(kEntityTables5, "Har1014", SoundManager::kFlagDefault, 15); + break; + + case 2: + getSound()->playSound(kEntityTables5, "Har1013", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1016", SoundManager::kFlagDefault, 150); + break; + + case 3: + getSound()->playSound(kEntityTables5, "Har1015A", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1015", SoundManager::kFlagDefault, 150); + break; + } + + // Update progress + getProgress().field_DC = 1; + getProgress().field_E0 = 1; + + handleCompartmentAction(); + + // Done with it! + return; + } + + if (params->param6 && params->param7) { + + ENTITY_PARAM(0, 6)++; + + switch(ENTITY_PARAM(0, 6)) { + default: + params->param8 = 1; + break; + + case 1: + getSound()->playSound(kEntityTables5, "Har1014", SoundManager::kFlagDefault, 15); + break; + + case 2: + getSound()->playSound(kEntityTables5, "Har1013", SoundManager::kFlagDefault, 15); + break; + + case 3: + getSound()->playSound(kEntityTables5, "Har1013A", SoundManager::kFlagDefault, 15); + break; + } + + handleCompartmentAction(); + return; + } + + if (!params->param5) { + + if (params->param6) { + ENTITY_PARAM(0, 3)++; + + switch(ENTITY_PARAM(0, 3)) { + default: + params->param8 = 1; + break; + + case 1: + getSound()->playSound(kEntityTables5, "Har1012", SoundManager::kFlagDefault, 15); + break; + + case 2: + getSound()->playSound(kEntityTables5, "Har1012A", SoundManager::kFlagDefault, 15); + break; + } + + handleCompartmentAction(); + return; + } else { + + if (params->param4) { + ENTITY_PARAM(0, 1)++; + + if (ENTITY_PARAM(0, 1) <= 1) + getSound()->playSound(kEntityTables5, "Har1014", SoundManager::kFlagDefault, 15); + else + params->param8 = 1; + + getProgress().field_DC = 1; + + handleCompartmentAction(); + return; + } + + if (params->param7) { + ENTITY_PARAM(0, 4)++; + + if (ENTITY_PARAM(0, 4) <= 1) { + getSound()->playSound(kEntityTables5, "Har1011", SoundManager::kFlagDefault, 15); + handleCompartmentAction(); + return; + } + } + } + + params->param8 = 1; + handleCompartmentAction(); + return; + } + + ENTITY_PARAM(0, 2) += 1; + + switch (ENTITY_PARAM(0, 2)) { + default: + params->param8 = 1; + break; + + case 1: + getSound()->playSound(kEntityTables5, "Har1013", SoundManager::kFlagDefault, 15); + break; + + case 2: + getSound()->playSound(kEntityTables5, "Har1013A", SoundManager::kFlagDefault, 15); + break; + } + + getProgress().field_E0 = 1; + + handleCompartmentAction(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Train, process) + EntityData::EntityParametersIIIS *params1 = (EntityData::EntityParametersIIIS*)_data->getCurrentParameters(1); + + switch (savepoint.action) { + default: + break; + + case kActionNone: + // Play smoke animation + if ((getEntities()->isPlayerInCar(kCarGreenSleeping) || getEntities()->isPlayerInCar(kCarRedSleeping)) + && params->param4 && !params->param5) { + + params->param4 -= 1; + + if (!params->param4 && getProgress().jacket == kJacketGreen) { + + getAction()->playAnimation(isNight() ? kEventCathSmokeNight : kEventCathSmokeDay); + params->param5 = 1; + getScenes()->processScene(); + } + } + + if (params->param6) { + UPDATE_PARAM_GOTO(params1->param7, getState()->time, 900, label_process); + getScenes()->loadSceneFromPosition(kCarRestaurant, 58); + } + + params1->param7 = 0; + +label_process: + if (params->param7) { + if (!params1->param8) { + params1->param8 = getState()->time + 4500; + + if (!params1->param8) + params->param7 = 0; + } + + if (params1->param8 && params1->param8 < getState()->time) { + params->param7 = 0; + params1->param8 = 0; + } + } + + // Update object + if (ENTITY_PARAM(0, 8) && !getSound()->isBuffered(kEntityTables5)) { + getObjects()->update((ObjectIndex)ENTITY_PARAM(0, 8), getObjects()->get((ObjectIndex)ENTITY_PARAM(0, 8)).entity, kObjectLocation3, kCursorHandKnock, kCursorHand); + ENTITY_PARAM(0, 8) = 0; + } + + // Play clock sound + if (params->param6 && !getSound()->isBuffered("ZFX1001", true)) + getSound()->playSound(kEntityPlayer, "ZFX1001"); + + break; + + case kActionKnock: + case kActionOpenDoor: { + // Handle opening harem compartments + ObjectIndex compartment = (ObjectIndex)savepoint.param.intValue; + if (compartment == kObjectCompartment5 || compartment == kObjectCompartment6 || compartment == kObjectCompartment7 || compartment == kObjectCompartment8) { + setCallback(savepoint.action == kActionKnock ? 3 : 4); + setup_harem(compartment, savepoint.action); + } + break; + } + + case kActionDefault: + params->param3 = 1; + if (getProgress().chapter < kChapter5) { + getObjects()->update(kObjectCompartment5, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment6, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment7, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment8, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); + } + getData()->entityPosition = kPosition_30000; + break; + + case kActionDrawScene: + getData()->car = getEntityData(kEntityPlayer)->car; + + // Play clock sound + if (getEntities()->isPlayerPosition(kCarRestaurant, 81)) { + params->param6 = 1; + if (!getSound()->isBuffered("ZFX1001")) + getSound()->playSound(kEntityPlayer, "ZFX1001"); + } else { + params->param6 = 0; + if (getSound()->isBuffered("ZFX1001", true)) + getSound()->removeFromQueue("ZFX1001"); + } + + // Draw moving background behind windows + if (params->param3) { + if (getEntityData(kEntityPlayer)->car != (CarIndex)params->param1 || isNight() != (bool)(params->param2)) { + switch (getEntityData(kEntityPlayer)->car) { + default: + getEntities()->clearSequences(kEntityTrain); + break; + + case kCarBaggageRear: + case kCarBaggage: + if (getProgress().isNightTime) + getEntities()->drawSequenceLeft(kEntityTrain, "B1WNM"); + else + getEntities()->drawSequenceLeft(kEntityTrain, isNight() ? "B1WNN" : "B1WND"); + break; + + case kCarGreenSleeping: + case kCarRedSleeping: + if (getProgress().isNightTime) + getEntities()->drawSequenceLeft(kEntityTrain, "S1WNM"); + else + getEntities()->drawSequenceLeft(kEntityTrain, isNight() ? "S1WNN" : "S1WND"); + break; + + case kCarRestaurant: + getEntities()->drawSequenceLeft(kEntityTrain, isNight() ? "RCWNN" : "RCWND"); + break; + } + + // Set parameters so we do not get called twice + params->param1 = getEntityData(kEntityPlayer)->car; + params->param2 = isNight(); + } + } + + if (!params->param5) { + params->param4 = 2700; // this is the sound file name + params->param5 = 0; + } + + if (getProgress().jacket == kJacketBlood) { + if (getEntities()->isPlayerPosition(kCarRedSleeping, 18)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + } + + if (getEntities()->isPlayerPosition(kCarGreenSleeping, 22)) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + break; + } + } + + resetParam8(); + break; + + + case kActionCallback: { + int action = getCallback(); + switch(action) { + default: + break; + + case 1: + case 2: + getAction()->playAnimation(action == 1 ? kEventCoudertBloodJacket : kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); + resetParam8(); + break; + + case 5: + getAction()->playAnimation(kEventLocomotiveConductorsDiscovered); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice2, true); + break; + + case 6: + getAction()->playAnimation(kEventCathBreakCeiling); + getObjects()->update(kObjectCeiling, kEntityPlayer, kObjectLocation2, kCursorKeepValue, kCursorKeepValue); + getScenes()->processScene(); + break; + + case 7: + getAction()->playAnimation(kEventCathJumpDownCeiling); + getScenes()->loadSceneFromPosition(kCarKronos, 89); + break; + + case 8: + getAction()->playAnimation(kEventCloseMatchbox); + getScenes()->loadSceneFromPosition(kCarRestaurant, 51); + break; + } + break; + } + + case kAction191070912: + ENTITY_PARAM(0, 7) = savepoint.param.intValue; + break; + + case kActionTrainStopRunning: + params->param3 = 0; + getEntities()->clearSequences(kEntityTrain); + break; + + case kActionCatchBeetle: + setCallback(8); + setup_savegame(kSavegameTypeEvent, kEventCloseMatchbox); + break; + + case kAction203339360: + if (params->param7) { + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventLocomotiveConductorsDiscovered); + } else { + params->param7 = 1; + getAction()->playAnimation(kEventLocomotiveConductorsLook); + getScenes()->loadSceneFromPosition(kCarCoalTender, 2); + } + break; + + case kActionTrainStartRunning: + if (!params->param3) { + params->param1 = 0; + params->param3 = 1; + getSavePoints()->push(kEntityTrain, kEntityTrain, kActionDrawScene); + } + break; + + case kAction203863200: + if (!strcmp(savepoint.param.charValue, "")) { + params->param8 = 1; + strcpy((char *)¶ms1->seq, savepoint.param.charValue); // this is the sound file name + } + break; + + case kAction222746496: + switch(savepoint.param.intValue) { + default: + break; + + case kObjectCompartment1: + case kObjectCompartment2: + case kObjectCompartmentA: + case kObjectCompartmentB: + params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param2 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartmentA) ? kPosition_8200 : kPosition_7500; + params1->param3 = kPosition_7850; + break; + + case kObjectCompartment3: + case kObjectCompartment4: + case kObjectCompartmentC: + case kObjectCompartmentD: + params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param2 = (savepoint.param.intValue == kObjectCompartment3 || savepoint.param.intValue == kObjectCompartmentC) ? kPosition_6470 : kPosition_5790; + params1->param3 = kPosition_6130; + break; + + case kObjectCompartment5: + case kObjectCompartment6: + case kObjectCompartmentE: + case kObjectCompartmentF: + params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param2 = (savepoint.param.intValue == kObjectCompartment5 || savepoint.param.intValue == kObjectCompartmentE) ? kPosition_4840 : kPosition_4070; + params1->param3 = kPosition_4455; + break; + + case kObjectCompartment7: + case kObjectCompartment8: + case kObjectCompartmentG: + case kObjectCompartmentH: + params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param2 = (savepoint.param.intValue == kObjectCompartment7 || savepoint.param.intValue == kObjectCompartmentG) ? kPosition_3050 : kPosition_2740; + params1->param3 = kPositionNone; + break; + } + break; + + case kActionBreakCeiling: + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventCathBreakCeiling); + break; + + case kActionJumpDownCeiling: + setCallback(7); + setup_savegame(kSavegameTypeEvent, kEventCathJumpDownCeiling); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Train::handleCompartmentAction() { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + + if (params->param8) + getSavePoints()->push(kEntityTrain, kEntityMahmud, kAction290410610, params->param1); + + getAction()->handleOtherCompartment((ObjectIndex)params->param1, false, !params->param8); + + ENTITY_PARAM(0, 8) = params->param1; + + CALLBACK_ACTION(); +} + +////////////////////////////////////////////////////////////////////////// +void Train::resetParam8() { + EXPOSE_PARAMS(EntityData::EntityParametersIIII) + EntityData::EntityParametersIIIS *params1 = (EntityData::EntityParametersIIIS*)_data->getCurrentParameters(1); + + if (params->param8 + && !getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params1->param1, (EntityPosition)params1->param2) + && !getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params1->param1, (EntityPosition)params1->param3)) { + + if (getSound()->isBuffered((const char *)¶ms1->seq)) + getSound()->processEntry((const char *)¶ms1->seq); + + params->param8 = 0; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/train.h b/engines/lastexpress/entities/train.h new file mode 100644 index 0000000000..4c6e2989ff --- /dev/null +++ b/engines/lastexpress/entities/train.h @@ -0,0 +1,95 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_TRAIN_H +#define LASTEXPRESS_TRAIN_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Train : public Entity { +public: + Train(LastExpressEngine *engine); + ~Train() {}; + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Harem events + * + * @param compartment The compartment to handle + * @param counter ??? (checked to decide which sound to make when knocking) + */ + DECLARE_FUNCTION_2(harem, ObjectIndex compartment, uint32 counter) + + /** + * Handles Train events + */ + DECLARE_FUNCTION(process) + +private: + // Helper methods + void resetParam8(); + void handleCompartmentAction(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_TRAIN_H diff --git a/engines/lastexpress/entities/vassili.cpp b/engines/lastexpress/entities/vassili.cpp new file mode 100644 index 0000000000..951c323f91 --- /dev/null +++ b/engines/lastexpress/entities/vassili.cpp @@ -0,0 +1,589 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/vassili.h" + +#include "lastexpress/entities/anna.h" +#include "lastexpress/entities/coudert.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Vassili::Vassili(LastExpressEngine *engine) : Entity(engine, kEntityVassili) { + ADD_CALLBACK_FUNCTION(Vassili, reset); + ADD_CALLBACK_FUNCTION(Vassili, draw); + ADD_CALLBACK_FUNCTION(Vassili, savegame); + ADD_CALLBACK_FUNCTION(Vassili, chapter1); + ADD_CALLBACK_FUNCTION(Vassili, chapter1Handler); + ADD_CALLBACK_FUNCTION(Vassili, function6); + ADD_CALLBACK_FUNCTION(Vassili, function7); + ADD_CALLBACK_FUNCTION(Vassili, function8); + ADD_CALLBACK_FUNCTION(Vassili, function9); + ADD_CALLBACK_FUNCTION(Vassili, seizure); + ADD_CALLBACK_FUNCTION(Vassili, drawInBed); + ADD_CALLBACK_FUNCTION(Vassili, chapter2); + ADD_CALLBACK_FUNCTION(Vassili, sleeping); + ADD_CALLBACK_FUNCTION(Vassili, chapter3); + ADD_CALLBACK_FUNCTION(Vassili, stealEgg); + ADD_CALLBACK_FUNCTION(Vassili, chapter4); + ADD_CALLBACK_FUNCTION(Vassili, chapter4Handler); + ADD_CALLBACK_FUNCTION(Vassili, chapter5); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Vassili, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Vassili, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(3, Vassili, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(4, Vassili, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject40, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(5, Vassili, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + getData()->entityPosition = getEntityData(kEntityTatiana)->entityPosition; + getData()->location = getEntityData(kEntityTatiana)->location; + } else { + if (params->param3 && params->param3 >= getState()->time) { + break; + }else { + params->param3 = getState()->time + 450; + if (params->param3 == 0) + break; + } + + if (!params->param2 && getObjects()->get(kObjectCompartmentA).location == kObjectLocation1) { + params->param2 = 1; + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + } + break; + } + break; + + case kActionDefault: + params->param1 = 1; + break; + + case kAction122732000: + setup_function6(); + break; + + case kAction168459827: + params->param1 = 0; + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Vassili, function6) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { + UPDATE_PARAM_GOTO(params->param3, getState()->timeTicks, params->param1, label_function7); + + setCallback(1); + setup_draw("303B"); + break; + } + + params->param3 = 0; + + if (params->param2) + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + +label_function7: + if (params->param4 != kTimeInvalid && getState()->time > kTime1489500) { + + if (getState()->time <= kTime1503000) { + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200) || !params->param4) { + + params->param4 = getState()->time; + if (!params->param4) { + setup_function7(); + break; + } + } + + if (params->param4 >= getState()->time) + break; + } + + params->param4 = kTimeInvalid; + setup_function7(); + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + params->param1 = 5 * (3 * rnd(25) + 15); + + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->drawSequenceLeft(kEntityVassili, "303C"); + params->param1 = 5 * (3 * rnd(25) + 15); + params->param2 = 1; + + // Shared part with kActionNone + goto label_function7; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Vassili, function7) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1 != kTimeInvalid && getState()->time > kTime1503000) { + + if (getState()->time <= kTime1512000) { + if (getEntities()->isPlayerInCar(kCarRedSleeping) || !params->param1) { + params->param1 = getState()->time + 150; + if (params->param1) { + setup_function8(); + break; + } + } + + if (params->param1 >= getState()->time) + break; + } + + params->param1 = kTimeInvalid; + setup_function8(); + } + break; + + case kActionDefault: + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityVassili); + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) + getScenes()->loadSceneFromObject(kObjectCompartmentA); + + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + break; + + case kAction339669520: + setup_function9(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Vassili, function8) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + setup_function9(); + break; + + case kActionDefault: + if (!getEntities()->isInsideTrainCar(kEntityPlayer, kCarRedSleeping)) { + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRedSleeping, (getEntityData(kEntityPlayer)->car <= kCarRedSleeping) ? 1 : 40); + } + + getSavePoints()->push(kEntityVassili, kEntityAnna, kAction226031488); + getSavePoints()->push(kEntityVassili, kEntityVerges, kAction226031488); + getSavePoints()->push(kEntityVassili, kEntityCoudert, kAction226031488); + getSound()->playSound(kEntityVassili, "VAS1027", SoundManager::kFlagDefault); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Vassili, function9) + switch (savepoint.action) { + default: + break; + + case kActionEndSound: + if (!getEntities()->isDistanceBetweenEntities(kEntityVassili, kEntityPlayer, 2500)) + getSound()->playSound(kEntityPlayer, "BUMP"); + + setup_seizure(); + break; + + case kActionDefault: + case kActionDrawScene: + if ((getObjects()->get(kObjectCompartmentA).location == kObjectLocation2 && getEntities()->isPlayerPosition(kCarRedSleeping, 17)) + || getEntities()->isPlayerPosition(kCarRedSleeping, 18) + || getEntities()->isPlayerPosition(kCarRedSleeping, 37) + || getEntities()->isPlayerPosition(kCarRedSleeping, 38) + || getEntities()->isPlayerPosition(kCarRedSleeping, 41)) { + + if (savepoint.action == kActionDrawScene) + getSound()->processEntry(kEntityVassili); + + setup_seizure(); + } else { + if (savepoint.action == kActionDefault) + getSound()->playSound(kEntityVassili, "VAS1028", SoundManager::kFlagDefault); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Vassili, seizure) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + // Check that we have removed the body from the train and changed jacket + if (!getProgress().eventCorpseMovedFromFloor) { + getAction()->playAnimation(kEventMertensCorpseFloor); + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, false); + break; + } + + if (!getProgress().eventCorpseThrown) { + getAction()->playAnimation(kEventMertensCorpseBed); + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, false); + break; + } + + if (getProgress().jacket == kJacketBlood) { + getAction()->playAnimation(kEventMertensBloodJacket); + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, false); + break; + } + + // Setup Anna & Coudert + RESET_ENTITY_STATE(kEntityAnna, Anna, setup_function37); + RESET_ENTITY_STATE(kEntityCoudert, Coudert, setup_function38); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventVassiliSeizure); + break; + + case kActionCallback: + if (getCallback() != 1) + break; + + getData()->location = kLocationInsideCompartment; + getAction()->playAnimation(kEventVassiliSeizure); + + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getProgress().field_18 = 2; + + getSavePoints()->push(kEntityVassili, kEntityAnna, kAction191477936); + getSavePoints()->push(kEntityVassili, kEntityVerges, kAction191477936); + getSavePoints()->push(kEntityVassili, kEntityCoudert, kAction191477936); + getScenes()->loadSceneFromObject(kObjectCompartmentA); + + setup_drawInBed(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Vassili, drawInBed) + if (savepoint.action == kActionDefault) + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Vassili, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_sleeping(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVassili); + + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->updateLocation2(kObjectCompartmentA, kObjectLocation1); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Vassili, sleeping) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { + UPDATE_PARAM(params->param3, getState()->timeTicks, params->param1); + + setCallback(1); + setup_draw("303B"); + } else { + params->param3 = 0; + if (params->param2) + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + } + break; + + case kActionDefault: + params->param5 = 5 * (3 * rnd(25) + 15); + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + break; + + case kActionCallback: + if (getCallback() != 1) + break; + + getEntities()->drawSequenceLeft(kEntityVassili, "303C"); + params->param1 = 5 * (3 * rnd(25) + 15); + params->param2 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Vassili, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_stealEgg(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVassili); + + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Vassili, stealEgg) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { + UPDATE_PARAM(params->param3, getState()->timeTicks, params->param1); + + setCallback(1); + setup_draw("303B"); + } else { + params->param3 = 0; + if (params->param2) + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + } + break; + + case kActionOpenDoor: + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventVassiliCompartmentStealEgg); + break; + + case kActionDefault: + params->param5 = 5 * (3 * rnd(25) + 15); + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + break; + + case kActionDrawScene: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_7850) + && getInventory()->hasItem(kItemFirebird) + && !getEvent(kEventVassiliCompartmentStealEgg)) + getObjects()->update(kObject48, kEntityVassili, kObjectLocationNone, kCursorNormal, kCursorHand); + else + getObjects()->update(kObject48, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityVassili, "303C"); + params->param1 = 5 * (3 * rnd(25) + 15); + params->param2 = 1; + break; + + case 2: + getAction()->playAnimation(kEventVassiliCompartmentStealEgg); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 67); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Vassili, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVassili); + + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->updateLocation2(kObjectCompartmentA, kObjectLocation1); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +// Looks identical to sleeping (#13) +IMPLEMENT_FUNCTION(17, Vassili, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { + UPDATE_PARAM(params->param3, getState()->timeTicks, params->param1); + + setCallback(1); + setup_draw("303B"); + } else { + params->param3 = 0; + if (params->param2) + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + } + break; + + case kActionDefault: + params->param5 = 5 * (3 * rnd(25) + 15); + getEntities()->drawSequenceLeft(kEntityVassili, "303A"); + break; + + case kActionCallback: + if (getCallback() != 1) + break; + + getEntities()->drawSequenceLeft(kEntityVassili, "303C"); + params->param1 = 5 * (3 * rnd(25) + 15); + params->param2 = 1; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Vassili, chapter5) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityVassili); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/vassili.h b/engines/lastexpress/entities/vassili.h new file mode 100644 index 0000000000..113bc1d958 --- /dev/null +++ b/engines/lastexpress/entities/vassili.h @@ -0,0 +1,110 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_VASSILI_H +#define LASTEXPRESS_VASSILI_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Vassili : public Entity { +public: + Vassili(LastExpressEngine *engine); + ~Vassili() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function6) + DECLARE_FUNCTION(function7) + DECLARE_FUNCTION(function8) + DECLARE_FUNCTION(function9) + DECLARE_FUNCTION(seizure) + DECLARE_FUNCTION(drawInBed) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + DECLARE_FUNCTION(sleeping) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + DECLARE_FUNCTION(stealEgg) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_VASSILI_H diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp new file mode 100644 index 0000000000..20979ff9f9 --- /dev/null +++ b/engines/lastexpress/entities/verges.cpp @@ -0,0 +1,1898 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/verges.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Verges::Verges(LastExpressEngine *engine) : Entity(engine, kEntityVerges) { + ADD_CALLBACK_FUNCTION(Verges, reset); + ADD_CALLBACK_FUNCTION(Verges, draw); + ADD_CALLBACK_FUNCTION(Verges, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Verges, playSound); + ADD_CALLBACK_FUNCTION(Verges, playSound16); + ADD_CALLBACK_FUNCTION(Verges, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Verges, savegame); + ADD_CALLBACK_FUNCTION(Verges, updateEntity); + ADD_CALLBACK_FUNCTION(Verges, function9); + ADD_CALLBACK_FUNCTION(Verges, function10); + ADD_CALLBACK_FUNCTION(Verges, function11); + ADD_CALLBACK_FUNCTION(Verges, function12); + ADD_CALLBACK_FUNCTION(Verges, function13); + ADD_CALLBACK_FUNCTION(Verges, updateFromTime); + ADD_CALLBACK_FUNCTION(Verges, function15); + ADD_CALLBACK_FUNCTION(Verges, function16); + ADD_CALLBACK_FUNCTION(Verges, function17); + ADD_CALLBACK_FUNCTION(Verges, chapter1); + ADD_CALLBACK_FUNCTION(Verges, talkHarem); + ADD_CALLBACK_FUNCTION(Verges, talkPassengerList); + ADD_CALLBACK_FUNCTION(Verges, talkGendarmes); + ADD_CALLBACK_FUNCTION(Verges, function22); + ADD_CALLBACK_FUNCTION(Verges, function23); + ADD_CALLBACK_FUNCTION(Verges, policeGettingOffTrain); + ADD_CALLBACK_FUNCTION(Verges, function25); + ADD_CALLBACK_FUNCTION(Verges, chapter1Handler); + ADD_CALLBACK_FUNCTION(Verges, chapter2); + ADD_CALLBACK_FUNCTION(Verges, chapter2Handler); + ADD_CALLBACK_FUNCTION(Verges, chapter3); + ADD_CALLBACK_FUNCTION(Verges, function30); + ADD_CALLBACK_FUNCTION(Verges, function31); + ADD_CALLBACK_FUNCTION(Verges, function32); + ADD_CALLBACK_FUNCTION(Verges, function33); + ADD_CALLBACK_FUNCTION(Verges, function34); + ADD_CALLBACK_FUNCTION(Verges, function35); + ADD_CALLBACK_FUNCTION(Verges, chapter4); + ADD_CALLBACK_FUNCTION(Verges, chapter4Handler); + ADD_CALLBACK_FUNCTION(Verges, function38); + ADD_CALLBACK_FUNCTION(Verges, chapter5); + ADD_CALLBACK_FUNCTION(Verges, chapter5Handler); + ADD_CALLBACK_FUNCTION(Verges, function41); + ADD_CALLBACK_FUNCTION(Verges, function42); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Verges, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Verges, draw) + Entity::draw(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(3, Verges, callbackActionOnDirection) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getData()->direction != kDirectionRight) + CALLBACK_ACTION(); + break; + + case kActionExitCompartment: + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + if (!params->param1) { + getSound()->excuseMe(kEntityVerges); + params->param1 = 1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(4, Verges, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(5, Verges, playSound16) + Entity::playSound(savepoint, false, SoundManager::kFlagDefault); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Verges, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, Verges, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(8, Verges, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + if (!getSound()->isBuffered(kEntityVerges)) + getSound()->playSound(kEntityPlayer, "TRA1113", getSound()->getSoundFlag(kEntityVerges)); + + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(9, Verges, function9) +switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObject104, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + + if (getEntities()->isInBaggageCar(kEntityPlayer) || getEntities()->isInKitchen(kEntityPlayer)) { + getAction()->playAnimation(getEntities()->isInBaggageCar(kEntityPlayer) ? kEventVergesBaggageCarOffLimits : kEventVergesCanIHelpYou); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + } + + getScenes()->loadSceneFromItemPosition(kItem9); + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_5900; + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + getSound()->playSound(kEntityVerges, (char *)¶ms->seq1); + + setCallback(2); + setup_draw("813DD"); + break; + + case 2: + if (!getSound()->isBuffered(kEntityVerges)) + getSound()->playSound(kEntityVerges, (char *)¶ms->seq1); + + getEntities()->drawSequenceRight(kEntityVerges, "813DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVerges); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + setCallback(4); + setup_function10(kCarGreenSleeping, kPosition_540, (char *)¶ms->seq1); + break; + + case 4: + getEntities()->clearSequences(kEntityVerges); + + setCallback(5); + setup_updateFromTime(225); + break; + + case 5: + setCallback(6); + setup_function11(); + break; + + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IIS(10, Verges, function10, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param7) { + if (!getSound()->isBuffered(kEntityVerges)) { + getSound()->playSound(kEntityVerges, (char *)¶ms->seq); + params->param7 = 1; + } + } + + if (getEntities()->updateEntity(kEntityVerges, (CarIndex)params->param1, (EntityPosition)params->param2)) { + CALLBACK_ACTION(); + break; + } + + if (params->param6) { + UPDATE_PARAM(params->param8, getState()->timeTicks, 75); + + getSound()->playSound(kEntityVerges, (char *)¶ms->seq); + + params->param6 = 0; + params->param8 = 0; + } + break; + + case kActionEndSound: + params->param6 = 1; + break; + + case kActionDefault: + if (!getSound()->isBuffered(kEntityVerges)) { + getSound()->playSound(kEntityVerges, (char *)¶ms->seq); + params->param7 = 1; + } + + if (getEntities()->updateEntity(kEntityVerges, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Verges, function11) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_updateEntity(kCarRestaurant, kPosition_540); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_callbackActionRestaurantOrSalon(); + break; + + case 2: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(3); + setup_draw("813US"); + break; + + case 3: + getEntities()->drawSequenceRight(kEntityVerges, "813UD"); + + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityVerges); + + setCallback(4); + setup_callbackActionOnDirection(); + break; + + case 4: { + getEntities()->clearSequences(kEntityVerges); + + bool loadscene = true; + + if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) + getAction()->playAnimation(kEventVergesEscortToDiningCar); + else if (getEntities()->isInBaggageCar(kEntityPlayer)) + getAction()->playAnimation(kEventVergesBaggageCarOffLimits); + else if (getEntities()->isInKitchen(kEntityPlayer)) + getAction()->playAnimation(kEventVergesCanIHelpYou); + else + loadscene = false; + + if (loadscene) { + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + } + + getInventory()->setLocationAndProcess(kItem9, kObjectLocation1); + + getData()->car = kCarBaggage; + getData()->entityPosition = kPosition_5000; + + getObjects()->update(kObject104, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + + CALLBACK_ACTION(); + break; + } + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Verges, function12) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObject104, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + + if (getEntities()->isInBaggageCar(kEntityPlayer) || getEntities()->isInKitchen(kEntityPlayer)) { + getAction()->playAnimation(getEntities()->isInBaggageCar(kEntityPlayer) ? kEventVergesBaggageCarOffLimits : kEventVergesCanIHelpYou); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + } + + getScenes()->loadSceneFromItemPosition(kItem9); + + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_5900; + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_draw("813DD"); + break; + + case 2: + getEntities()->drawSequenceRight(kEntityVerges, "813DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVerges); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + getData()->entityPosition = kPosition_850; + getEntities()->clearSequences(kEntityVerges); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(13, Verges, function13, bool) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventVergesSuitcase); + break; + + case kActionCallback: + if (getCallback() == 1) { + if (getEvent(kEventVergesSuitcase) || getEvent(kEventVergesSuitcaseNight) || getEvent(kEventVergesSuitcaseOtherEntry) || getEvent(kEventVergesSuitcaseNightOtherEntry)) + params->param2 = 1; + + if (isNight() && getProgress().chapter != kChapter1) + params->param2 = 1; + + if (params->param1) { + if (isNight()) + getAction()->playAnimation(params->param2 ? kEventVergesSuitcaseNightOtherEntryStart : kEventVergesSuitcaseNightOtherEntry); + else + getAction()->playAnimation(params->param2 ? kEventVergesSuitcaseOtherEntryStart : kEventVergesSuitcaseOtherEntry); + } else { + if (isNight()) + getAction()->playAnimation(params->param2 ? kEventVergesSuitcaseNightStart : kEventVergesSuitcaseNight); + else + getAction()->playAnimation(params->param2 ? kEventVergesSuitcaseStart : kEventVergesSuitcase); + } + + getEntities()->clearSequences(kEntityVerges); + getScenes()->loadSceneFromPosition(kCarBaggage, 91); + + CALLBACK_ACTION(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(14, Verges, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_IS(15, Verges, function15, EntityIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param5 && params->param6) { + getSavePoints()->push(kEntityVerges, (EntityIndex)params->param1, kAction125499160); + + if (!getEntities()->isPlayerPosition(kCarGreenSleeping, 2) && !getEntities()->isPlayerPosition(kCarRedSleeping, 2)) + getData()->entityPosition = kPosition_2088; + + CALLBACK_ACTION(); + } + break; + + case kActionEndSound: + params->param5 = 1; + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityVerges, "620F"); + getSavePoints()->push(kEntityVerges, (EntityIndex)params->param1, kAction171394341); + break; + + case kAction155853632: + params->param6 = 1; + break; + + case kAction202558662: + getEntities()->drawSequenceLeft(kEntityVerges, "620E"); + getSound()->playSound(kEntityVerges, (char *)¶ms->seq); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_ISS(16, Verges, function16, EntityIndex) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (CURRENT_PARAMS(1, 1) && params->param8) { + getSavePoints()->push(kEntityVerges, (EntityIndex)params->param1, kAction125499160); + + if (!getEntities()->isPlayerPosition(kCarGreenSleeping, 2) && !getEntities()->isPlayerPosition(kCarRedSleeping, 2)) + getData()->entityPosition = kPosition_2088; + + CALLBACK_ACTION(); + } + break; + + case kActionEndSound: + CURRENT_PARAMS(1, 1)++; + + if (CURRENT_PARAMS(1, 1) == 1) + getSound()->playSound(kEntityVerges, (char *)¶ms->seq2); + break; + + case kActionDefault: + getEntities()->drawSequenceLeft(kEntityVerges, "620F"); + getSavePoints()->push(kEntityVerges, (EntityIndex)params->param1, kAction171394341); + break; + + case kAction155853632: + params->param8 = 1; + break; + + case kAction202558662: + getEntities()->drawSequenceLeft(kEntityVerges, "620E"); + getSound()->playSound(kEntityVerges, (char *)¶ms->seq1); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Verges, function17) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 2: + setCallback(3); + setup_function15(kEntityMertens, "TRA1291"); + break; + + case 3: + setCallback(4); + setup_function11(); + break; + + case 4: + ENTITY_PARAM(0, 3) = 0; + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Verges, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityVerges, kActionDeliverMessageToTyler, 0); + getSavePoints()->addData(kEntityVerges, kAction226031488, 1); + getSavePoints()->addData(kEntityVerges, kAction339669520, 1); + getSavePoints()->addData(kEntityVerges, kAction167854368, 4); + getSavePoints()->addData(kEntityVerges, kAction158617345, 2); + getSavePoints()->addData(kEntityVerges, kAction168255788, 3); + getSavePoints()->addData(kEntityVerges, kAction201431954, 5); + getSavePoints()->addData(kEntityVerges, kAction168187490, 6); + + getObjects()->update(kObject104, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarBaggage; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(19, Verges, talkHarem) + talk(savepoint, "TRA1202", "TRA1201"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Verges, talkPassengerList) + talk(savepoint, "TRA1205", "TRA1206"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Verges, talkGendarmes) + talk(savepoint, "TRA1250", "TRA1251"); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Verges, function22) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 2: + if (getEvent(kEventMertensAskTylerCompartment) || getEvent(kEventMertensAskTylerCompartmentD) || getEvent(kEventMertensAugustWaiting)) { + setCallback(3); + setup_function16(kEntityMertens, "TRA1200", "TRA1201"); + } else { + setCallback(4); + setup_function16(kEntityMertens, "TRA1200A", "TRA1201"); + } + break; + + case 3: + case 4: + getSavePoints()->push(kEntityVerges, kEntityMertens, kAction169633856); + + setCallback(5); + setup_function11(); + break; + + case 5: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Verges, function23) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getScenes()->loadSceneFromItemPosition(kItem9); + + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + + case kAction191477936: + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + + setCallback(1); + setup_function11(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Verges, policeGettingOffTrain) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isDistanceBetweenEntities(kEntityVerges, kEntityPlayer, 1000) && getEntityData(kEntityPlayer)->location == kLocationOutsideCompartment) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventGendarmesArrestation); + } + break; + + case kActionEndSound: + CALLBACK_ACTION(); + break; + + case kActionDefault: + getSound()->playSound(kEntityVerges, "POL1101", SoundManager::kFlagDefault); + break; + + case kActionCallback: + if (getCallback() == 1) { + getSound()->processEntry(kEntityVerges); + getAction()->playAnimation(kEventGendarmesArrestation); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Verges, function25) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getScenes()->loadSceneFromItemPosition(kItem9); + + if (!getEntities()->isInKronosSalon(kEntityPlayer)) { + + if (getEntityData(kEntityPlayer)->car > kCarRedSleeping + || (getEntityData(kEntityPlayer)->car == kCarRedSleeping && getEntityData(kEntityPlayer)->entityPosition > kPosition_9270)) { + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 40); + + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_9270; + } else { + if (getEntityData(kEntityPlayer)->car > kCarGreenSleeping + || (getEntityData(kEntityPlayer)->car == kCarGreenSleeping && getEntityData(kEntityPlayer)->entityPosition < kPosition_4840)) { + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartment5, true); + } + + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_850; + } + + getData()->location = kLocationOutsideCompartment; + + getObjects()->update(kObjectRestaurantCar, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorForward); + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + + if (getEntities()->isOutsideAnnaWindow()) + getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); + + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4840) + || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_4455)) { + getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromObject(kObjectCompartmentE, true); + } + + getSavePoints()->push(kEntityVerges, kEntityGendarmes, kAction169499649); + + getProgress().field_3C = 1; + getState()->timeDelta = 1; + + if (getData()->car == kCarRedSleeping) { + setCallback(6); + setup_function10(kCarGreenSleeping, kPosition_540, "TRA1005"); + } else { + setCallback(7); + setup_function10(kCarRedSleeping, kPosition_9460, "TRA1006"); + } + break; + } + // Fallback to next case + + case 2: + if (getEvent(kEventKronosConversation)) { + getProgress().field_3C = 1; + getData()->car = kCarGreenSleeping; + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + + getState()->timeDelta = 3; + getSavePoints()->push(kEntityVerges, kEntityChapters, kAction169629818); + + setCallback(3); + setup_policeGettingOffTrain(); + } else { + setCallback(2); + setup_updateFromTime(150); + } + break; + + case 3: + getSavePoints()->push(kEntityVerges, kEntityCoudert, kAction168254872); + + setCallback(4); + setup_function10(kCarRedSleeping, kPosition_9460, "TRA1006"); + break; + + case 4: + setCallback(5); + setup_function11(); + break; + + case 5: + case 11: + ENTITY_PARAM(0, 7) = 0; + + CALLBACK_ACTION(); + break; + + case 6: + case 7: + getEntities()->clearSequences(kEntityVerges); + break; + + case 8: + getSavePoints()->push(kEntityVerges, kEntityChapters, kAction169629818); + + setCallback(9); + setup_policeGettingOffTrain(); + break; + + case 9: + getObjects()->update(kObjectRestaurantCar, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + getObjects()->update(kObjectCompartmentE, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getSavePoints()->push(kEntityVerges, kEntityCoudert, kAction168254872); + + setCallback(10); + setup_function10(kCarGreenSleeping, kPosition_540, "TRA1006"); + break; + + case 10: + setCallback(11); + setup_function11(); + break; + } + break; + + case kAction168710784: + getData()->car = kCarGreenSleeping; + + if (!(getEntityData(kEntityPlayer)->car == kCarGreenSleeping)) + getData()->car = kCarRedSleeping; + + getData()->entityPosition = kPosition_8200; + getData()->location = kLocationOutsideCompartment; + + getState()->timeDelta = 3; + + setCallback(8); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Verges, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (ENTITY_PARAM(0, 6)) { + params->param1 = 1; + params->param2 = 1; + params->param3 = 1; + params->param4 = 1; + params->param5 = 1; + params->param6 = 1; + + ENTITY_PARAM(0, 6) = 0; + } + + if (ENTITY_PARAM(0, 2)) { + setCallback(1); + setup_function23(); + break; + } + +label_callback1: + if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) { + setCallback(2); + setup_function13(false); + break; + } + +label_callback2: + if (ENTITY_PARAM(0, 7)) { + setCallback(3); + setup_function25(); + break; + } + +label_callback3: + if (params->param6) + goto label_callback12; + + TIME_CHECK_CALLBACK_1(kTimeChapter1, params->param7, 4, setup_function9, "TRA1001"); + +label_callback4: + TIME_CHECK_CALLBACK(kTime1089000, params->param8, 5, setup_function12); + + params->param8 = 1; + + if (!params->param5) { + setCallback(5); + setup_function12(); + break; + } + +label_callback8: + TIME_CHECK_CALLBACK_1(kTime1107000, CURRENT_PARAMS(1, 1), 9, setup_function9, "TRA1001A"); + +label_callback9: + TIME_CHECK_CALLBACK_1(kTime1134000, CURRENT_PARAMS(1, 2), 10, setup_function9, "TRA1002"); + +label_callback10: + TIME_CHECK_CALLBACK_1(kTime1165500, CURRENT_PARAMS(1, 3), 11, setup_function9, "TRA1003"); + +label_callback11: + TIME_CHECK_CALLBACK_1(kTime1225800, CURRENT_PARAMS(1, 4), 12, setup_function9, "TRA1004"); + +label_callback12: + if (ENTITY_PARAM(0, 5) && !params->param2) { + setCallback(13); + setup_talkGendarmes(); + break; + } + +label_callback13: + if (getInventory()->hasItem(kItemPassengerList) && !params->param3 && (getState()->time < kTime1134000 || getState()->time > kTime1156500)) { + setCallback(14); + setup_talkPassengerList(); + break; + } + +label_callback14: + if (ENTITY_PARAM(0, 3) && !params->param4 && (getState()->time < kTime1134000 || getState()->time > kTime1156500)) { + setCallback(15); + setup_function17(); + break; + } + +label_callback15: + if (ENTITY_PARAM(0, 1) && !params->param5) { + if (getState()->time < kTime1134000 || getState()->time > kTime1156500) { + setCallback(16); + setup_function22(); + } + } + break; + + case kActionOpenDoor: + setCallback(17); + setup_function13(savepoint.param.intValue < 106 ? true : false); + break; + + case kActionDefault: + getData()->car = kCarBaggage; + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + + getEntities()->clearSequences(kEntityVerges); + getInventory()->setLocationAndProcess(kItem9, kObjectLocation1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback1; + + case 2: + goto label_callback2; + + case 3: + goto label_callback3; + + case 4: + goto label_callback4; + + case 5: + setCallback(6); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 6: + setCallback(7); + setup_function15(kEntityMertens, "TRA1202"); + break; + + case 7: + setCallback(8); + setup_function11(); + break; + + case 8: + goto label_callback8; + + case 9: + goto label_callback9; + + case 10: + goto label_callback10; + + case 11: + goto label_callback11; + + case 12: + goto label_callback12; + + case 13: + params->param2 = 1; + goto label_callback13; + + case 14: + params->param3 = 1; + goto label_callback14; + + case 15: + params->param4 = 1; + goto label_callback15; + + case 16: + params->param5 = 1; + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Verges, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVerges); + + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarBaggage; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObject104, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + + ENTITY_PARAM(0, 3) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Verges, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) { + setCallback(1); + setup_function13(false); + } + +label_callback_1: + TIME_CHECK_CALLBACK_1(kTime1818900, params->param1, 2, setup_function9, "Tra2177"); + +label_callback_2: + if (params->param2 == kTimeInvalid || !getState()->time) + goto label_callback_6; + + if (getState()->time > kTime1836000) { + params->param2 = kTimeInvalid; + setCallback(3); + setup_function12(); + break; + } + + if (!getEntities()->isPlayerInCar(kCarRedSleeping) || !params->param2) { + params->param2 = getState()->time; + + if (!params->param2) { + setCallback(3); + setup_function12(); + break; + } + } + + if (params->param2 >= getState()->time) { +label_callback_6: + + if (ENTITY_PARAM(0, 3)) { + setCallback(7); + setup_function17(); + } + + break; + } + + params->param2 = kTimeInvalid; + setCallback(3); + setup_function12(); + break; + + case kActionOpenDoor: + setCallback(8); + setup_function13(savepoint.param.intValue < 106); + break; + + case kActionDefault: + getInventory()->setLocationAndProcess(kItem9, kObjectLocation1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 4: + setCallback(5); + setup_function15(kEntityCoudert, "TRA2100"); + break; + + case 5: + setCallback(6); + setup_function11(); + break; + + case 6: + goto label_callback_6; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Verges, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_function23(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVerges); + + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObject104, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 4) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(30, Verges, function30) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 2: + setCallback(3); + setup_function15(kEntityCoudert, (char *)¶ms->seq1); + break; + + case 3: + setCallback(4); + setup_function11(); + break; + + case 4: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(31, Verges, function31) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 2: + setCallback(3); + setup_function15(kEntityCoudert, "TRA3015"); + break; + + case 3: + setCallback(4); + setup_function11(); + break; + + case 4: + getProgress().field_48 = 1; + ENTITY_PARAM(0, 4) = 0; + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(32, Verges, function32) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK_3(kTime2263500, params->param1, 5, setup_function10, kCarRedSleeping, kPosition_9460, "TRA3006"); + break; + + case kActionDefault: + getObjects()->update(kObject104, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + + if (getEntities()->isInBaggageCar(kEntityPlayer) || getEntities()->isInKitchen(kEntityPlayer)) { + getAction()->playAnimation(getEntities()->isInBaggageCar(kEntityPlayer) ? kEventVergesBaggageCarOffLimits : kEventVergesCanIHelpYou); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarRestaurant, 65); + } + + getScenes()->loadSceneFromItemPosition(kItem9); + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_5900; + + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_8500; + getData()->location = kLocationOutsideCompartment; + getSound()->playSound(kEntityVerges, "TRA3004"); + + setCallback(2); + setup_draw("813DD"); + break; + + case 2: + if (!getSound()->isBuffered(kEntityVerges)) + getSound()->playSound(kEntityVerges, "TRA3004"); + + getEntities()->drawSequenceRight(kEntityVerges, "813DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVerges); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + setCallback(4); + setup_function10(kCarGreenSleeping, kPosition_540, "TRA3004"); + break; + + case 4: + getEntities()->clearSequences(kEntityVerges); + break; + + case 5: + setCallback(6); + setup_function11(); + break; + + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(33, Verges, function33) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_draw("813US"); + break; + + case 2: + getEntities()->drawSequenceRight(kEntityVerges, "813UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityVerges); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + getEntities()->clearSequences(kEntityVerges); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_5799; + + setCallback(getProgress().field_3C ? 4 : 5); + setup_playSound(getProgress().field_3C ? "ABB3035A" : "ABB3035"); + break; + + case 4: + setCallback(5); + setup_playSound("ABB3035"); + break; + + case 5: + getSavePoints()->push(kEntityVerges, kEntityAbbot, kAction192054567); + + setCallback(6); + setup_function9("Tra3010"); + break; + + case 6: + setup_function34(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(34, Verges, function34) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) { + setCallback(1); + setup_function13(false); + break; + } + +label_callback_1: + if (ENTITY_PARAM(0, 4)) { + setCallback(2); + setup_function31(); + break; + } + +label_callback_2: + if (ENTITY_PARAM(0, 3)) { + setCallback(3); + setup_function17(); + break; + } + +label_callback_3: + TIME_CHECK_CALLBACK_1(kTime1971000, params->param1, 4, setup_function9, "Tra3001"); + +label_callback_4: + TIME_CHECK_CALLBACK_1(kTime1998000, params->param2, 5, setup_function9, "Tra3010a"); + +label_callback_5: + TIME_CHECK_CALLBACK(kTime2016000, params->param3, 6, setup_function35); + +label_callback_6: + TIME_CHECK_CALLBACK_1(kTime2070000, params->param4, 7, setup_function9, "Tra3002"); + +label_callback_7: + TIME_CHECK_CALLBACK_1(kTime2142000, params->param5, 8, setup_function9, "Tra3003"); + +label_callback_8: + TIME_CHECK_CALLBACK_1(kTime2173500, params->param6, 9, setup_function30, "Tra3012"); + +label_callback_9: + TIME_CHECK_CALLBACK(kTime2218500, params->param7, 10, setup_function32); + break; + + case kActionOpenDoor: + setCallback(11); + setup_function13(savepoint.param.intValue < 106); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + + case 9: + goto label_callback_9; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(35, Verges, function35) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 2: + setCallback(3); + setup_function15(kEntityMertens, "Tra3011A"); + break; + + case 3: + getSavePoints()->push(kEntityVerges, kEntityCoudert, kAction188570113); + + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 4: + setCallback(5); + setup_function15(kEntityMertens, "Tra3011"); + break; + + case 5: + getSavePoints()->push(kEntityVerges, kEntityMertens, kAction188635520); + + setCallback(6); + setup_function11(); + break; + + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(36, Verges, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVerges); + + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarBaggage; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObject104, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityVerges, kObjectLocationNone, kCursorNormal, kCursorHand); + + ENTITY_PARAM(0, 3) = 0; + ENTITY_PARAM(0, 6) = 0; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(37, Verges, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInBaggageCarEntrance(kEntityPlayer)) { + setCallback(1); + setup_function13(false); + break; + } + +label_callback_1: + if (ENTITY_PARAM(0, 6)) { + if (ENTITY_PARAM(0, 3)) { + setCallback(2); + setup_function17(); + break; + } + +label_callback_2: + TIME_CHECK_CALLBACK_1(kTime2349000, params->param1, 3, setup_function9, "Tra1001"); + +label_callback_3: + TIME_CHECK_CALLBACK_1(kTime2378700, params->param2, 4, setup_function9, "Tra4001"); + +label_callback_4: + TIME_CHECK_CALLBACK_1(kTime2403000, params->param3, 5, setup_function9, "Tra1001A"); + +label_callback_5: + TIME_CHECK_CALLBACK_1(kTime2414700, params->param4, 6, setup_function9, "Tra4002"); + +label_callback_6: + TIME_CHECK_CALLBACK_1(kTime2484000, params->param5, 7, setup_function9, "Tra4003"); + +label_callback_7: + TIME_CHECK_CALLBACK_1(kTime2511000, params->param6, 8, setup_function9, "Tra4004"); + } + +label_callback_8: + TIME_CHECK_CALLBACK_1(kTime2538000, params->param7, 9, setup_function9, "Tra4005"); + + break; + + case kActionOpenDoor: + setCallback(10); + setup_function13(savepoint.param.intValue < 106); + break; + + case kActionDefault: + getData()->car = kCarBaggage; + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + + getInventory()->setLocationAndProcess(kItem9, kObjectLocation1); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + goto label_callback_1; + + case 2: + goto label_callback_2; + + case 3: + goto label_callback_3; + + case 4: + goto label_callback_4; + + case 5: + goto label_callback_5; + + case 6: + goto label_callback_6; + + case 7: + goto label_callback_7; + + case 8: + goto label_callback_8; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(38, Verges, function38) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->update(kObject104, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + getScenes()->loadSceneFromItemPosition(kItem9); + getEntities()->clearSequences(kEntityVerges); + + getData()->entityPosition = kPosition_6469; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->clearSequences(kEntityVerges); + setCallback(2); + setup_updateFromTime(1800); + break; + + case 2: + setCallback(3); + setup_function11(); + break; + + case 3: + setup_chapter4Handler(); + break; + } + break; + + case kAction125233040: + getData()->entityPosition = kPosition_5790; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_540); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(39, Verges, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVerges); + + getData()->entityPosition = kPosition_3650; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObject104, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + getObjects()->update(kObject105, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(40, Verges, chapter5Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getEntities()->isInSalon(kEntityPlayer) && !getSound()->isBuffered(kEntityVerges)) + getSound()->playSound(kEntityVerges, "WAT5000"); + break; + + case kActionOpenDoor: + if (getSound()->isBuffered(kEntityVerges)) + getSound()->processEntry(kEntityVerges); + + if (getSound()->isBuffered("MUS050")) + getSound()->processEntry("MUS050"); + + getObjects()->update(kObject65, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCathFreePassengers); + break; + + case kActionDefault: + getScenes()->loadSceneFromItemPosition(kItem9); + getObjects()->update(kObject65, kEntityVerges, kObjectLocation1, kCursorNormal, kCursorForward); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCathFreePassengers); + getSavePoints()->pushAll(kEntityVerges, kActionProceedChapter5); + getScenes()->loadSceneFromPosition(kCarRedSleeping, 40); + setup_function41(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(41, Verges, function41) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getObjects()->updateLocation2(kObjectRestaurantCar, kObjectLocation3); + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_9460; + getData()->location = kLocationInsideCompartment; + + setCallback(1); + setup_function10(kCarRedSleeping, kPosition_2000, "Tra5001"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getEntities()->drawSequenceLeft(kEntityVerges, "620E"); + // Fallback to next case + + case 2: + if (getSound()->isBuffered(kEntityVerges)) { + setCallback(2); + setup_updateFromTime(225); + } else { + setCallback(3); + setup_playSound("Con5001"); + } + break; + + case 3: + getSavePoints()->push(kEntityVerges, kEntityCoudert, kAction155991520); + + setCallback(4); + setup_updateEntity(kCarBaggageRear, kPosition_9460); + break; + + case 4: + setup_function42(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(42, Verges, function42) + if (savepoint.action == kActionDefault) + getEntities()->clearSequences(kEntityVerges); +} + + +////////////////////////////////////////////////////////////////////////// +// Private functions +////////////////////////////////////////////////////////////////////////// +void Verges::talk(const SavePoint &savepoint, const char *sound1, const char *sound2) { + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_function12(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_2000); + break; + + case 2: + setCallback(3); + setup_function15(kEntityCoudert, sound1); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_2000); + break; + + case 4: + setCallback(5); + setup_function15(kEntityMertens, sound2); + break; + + case 5: + setup_function11(); + break; + + case 6: + CALLBACK_ACTION(); + break; + } + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/verges.h b/engines/lastexpress/entities/verges.h new file mode 100644 index 0000000000..3162d4e0ea --- /dev/null +++ b/engines/lastexpress/entities/verges.h @@ -0,0 +1,182 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_VERGES_H +#define LASTEXPRESS_VERGES_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Verges : public Entity { +public: + Verges(LastExpressEngine *engine); + ~Verges() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Plays sound + * + * @param savepoint The savepoint + * - the sound filename + */ + DECLARE_FUNCTION_NOSETUP(playSound16) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION_1(function9, const char *soundName) + DECLARE_FUNCTION_3(function10, CarIndex car, EntityPosition entityPosition, const char *soundName) + DECLARE_FUNCTION(function11) + DECLARE_FUNCTION(function12) + DECLARE_FUNCTION_1(function13, bool) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + DECLARE_FUNCTION_2(function15, EntityIndex entity, const char *soundName) + DECLARE_FUNCTION_3(function16, EntityIndex entityIndex, const char *soundName1, const char *soundName2) + DECLARE_FUNCTION(function17) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + DECLARE_FUNCTION_NOSETUP(talkHarem) + DECLARE_FUNCTION(talkPassengerList) + DECLARE_FUNCTION(talkGendarmes) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + DECLARE_FUNCTION(policeGettingOffTrain) + DECLARE_FUNCTION(function25) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + DECLARE_FUNCTION_1(function30, const char *soundName) + DECLARE_FUNCTION(function31) + DECLARE_FUNCTION(function32) + DECLARE_FUNCTION(function33) + DECLARE_FUNCTION(function34) + DECLARE_FUNCTION(function35) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function38) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function41) + DECLARE_FUNCTION(function42) + +private: + void talk(const SavePoint &savepoint, const char* sound1, const char* sound2); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_VERGES_H diff --git a/engines/lastexpress/entities/vesna.cpp b/engines/lastexpress/entities/vesna.cpp new file mode 100644 index 0000000000..9e0ef09a08 --- /dev/null +++ b/engines/lastexpress/entities/vesna.cpp @@ -0,0 +1,1161 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/vesna.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/fight.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Vesna::Vesna(LastExpressEngine *engine) : Entity(engine, kEntityVesna) { + ADD_CALLBACK_FUNCTION(Vesna, reset); + ADD_CALLBACK_FUNCTION(Vesna, playSound); + ADD_CALLBACK_FUNCTION(Vesna, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Vesna, draw); + ADD_CALLBACK_FUNCTION(Vesna, updateEntity); + ADD_CALLBACK_FUNCTION(Vesna, updateFromTime); + ADD_CALLBACK_FUNCTION(Vesna, updateEntity2); + ADD_CALLBACK_FUNCTION(Vesna, callbackActionRestaurantOrSalon); + ADD_CALLBACK_FUNCTION(Vesna, callbackActionOnDirection); + ADD_CALLBACK_FUNCTION(Vesna, savegame); + ADD_CALLBACK_FUNCTION(Vesna, function11); + ADD_CALLBACK_FUNCTION(Vesna, chapter1); + ADD_CALLBACK_FUNCTION(Vesna, chapter1Handler); + ADD_CALLBACK_FUNCTION(Vesna, function14); + ADD_CALLBACK_FUNCTION(Vesna, function15); + ADD_CALLBACK_FUNCTION(Vesna, chapter2); + ADD_CALLBACK_FUNCTION(Vesna, chapter2Handler); + ADD_CALLBACK_FUNCTION(Vesna, function18); + ADD_CALLBACK_FUNCTION(Vesna, chapter3); + ADD_CALLBACK_FUNCTION(Vesna, chapter3Handler); + ADD_CALLBACK_FUNCTION(Vesna, function21); + ADD_CALLBACK_FUNCTION(Vesna, function22); + ADD_CALLBACK_FUNCTION(Vesna, function23); + ADD_CALLBACK_FUNCTION(Vesna, chapter4); + ADD_CALLBACK_FUNCTION(Vesna, function25); + ADD_CALLBACK_FUNCTION(Vesna, function26); + ADD_CALLBACK_FUNCTION(Vesna, function27); + ADD_CALLBACK_FUNCTION(Vesna, chapter5); + ADD_CALLBACK_FUNCTION(Vesna, chapter5Handler); + ADD_CALLBACK_FUNCTION(Vesna, function30); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Vesna, reset) + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(2, Vesna, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(3, Vesna, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(4, Vesna, draw) + Entity::draw(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(5, Vesna, updateEntity, CarIndex, EntityPosition) + if (savepoint.action == kActionExcuseMeCath) { + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT10150" : "CAT1015A"); + + return; + } + + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_I(6, Vesna, updateFromTime, uint32) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(7, Vesna, updateEntity2, CarIndex, EntityPosition) + switch (savepoint.action) { + default: + break; + + case kActionNone: + params->param3 = 0; + + if (getEntities()->isDistanceBetweenEntities(kEntityVesna, kEntityMilos, 500) + || (((getData()->direction == kDirectionUp && (getData()->car > getEntityData(kEntityMilos)->car)) || (getData()->car == getEntityData(kEntityMilos)->car && getData()->entityPosition > getEntityData(kEntityMilos)->entityPosition))) + || (((getData()->direction == kDirectionDown && (getData()->car < getEntityData(kEntityMilos)->car)) || (getData()->car == getEntityData(kEntityMilos)->car && getData()->entityPosition < getEntityData(kEntityMilos)->entityPosition)))) { + getData()->field_49B = 0; + params->param3 = 1; + } + + if (!params->param3) + getEntities()->updateEntity(kEntityVesna, (CarIndex)params->param1, (EntityPosition)params->param2); + break; + + case kActionDefault: + getEntities()->updateEntity(kEntityVesna, (CarIndex)params->param1, (EntityPosition)params->param2); + break; + + case kAction123668192: + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Vesna, callbackActionRestaurantOrSalon) + Entity::callbackActionRestaurantOrSalon(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Vesna, callbackActionOnDirection) + Entity::callbackActionOnDirection(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(10, Vesna, savegame, SavegameType, uint32) + Entity::savegame(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Vesna, function11) + // Expose parameters as IIIS and ignore the default exposed parameters + EntityData::EntityParametersIIIS *parameters = (EntityData::EntityParametersIIIS*)_data->getCurrentParameters(); + + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (parameters->param3) { + UPDATE_PARAM(parameters->param7, getState()->timeTicks, 75); + + parameters->param2 = 1; + parameters->param3 = 0; + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + parameters->param7 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (parameters->param3) { + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorNormal, kCursorNormal); + + setCallback(4); + setup_playSound(getSound()->wrongDoorCath()); + break; + } + + parameters->param1++; + switch (parameters->param1) { + default: + strcpy((char *)¶meters->seq, "VES1015C"); + parameters->param1 = 0; + break; + + case 1: + strcpy((char *)¶meters->seq, "VES1015A"); + break; + + case 2: + strcpy((char *)¶meters->seq, "VES1015B"); + break; + } + + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 2 : 1); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionDrawScene: + if (parameters->param2 || parameters->param3) { + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation1, kCursorHandKnock, kCursorHand); + + parameters->param2 = 0; + parameters->param3 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound((char *)¶meters->seq); + break; + + case 3: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorTalk, kCursorNormal); + parameters->param3 = 1; + break; + + case 4: + parameters->param2 = 1; + parameters->param3 = 0; + break; + } + break; + + case kAction55996766: + case kAction101687594: + CALLBACK_ACTION(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Vesna, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getSavePoints()->addData(kEntityVesna, kAction124190740, 0); + + getData()->entityPosition = kPosition_4689; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Vesna, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + getData()->entityPosition = getEntityData(kEntityMilos)->entityPosition; + getData()->location = getEntityData(kEntityMilos)->location; + break; + + case kActionCallback: + if (getCallback() == 1) { + getEntities()->clearSequences(kEntityVesna); + setup_function14(); + } + break; + + case kAction204832737: + setCallback(1); + setup_updateEntity2(kCarRedSleeping, kPosition_3050); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Vesna, function14) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + break; + + case kAction190412928: + setCallback(1); + setup_function11(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Vesna, function15) + if (savepoint.action == kActionDefault) { + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + + getEntities()->clearSequences(kEntityVesna); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Vesna, chapter2) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter2Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVesna); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Vesna, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kAction135024800: + setCallback(2); + setup_function18(); + break; + + case kAction137165825: + setCallback(1); + setup_function11(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Vesna, function18) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("610Bg", kObjectCompartmentG); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("808US"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityVesna, "808UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(5); + setup_callbackActionOnDirection(); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityVesna); + + setCallback(6); + setup_updateFromTime(4500); + break; + + case 6: + setCallback(7); + setup_callbackActionRestaurantOrSalon(); + break; + + case 7: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(8); + setup_draw("808DD"); + break; + + case 8: + getEntities()->drawSequenceRight(kEntityVesna, "808DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(9); + setup_callbackActionOnDirection(); + break; + + case 9: + setCallback(10); + setup_updateEntity(kCarRedSleeping, kPosition_3050); + break; + + case 10: + setCallback(11); + setup_enterExitCompartment("610Ag", kObjectCompartmentG); + break; + + case 11: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityVesna); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Vesna, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVesna); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Vesna, chapter3Handler) + EntityData::EntityParametersIIIS *parameters = (EntityData::EntityParametersIIIS*)_data->getCurrentParameters(); + + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getProgress().field_54 && parameters->param7 != kTimeInvalid) { + if (getState()->time > kTime2250000) { + parameters->param7 = kTimeInvalid; + setup_function22(); + break; + } + + if (!getEntities()->isPlayerInCar(kCarRedSleeping) || !parameters->param7) + parameters->param7 = getState()->time; + + if (parameters->param7 < getState()->time) { + parameters->param7 = kTimeInvalid; + setup_function22(); + break; + } + } + + if (parameters->param2) { + UPDATE_PARAM(parameters->param8, getState()->timeTicks, 75); + + parameters->param1 = 1; + parameters->param2 = 0; + + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation1, kCursorNormal, kCursorNormal); + } + + parameters->param8 = 0; + break; + + case kActionKnock: + case kActionOpenDoor: + if (parameters->param2) { + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorNormal, kCursorNormal); + + setCallback(4); + setup_playSound(getSound()->wrongDoorCath()); + break; + } + + ++parameters->param3; + + switch (parameters->param3) { + default: + break; + + case 1: + strcpy((char *)¶meters->seq, "VES1015A"); + break; + + case 2: + strcpy((char *)¶meters->seq, "VES1015B"); + break; + + case 3: + strcpy((char *)¶meters->seq, "VES1015C"); + parameters->param3 = 0; + break; + } + + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorNormal, kCursorNormal); + + setCallback(savepoint.action == kActionKnock ? 2 : 1); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + getEntities()->clearSequences(kEntityVesna); + break; + + case kActionDrawScene: + if (parameters->param1 || parameters->param2) { + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation1, kCursorHandKnock, kCursorHand); + parameters->param1 = 0; + parameters->param2 = 0; + } + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound((char *)¶meters->seq); + break; + + case 3: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorTalk, kCursorNormal); + parameters->param2 = 1; + break; + + case 4: + parameters->param1 = 1; + parameters->param2 = 0; + break; + } + break; + + case kAction137165825: + setCallback(5); + setup_function11(); + break; + + case kAction155913424: + setCallback(6); + setup_function21(); + break; + + case kAction203663744: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Vesna, function21) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_enterExitCompartment("610Bg", kObjectCompartmentG); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("808US"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityVesna, "808UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(5); + setup_callbackActionOnDirection(); + break; + + case 5: + getEntities()->clearSequences(kEntityVesna); + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationInsideCompartment; + + setCallback(6); + setup_updateFromTime(4500); + break; + + case 6: + setCallback(7); + setup_callbackActionRestaurantOrSalon(); + break; + + case 7: + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(8); + setup_draw("808DD"); + break; + + case 8: + getEntities()->drawSequenceRight(kEntityVesna, "808DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(9); + setup_callbackActionOnDirection(); + break; + + case 9: + setCallback(10); + setup_updateEntity(kCarRedSleeping, kPosition_3050); + break; + + case 10: + setCallback(11); + setup_enterExitCompartment("610Ag", kObjectCompartmentG); /* BUG the original engine passes 3050 here */ + break; + + case 11: + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityVesna); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(22, Vesna, function22) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getSavePoints()->push(kEntityVesna, kEntityMilos, kAction259125998); + + setCallback(1); + setup_enterExitCompartment("610Bg", kObjectCompartmentG); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("808US"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityVesna, "808UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(5); + setup_callbackActionOnDirection(); + break; + + case 5: + getEntities()->clearSequences(kEntityVesna); + getData()->car = kCarBaggage; + getSavePoints()->push(kEntityVesna, kEntityAnna, kAction235856512); + break; + + case 6: + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(7); + setup_draw("808DD"); + break; + + case 7: + getEntities()->drawSequenceRight(kEntityVesna, "808DS"); + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(8); + setup_callbackActionOnDirection(); + break; + + case 8: + setCallback(9); + setup_updateEntity(kCarRedSleeping, kPosition_3050); + break; + + case 9: + setCallback(10); + setup_enterExitCompartment("610Ag", kObjectCompartmentG); /* BUG the original engine passes 3050 here */ + break; + + case 10: + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityVesna); + + setup_function23(); + break; + } + break; + + case kAction189299008: + setCallback(6); + setup_callbackActionRestaurantOrSalon(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(23, Vesna, function23) + switch (savepoint.action) { + default: + break; + + case kActionKnock: + case kActionOpenDoor: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorNormal, kCursorNormal); + setCallback(savepoint.action == kActionKnock ? 1 : 2); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + break; + + case kActionDefault: + getData()->car = kCarRedSleeping; + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + setCallback(3); + setup_playSound("VES1015A"); + break; + + case 3: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + } + break; + + case kAction203663744: + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(24, Vesna, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setCallback(1); + setup_function11(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVesna); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + + getObjects()->update(kObjectCompartmentG, kEntityVesna, kObjectLocation3, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + if (getCallback() == 1) + setup_function25(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(25, Vesna, function25) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (getState()->time > kTime2428200 && !params->param1) { + params->param1 = 1; + setup_function26(); + } + break; + + case kActionDefault: + getSavePoints()->push(kEntityVesna, kEntityMilos, kAction135600432); + + setCallback(1); + setup_enterExitCompartment("610BG", kObjectCompartmentG); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->location = kLocationOutsideCompartment; + if (getData()->entityPosition < kPosition_2087) + getData()->entityPosition = kPosition_2088; + + setCallback(2); + setup_updateEntity(kCarRestaurant, kPosition_850); + break; + + case 2: + setCallback(3); + setup_callbackActionRestaurantOrSalon(); + break; + + case 3: + getData()->entityPosition = kPosition_1540; + getData()->location = kLocationOutsideCompartment; + + setCallback(4); + setup_draw("808US"); + break; + + case 4: + getEntities()->drawSequenceRight(kEntityVesna, "808UD"); + if (getEntities()->isInSalon(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(5); + setup_callbackActionOnDirection(); + break; + + case 5: + getEntities()->clearSequences(kEntityVesna); + getData()->entityPosition = kPosition_5900; + getData()->location = kLocationInsideCompartment; + + // Original game calls clearSequences a second time + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(26, Vesna, function26) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + setCallback(1); + setup_callbackActionRestaurantOrSalon(); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_5800; + getData()->location = kLocationOutsideCompartment; + + setCallback(2); + setup_draw("808DD"); + break; + + case 2: + getEntities()->drawSequenceRight(kEntityVesna, "808DS"); + + if (getEntities()->isInRestaurant(kEntityPlayer)) + getEntities()->updateFrame(kEntityVesna); + + setCallback(3); + setup_callbackActionOnDirection(); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarRedSleeping, kPosition_3050); + break; + + case 4: + setCallback(5); + setup_enterExitCompartment("610AG", kObjectCompartmentG); + break; + + case 5: + setup_function27(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(27, Vesna, function27) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityVesna); + getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(28, Vesna, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityVesna); + + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(29, Vesna, chapter5Handler) + switch (savepoint.action) { + default: + break; + + case kActionOpenDoor: + setCallback(1); + + getData()->currentCall++; + setup_savegame(kSavegameTypeEvent, kEventCathVesnaRestaurantKilled); + break; + + case kActionDefault: + getObjects()->update(kObject64, kEntityVesna, kObjectLocationNone, kCursorNormal, kCursorForward); + break; + + case kActionCallback: + if (getCallback() == 1) { + getAction()->playAnimation(kEventCathVesnaRestaurantKilled); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + } + break; + + case kAction134427424: + getObjects()->update(kObject64, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); + setup_function30(); + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(30, Vesna, function30) + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (!params->param1) { + UPDATE_PARAM_PROC(params->param3, getState()->timeTicks, 120) + getSound()->playSound(kEntityVesna, "Ves50001", SoundManager::kFlagDefault); + params->param1 = 1; + UPDATE_PARAM_PROC_END + } + + UPDATE_PARAM(params->param4, getState()->timeTicks, 180); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventCathVesnaTrainTopKilled); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + case 2: + getAction()->playAnimation(kEventCathVesnaTrainTopKilled); + getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); + break; + + case 3: + getAction()->playAnimation(kEventCathVesnaTrainTopFight); + + setCallback(4); + setup_savegame(kSavegameTypeTime, kTimeNone); + break; + + case 4: + params->param2 = getFight()->setup(kFightVesna); + + if (params->param2) { + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, params->param2 != Fight::kFightEndExit); + } else { + getSound()->playSound(kEntityPlayer, "TUNNEL"); + + getState()->time += 1800; + + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventCathVesnaTrainTopWin); + } + break; + + case 5: + getAction()->playAnimation(kEventCathVesnaTrainTopWin); + getScenes()->loadSceneFromPosition(kCarRestaurant, 11); + + setup_nullfunction(); + break; + } + break; + + case kAction167992577: + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventCathVesnaTrainTopFight); + break; + + case kAction202884544: + if (params->param1) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventCathVesnaTrainTopKilled); + } else { + getSound()->playSound(kEntityVesna, "Ves5001", SoundManager::kFlagDefault); + params->param1 = 1; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(31, Vesna) + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/vesna.h b/engines/lastexpress/entities/vesna.h new file mode 100644 index 0000000000..4a0a8550b2 --- /dev/null +++ b/engines/lastexpress/entities/vesna.h @@ -0,0 +1,176 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_VESNA_H +#define LASTEXPRESS_VESNA_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Vesna : public Entity { +public: + Vesna(LastExpressEngine *engine); + ~Vesna() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + + /** + * Draws the entity + * + * @param sequence The sequence to draw + */ + DECLARE_FUNCTION_1(draw, const char* sequence) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + /** + * Updates parameter 2 using time value + * + * @param time The time to add + */ + DECLARE_FUNCTION_1(updateFromTime, uint32 time) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity2, CarIndex car, EntityPosition entityPosition) + + /** + * Process callback action when somebody is standing in the restaurant or salon. + */ + DECLARE_FUNCTION(callbackActionRestaurantOrSalon) + + /** + * Process callback action when the entity direction is not kDirectionRight + */ + DECLARE_FUNCTION(callbackActionOnDirection) + + /** + * Saves the game + * + * @param savegameType The type of the savegame + * @param param The param for the savegame (EventIndex or TimeValue) + */ + DECLARE_FUNCTION_2(savegame, SavegameType savegameType, uint32 param) + + DECLARE_FUNCTION(function11) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function14) + DECLARE_FUNCTION(function15) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + DECLARE_FUNCTION(function18) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + DECLARE_FUNCTION(function21) + DECLARE_FUNCTION(function22) + DECLARE_FUNCTION(function23) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + DECLARE_FUNCTION(function25) + DECLARE_FUNCTION(function26) + DECLARE_FUNCTION(function27) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function30) + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_VESNA_H diff --git a/engines/lastexpress/entities/yasmin.cpp b/engines/lastexpress/entities/yasmin.cpp new file mode 100644 index 0000000000..fe7c7fb2bf --- /dev/null +++ b/engines/lastexpress/entities/yasmin.cpp @@ -0,0 +1,490 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lastexpress/entities/yasmin.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/helpers.h" + +namespace LastExpress { + +Yasmin::Yasmin(LastExpressEngine *engine) : Entity(engine, kEntityYasmin) { + ADD_CALLBACK_FUNCTION(Yasmin, reset); + ADD_CALLBACK_FUNCTION(Yasmin, enterExitCompartment); + ADD_CALLBACK_FUNCTION(Yasmin, playSound); + ADD_CALLBACK_FUNCTION(Yasmin, updateFromTime); + ADD_CALLBACK_FUNCTION(Yasmin, updateEntity); + ADD_CALLBACK_FUNCTION(Yasmin, function6); + ADD_CALLBACK_FUNCTION(Yasmin, function7); + ADD_CALLBACK_FUNCTION(Yasmin, chapter1); + ADD_CALLBACK_FUNCTION(Yasmin, chapter1Handler); + ADD_CALLBACK_FUNCTION(Yasmin, function10); + ADD_CALLBACK_FUNCTION(Yasmin, chapter2); + ADD_CALLBACK_FUNCTION(Yasmin, chapter2Handler); + ADD_CALLBACK_FUNCTION(Yasmin, chapter3); + ADD_CALLBACK_FUNCTION(Yasmin, chapter3Handler); + ADD_CALLBACK_FUNCTION(Yasmin, chapter4); + ADD_CALLBACK_FUNCTION(Yasmin, chapter4Handler); + ADD_CALLBACK_FUNCTION(Yasmin, function17); + ADD_CALLBACK_FUNCTION(Yasmin, chapter5); + ADD_CALLBACK_FUNCTION(Yasmin, chapter5Handler); + ADD_CALLBACK_FUNCTION(Yasmin, function20); + ADD_CALLBACK_FUNCTION(Yasmin, function21); + ADD_NULL_FUNCTION(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(1, Yasmin, reset) + switch (savepoint.action) { + default: + break; + + case kActionExcuseMeCath: + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntityYasmin); + break; + } + + // Process default actions + Entity::reset(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_SI(2, Yasmin, enterExitCompartment, ObjectIndex) + Entity::enterExitCompartment(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_S(3, Yasmin, playSound) + Entity::playSound(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_NOSETUP(4, Yasmin, updateFromTime) + Entity::updateFromTime(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION_II(5, Yasmin, updateEntity, CarIndex, EntityPosition) + Entity::updateEntity(savepoint, true); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(6, Yasmin, function6) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_enterExitCompartment("615Be", kObjectCompartment5); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_3050); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("615Ag", kObjectCompartment7); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityYasmin); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(7, Yasmin, function7) + switch (savepoint.action) { + default: + break; + + case kActionDefault: + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationOutsideCompartment; + + setCallback(1); + setup_enterExitCompartment("615Bg", kObjectCompartment7); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_updateEntity(kCarGreenSleeping, kPosition_4840); + break; + + case 2: + setCallback(3); + setup_enterExitCompartment("615Ae", kObjectCompartment5); + break; + + case 3: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityYasmin); + + CALLBACK_ACTION(); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(8, Yasmin, chapter1) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CHAPTER1(setup_chapter1Handler); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_4840; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(9, Yasmin, chapter1Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime1093500, params->param1, 1, setup_function6); + TIME_CHECK_CALLBACK(kTime1161000, params->param2, 3, setup_function7); + TIME_CHECK_PLAYSOUND_UPDATEPOSITION(kTime1162800, params->param3, 4, "Har1102", kPosition_4070); + TIME_CHECK_PLAYSOUND(kTime1165500, params->param4, 5, "Har1104"); + TIME_CHECK_PLAYSOUND(kTime1174500, params->param5, 6, "Har1106"); + TIME_CHECK_CALLBACK(kTime1183500, params->param6, 7, setup_function6); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_2740; + setCallback(2); + setup_playSound("Har1102"); + break; + + case 2: + TIME_CHECK_CALLBACK(kTime1161000, params->param2, 3, setup_function7); + // Fallback to case 3 + + case 3: + TIME_CHECK_PLAYSOUND_UPDATEPOSITION(kTime1162800, params->param3, 4, "Har1102", kPosition_4070); + // Fallback to case 4 + + case 4: + TIME_CHECK_PLAYSOUND(kTime1165500, params->param4, 5, "Har1104"); + // Fallback to case 5 + + case 5: + TIME_CHECK_PLAYSOUND(kTime1174500, params->param5, 6, "Har1106"); + // Fallback to case 6 + + case 6: + TIME_CHECK_CALLBACK(kTime1183500, params->param6, 7, setup_function6); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(10, Yasmin, function10) + if (savepoint.action == kActionDefault) { + getObjects()->update(kObjectCompartment7, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + + getEntities()->clearSequences(kEntityYasmin); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(11, Yasmin, chapter2) + if (savepoint.action == kActionDefault) { + getEntities()->clearSequences(kEntityYasmin); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + + setup_chapter2Handler(); + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(12, Yasmin, chapter2Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime1759500, params->param1, 1, setup_function7); + + if (getState()->time > kTime1800000 && !params->param2) { + params->param2 = 1; + getData()->entityPosition = kPosition_4070; + + getSavePoints()->push(kEntityYasmin, kEntityTrain, kAction191070912, kPosition_4070); + } + break; + + case kActionCallback: + + if (getCallback() != 1) + break; + + if (getState()->time > kTime1800000 && !params->param2) { + params->param2 = 1; + getData()->entityPosition = kPosition_4070; + + getSavePoints()->push(kEntityYasmin, kEntityTrain, kAction191070912, kPosition_4070); + } + + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(13, Yasmin, chapter3) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter3Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityYasmin); + + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(14, Yasmin, chapter3Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime2062800, params->param1, 1, setup_function6); + TIME_CHECK_CALLBACK(kTime2106000, params->param2, 2, setup_function7); + TIME_CHECK_CALLBACK(kTime2160000, params->param3, 3, setup_function6); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + TIME_CHECK_CALLBACK(kTime2106000, params->param2, 2, setup_function7); + // Fallback to case 2 + + case 2: + TIME_CHECK_CALLBACK(kTime2160000, params->param3, 3, setup_function6); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(15, Yasmin, chapter4) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter4Handler(); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_3050; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarGreenSleeping; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(16, Yasmin, chapter4Handler) + switch (savepoint.action) { + default: + break; + + case kActionNone: + TIME_CHECK_CALLBACK(kTime2457000, params->param1, 1, setup_function7); + TIME_CHECK_CALLBACK(kTime2479500, params->param2, 3, setup_function6); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getData()->entityPosition = kPosition_4070; + setCallback(2); + setup_playSound("Har1110"); + break; + + case 2: + TIME_CHECK_CALLBACK(kTime2479500, params->param2, 3, setup_function6); + break; + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(17, Yasmin, function17) + // Same as existing function 10 ? + function10(savepoint); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(18, Yasmin, chapter5) + switch (savepoint.action) { + default: + break; + + case kActionNone: + setup_chapter5Handler(); + break; + + case kActionDefault: + getEntities()->clearSequences(kEntityYasmin); + + getData()->entityPosition = kPosition_3969; + getData()->location = kLocationInsideCompartment; + getData()->car = kCarRestaurant; + getData()->clothes = kClothesDefault; + getData()->inventoryItem = kItemNone; + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(19, Yasmin, chapter5Handler) + if (savepoint.action == kActionProceedChapter5) + setup_function20(); +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(20, Yasmin, function20) + switch (savepoint.action) { + default: + break; + + case kActionNone: + UPDATE_PARAM(params->param1, getState()->time, 2700); + setup_function21(); + break; + + case kActionDefault: + getData()->entityPosition = kPosition_2500; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarGreenSleeping; + break; + + case kActionDrawScene: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { + setup_function21(); + } + break; + } +} + +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_FUNCTION(21, Yasmin, function21) + switch (savepoint.action) { + default: + break; + + case kActionNone: + case kActionDefault: + if (getEntities()->updateEntity(kEntityYasmin, (CarIndex)params->param1, (EntityPosition)params->param2)) + CALLBACK_ACTION(); + break; + + case kActionExcuseMeCath: + getSound()->excuseMeCath(); + break; + + case kActionExcuseMe: + getSound()->excuseMe(kEntityYasmin); + break; + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/entities/yasmin.h b/engines/lastexpress/entities/yasmin.h new file mode 100644 index 0000000000..125b11d566 --- /dev/null +++ b/engines/lastexpress/entities/yasmin.h @@ -0,0 +1,142 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_YASMIN_H +#define LASTEXPRESS_YASMIN_H + +#include "lastexpress/entities/entity.h" +#include "lastexpress/entities/entity_intern.h" + +namespace LastExpress { + +class LastExpressEngine; + +class Yasmin : public Entity { +public: + Yasmin(LastExpressEngine *engine); + ~Yasmin() {}; + + /** + * Resets the entity + */ + DECLARE_FUNCTION(reset) + + /** + * Handles entering/exiting a compartment. + * + * @param sequence The sequence to draw + * @param compartment The compartment + */ + DECLARE_FUNCTION_2(enterExitCompartment, const char* sequence, ObjectIndex compartment) + + /** + * Plays sound + * + * @param filename The sound filename + */ + DECLARE_FUNCTION_1(playSound, const char* filename) + + /** + * Updates parameter 2 using time value + * + * @param savepoint The savepoint + * - Time to add + */ + DECLARE_FUNCTION_NOSETUP(updateFromTime) + + /** + * Updates the entity + * + * @param car The car + * @param entityPosition The entity position + */ + DECLARE_FUNCTION_2(updateEntity, CarIndex car, EntityPosition entityPosition) + + DECLARE_FUNCTION(function6) + DECLARE_FUNCTION(function7) + + /** + * Setup Chapter 1 + */ + DECLARE_FUNCTION(chapter1) + + /** + * Handle Chapter 1 events + */ + DECLARE_FUNCTION(chapter1Handler) + + DECLARE_FUNCTION(function10) + + /** + * Setup Chapter 2 + */ + DECLARE_FUNCTION(chapter2) + + /** + * Handle Chapter 2 events + */ + DECLARE_FUNCTION(chapter2Handler) + + /** + * Setup Chapter 3 + */ + DECLARE_FUNCTION(chapter3) + + /** + * Handle Chapter 3 events + */ + DECLARE_FUNCTION(chapter3Handler) + + /** + * Setup Chapter 4 + */ + DECLARE_FUNCTION(chapter4) + + /** + * Handle Chapter 4 events + */ + DECLARE_FUNCTION(chapter4Handler) + + DECLARE_FUNCTION(function17) + + /** + * Setup Chapter 5 + */ + DECLARE_FUNCTION(chapter5) + + /** + * Handle Chapter 5 events + */ + DECLARE_FUNCTION(chapter5Handler) + + DECLARE_FUNCTION(function20) + DECLARE_FUNCTION(function21) + + DECLARE_NULL_FUNCTION() +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_YASMIN_H |