diff options
author | Evgeny Grechnikov | 2018-08-25 15:11:24 +0300 |
---|---|---|
committer | Eugene Sandulenko | 2018-08-26 12:09:43 +0200 |
commit | f771fa40ad474d78d32ce5bff67afc937547e5de (patch) | |
tree | 483ee750c81169142fc58a68e87d5a321a4a96f3 /engines/lastexpress | |
parent | f3cb1fcd84d7ca1dd25b7adb4b54f08c535008ac (diff) | |
download | scummvm-rg350-f771fa40ad474d78d32ce5bff67afc937547e5de.tar.gz scummvm-rg350-f771fa40ad474d78d32ce5bff67afc937547e5de.tar.bz2 scummvm-rg350-f771fa40ad474d78d32ce5bff67afc937547e5de.zip |
LASTEXPRESS: multiple fixes in NPC logic
Checked the logic against the original game
(to be precise, DOS English version from GOG, although I think
AI logic has no significant differences with other versions).
Fixed a *lot* of errors with varying visibility for the user.
Also, save+exit+load sometimes resulted in memory corruption like
((EntityParametersSSII*)(new EntityParametersIIII))->param8 = 0;
load operation did not restore the correct type of NPC logic context,
the default one was used (which also has the smallest sizeof).
Should be fixed now. Save+load is still unusable because it locks
everybody waiting for kActionEndSound (the sound state is not restored),
but, at least, it should not corrupt the memory. Hopefully.
Diffstat (limited to 'engines/lastexpress')
47 files changed, 1312 insertions, 1032 deletions
diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index a6cecc7408..dec57a4c39 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -487,10 +487,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { // Handle right-click to interrupt sequence Common::Event ev; - if (!_engine->getEventManager()->pollEvent(ev)) - break; - - if (ev.type == Common::EVENT_RBUTTONUP) + if (_engine->getEventManager()->pollEvent(ev) && ev.type == Common::EVENT_RBUTTONUP) break; _engine->_system->delayMillis(175); diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp index 1581916e07..99b9ee3bc2 100644 --- a/engines/lastexpress/entities/abbot.cpp +++ b/engines/lastexpress/entities/abbot.cpp @@ -41,18 +41,18 @@ 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_S(Abbot, draw); + ADD_CALLBACK_FUNCTION_SI(Abbot, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(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_SSI(Abbot, draw2); + ADD_CALLBACK_FUNCTION_I(Abbot, updateFromTime); + ADD_CALLBACK_FUNCTION_I(Abbot, updateFromTicks); + ADD_CALLBACK_FUNCTION_S(Abbot, playSound); + ADD_CALLBACK_FUNCTION_II(Abbot, savegame); + ADD_CALLBACK_FUNCTION_II(Abbot, updateEntity); + ADD_CALLBACK_FUNCTION_SIIS(Abbot, callSavepoint); + ADD_CALLBACK_FUNCTION_SII(Abbot, updatePosition); ADD_CALLBACK_FUNCTION(Abbot, callbackActionRestaurantOrSalon); ADD_CALLBACK_FUNCTION(Abbot, chapter1); ADD_CALLBACK_FUNCTION(Abbot, chapter2); @@ -79,7 +79,7 @@ Abbot::Abbot(LastExpressEngine *engine) : Entity(engine, kEntityAbbot) { ADD_CALLBACK_FUNCTION(Abbot, goCompartment4); ADD_CALLBACK_FUNCTION(Abbot, inCompartment4); ADD_CALLBACK_FUNCTION(Abbot, chapter4); - ADD_CALLBACK_FUNCTION(Abbot, doWalkSearchingForCath); + ADD_CALLBACK_FUNCTION_II(Abbot, doWalkSearchingForCath); ADD_CALLBACK_FUNCTION(Abbot, chapter4Handler); ADD_CALLBACK_FUNCTION(Abbot, leaveDinner); ADD_CALLBACK_FUNCTION(Abbot, inCompartment); @@ -616,7 +616,7 @@ IMPLEMENT_FUNCTION(26, Abbot, inSalon1) break; case kActionNone: - if (!Entity::updateParameter(params->param2, getState()->time, 4500)) + if (!params->param1 || !Entity::updateParameterCheck(params->param2, getState()->time, 4500)) break; if (getEntities()->isSomebodyInsideRestaurantOrSalon()) @@ -691,7 +691,7 @@ IMPLEMENT_FUNCTION(28, Abbot, openCompartment2) break; case kActionNone: - Entity::timeCheckCallback(kTime2052000, params->param1, 1, WRAP_SETUP_FUNCTION(Abbot, setup_goWander)); + Entity::timeCheckCallback(kTime2052000, params->param1, 2, WRAP_SETUP_FUNCTION(Abbot, setup_goWander)); break; case kActionDefault: @@ -699,7 +699,7 @@ IMPLEMENT_FUNCTION(28, Abbot, openCompartment2) getEntities()->drawSequenceLeft(kEntityAbbot, "508A"); setCallback(1); - setup_playSound("abb3013"); + setup_playSound("Abb3013"); break; case kActionCallback: @@ -749,6 +749,9 @@ IMPLEMENT_FUNCTION(29, Abbot, goWander) break; case 4: + // compare with callback 2. + // This is taken from the original game as is, + // but do we really want real-time 30s in case 2 but simulated-time 15s (aka real-time 5s) here? setCallback(5); setup_updateFromTime(225); break; @@ -962,7 +965,7 @@ IMPLEMENT_FUNCTION(32, Abbot, goCompartment3) case 1: getObjects()->update(kObjectCompartmentC, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); - setCallback(1); + setCallback(2); setup_enterExitCompartment("617Ac", kObjectCompartmentC); break; @@ -1355,7 +1358,7 @@ IMPLEMENT_FUNCTION(42, Abbot, leaveDinner) case kActionDefault: getData()->location = kLocationOutsideCompartment; - getEntities()->updatePositionExit(kEntityAbbot, kCarRestaurant, 67); + getEntities()->updatePositionEnter(kEntityAbbot, kCarRestaurant, 67); setCallback(1); setup_callSavepoint("029F", kEntityTables4, kActionDrawTablesWithChairs, "029G"); @@ -1406,8 +1409,8 @@ IMPLEMENT_FUNCTION(43, Abbot, inCompartment) break; case kActionNone: - if (params->param1 && params->param4 != kTimeInvalid && params->param2 < getState()->time) { - if (getState()->time < kTime2452500) { + if (params->param1 && params->param4 != kTimeInvalid) { + if (getState()->time > kTime2452500) { params->param4 = kTimeInvalid; setCallback(1); @@ -1415,7 +1418,7 @@ IMPLEMENT_FUNCTION(43, Abbot, inCompartment) break; } else { if (!getEntities()->isDistanceBetweenEntities(kEntityAbbot, kEntityPlayer, 1000) || getSoundQueue()->isBuffered(kEntityBoutarel) || !params->param4) - params->param4 = (uint)getState()->time + 450; + params->param4 = (uint)getState()->time; if (params->param4 < getState()->time) { params->param4 = kTimeInvalid; @@ -1655,7 +1658,8 @@ IMPLEMENT_FUNCTION(48, Abbot, afterBomb) getData()->inventoryItem = kItemNone; setCallback(4); - setup_updatePosition("126C", kCarRedSleeping, 52); + setup_updatePosition("126C", kCarRestaurant, 52); + break; } Entity::timeCheckCallbackInventory(kTime2533500, params->param2, 5, WRAP_SETUP_FUNCTION(Abbot, setup_callbackActionRestaurantOrSalon)); @@ -1771,6 +1775,9 @@ IMPLEMENT_FUNCTION(49, Abbot, catchCath) getSavePoints()->push(kEntityAbbot, kEntityTatiana, kAction238790488); getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventAbbotWrongCompartment); break; case kActionDefault: @@ -1791,7 +1798,7 @@ IMPLEMENT_FUNCTION(49, Abbot, catchCath) break; case 1: - getAction()->playAnimation(getObjects()->get(kObjectCompartment2).model < kObjectModel2 ? kEventAbbotWrongCompartmentBed : kEventAbbotWrongCompartment); + getAction()->playAnimation(getObjects()->get(kObjectCompartment2).model == kObjectModel1 ? kEventAbbotWrongCompartmentBed : kEventAbbotWrongCompartment); getEntities()->updateEntity(kEntityAbbot, kCarRedSleeping, kPosition_6470); getSound()->playSound(kEntityPlayer, "LIB015"); getScenes()->loadSceneFromObject(kObjectCompartment2, true); diff --git a/engines/lastexpress/entities/alexei.cpp b/engines/lastexpress/entities/alexei.cpp index 5ea3ff4898..89027c2d2f 100644 --- a/engines/lastexpress/entities/alexei.cpp +++ b/engines/lastexpress/entities/alexei.cpp @@ -37,21 +37,21 @@ 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_S(Alexei, playSound); + ADD_CALLBACK_FUNCTION_I(Alexei, updateFromTime); + ADD_CALLBACK_FUNCTION_S(Alexei, draw); + ADD_CALLBACK_FUNCTION_SII(Alexei, updatePosition); + ADD_CALLBACK_FUNCTION_SI(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_SIIS(Alexei, callSavepoint); + ADD_CALLBACK_FUNCTION_II(Alexei, savegame); + ADD_CALLBACK_FUNCTION_II(Alexei, updateEntity); + ADD_CALLBACK_FUNCTION_SSI(Alexei, draw2); ADD_CALLBACK_FUNCTION(Alexei, callbackActionRestaurantOrSalon); ADD_CALLBACK_FUNCTION(Alexei, enterComparment); ADD_CALLBACK_FUNCTION(Alexei, exitCompartment); ADD_CALLBACK_FUNCTION(Alexei, pacingAtWindow); - ADD_CALLBACK_FUNCTION(Alexei, compartmentLogic); + ADD_CALLBACK_FUNCTION_IS(Alexei, compartmentLogic); ADD_CALLBACK_FUNCTION(Alexei, chapter1); ADD_CALLBACK_FUNCTION(Alexei, atDinner); ADD_CALLBACK_FUNCTION(Alexei, returnCompartment); @@ -97,8 +97,8 @@ IMPLEMENT_FUNCTION_S(2, Alexei, playSound) IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// -IMPLEMENT_FUNCTION_I(3, Alexei, updateFromTicks, uint32) - Entity::updateFromTicks(savepoint); +IMPLEMENT_FUNCTION_I(3, Alexei, updateFromTime, uint32) + Entity::updateFromTime(savepoint); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -394,7 +394,7 @@ IMPLEMENT_FUNCTION_IS(16, Alexei, compartmentLogic, TimeValue) case 7: setCallback(8); - setup_updateFromTicks(300); + setup_updateFromTime(300); break; case 8: @@ -675,7 +675,7 @@ IMPLEMENT_FUNCTION(20, Alexei, goSalon) case 4: getData()->location = kLocationInsideCompartment; - setup_function26(); + setup_sitting(); break; } break; @@ -689,7 +689,7 @@ IMPLEMENT_FUNCTION(21, Alexei, sitting) break; case kActionNone: - if (Entity::updateParameterCheck(params->param2, getState()->time, params->param1)) { + if (Entity::updateParameterCheck(params->param2, getState()->time, params->param1) && getEntities()->isSomebodyInsideRestaurantOrSalon()) { getData()->location = kLocationOutsideCompartment; getData()->inventoryItem = kItemNone; @@ -738,6 +738,7 @@ IMPLEMENT_FUNCTION(21, Alexei, sitting) case 3: getEntities()->drawSequenceLeft(kEntityAlexei, "103B"); getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 52); + getData()->location = kLocationInsideCompartment; break; } break; @@ -751,7 +752,7 @@ IMPLEMENT_FUNCTION(22, Alexei, standingAtWindow) break; case kActionNone: - if (Entity::updateParameter(params->param2, getState()->time, params->param2)) { + if (Entity::updateParameterCheck(params->param2, getState()->time, params->param1)) { if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { getData()->location = kLocationOutsideCompartment; getData()->inventoryItem = kItemNone; @@ -768,7 +769,7 @@ IMPLEMENT_FUNCTION(22, Alexei, standingAtWindow) if (getState()->time > kTime1138500) { params->param3 = kTimeInvalid; } else { - if (!getEntities()->isInSalon(kEntityPlayer) || getEntities()->isInSalon(kEntityPlayer) || !params->param3) + if (!getEntities()->isInSalon(kEntityPlayer) && !getEntities()->isInRestaurant(kEntityPlayer) || !params->param3) params->param3 = (uint)getState()->time; if (params->param3 >= getState()->time) @@ -788,7 +789,7 @@ IMPLEMENT_FUNCTION(22, Alexei, standingAtWindow) break; case kActionDefault: - params->param1 = 255 * (4 * rnd(4) + 8); + params->param1 = 225 * (4 * rnd(4) + 8); getEntities()->drawSequenceLeft(kEntityAlexei, "103E"); if (!getEvent(kEventAlexeiSalonPoem)) getData()->inventoryItem = kItemParchemin; @@ -821,7 +822,7 @@ IMPLEMENT_FUNCTION(22, Alexei, standingAtWindow) getEntities()->updatePositionExit(kEntityAlexei, kCarRestaurant, 52); getData()->location = kLocationInsideCompartment; - setup_standingAtWindow(); + setup_sitting(); break; } break; @@ -835,7 +836,7 @@ IMPLEMENT_FUNCTION(23, Alexei, waitingForTatiana) break; case kActionNone: - getData()->inventoryItem = (!getEntities()->isInRestaurant(kEntityAlexei) || getEvent(kEventAlexeiSalonPoem)) ? kItemNone : kItemParchemin; + getData()->inventoryItem = (!getEntities()->isInRestaurant(kEntityTatiana) || getEvent(kEventAlexeiSalonPoem)) ? kItemNone : kItemParchemin; break; case kAction1: @@ -913,7 +914,7 @@ IMPLEMENT_FUNCTION(24, Alexei, upset) case 1: getAction()->playAnimation(kEventAlexeiSalonCath); - getData()->car = kCarRestaurant; + getData()->car = kCarRedSleeping; getData()->entityPosition = kPosition_9460; getEntities()->clearSequences(kEntityAlexei); getScenes()->loadSceneFromPosition(kCarRestaurant, 55); @@ -1125,7 +1126,7 @@ IMPLEMENT_FUNCTION(30, Alexei, atBreakfast) break; case 2: - getSound()->playSound(kEntityAlexei, "TAt2116A"); + getSound()->playSound(kEntityAlexei, "TAT2116A"); getEntities()->updatePositionEnter(kEntityAlexei, kCarRestaurant, 63); setCallback(3); @@ -1333,7 +1334,7 @@ IMPLEMENT_FUNCTION(35, Alexei, pacing3) case kActionNone: if (getEntities()->isInSalon(kEntityPlayer)) { - if (Entity::updateParameter(params->param2, getState()->time, 2700)) { + if (Entity::updateParameterCheck(params->param2, getState()->time, 2700)) { setCallback(1); setup_callbackActionRestaurantOrSalon(); break; @@ -1342,7 +1343,7 @@ IMPLEMENT_FUNCTION(35, Alexei, pacing3) params->param2 = 0; } - if (Entity::updateParameter(params->param3, getState()->time, params->param1)) { + if (Entity::updateParameterCheck(params->param3, getState()->time, params->param1)) { if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { setCallback(3); setup_pacingAtWindow(); @@ -1535,10 +1536,10 @@ IMPLEMENT_FUNCTION(39, Alexei, meetTatiana) break; } - params->param4 = kTimeInvalid; + params->param5 = kTimeInvalid; - getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 70); - getEntities()->updatePositionEnter(kEntityAlexei, kCarGreenSleeping, 71); + getEntities()->updatePositionExit(kEntityAlexei, kCarGreenSleeping, 70); + getEntities()->updatePositionExit(kEntityAlexei, kCarGreenSleeping, 71); if (getEntities()->isInGreenCarEntrance(kEntityPlayer)) { getSound()->excuseMe(kEntityAlexei); @@ -1725,10 +1726,7 @@ IMPLEMENT_FUNCTION(43, Alexei, pacing) break; case kActionNone: - if (getState()->time < kTime1806300 && params->param2 < getState()->time) { - if (!params->param2) - params->param2 = (uint)getState()->time + params->param1; - + if (getState()->time < kTime1806300 && Entity::updateParameterCheck(params->param2, getState()->time, params->param1)) { if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { setCallback(1); setup_pacingAtWindow(); @@ -1782,7 +1780,7 @@ IMPLEMENT_FUNCTION(44, Alexei, goToPlatform) break; case kActionNone: - if (getState()->time > kTime2457000 && !params->param1) { + if (getState()->time > kTime2475000 && !params->param1) { params->param1 = 1; getEntities()->updatePositionExit(kEntityAlexei, kCarGreenSleeping, 70); @@ -1986,7 +1984,7 @@ IMPLEMENT_FUNCTION(47, Alexei, function47) getData()->entityPosition = kPositionNone; getData()->location = kLocationOutsideCompartment; - getData()->car = kCarNone; + getData()->car = kCarLocomotive; getObjects()->update(kObjectCompartment2, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); getObjects()->update(kObjectHandleInsideBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); diff --git a/engines/lastexpress/entities/alexei.h b/engines/lastexpress/entities/alexei.h index 5e14039a35..713a8c7847 100644 --- a/engines/lastexpress/entities/alexei.h +++ b/engines/lastexpress/entities/alexei.h @@ -47,11 +47,11 @@ public: DECLARE_FUNCTION_1(playSound, const char *filename) /** - * Updates parameter 2 using ticks value + * Updates parameter 2 using time value * - * @param ticks The number of ticks to add + * @param time The time to add */ - DECLARE_FUNCTION_1(updateFromTicks, uint32 ticks) + DECLARE_FUNCTION_1(updateFromTime, uint32 time) /** * Draws the entity diff --git a/engines/lastexpress/entities/alouan.cpp b/engines/lastexpress/entities/alouan.cpp index 0667d11697..a4bb10539c 100644 --- a/engines/lastexpress/entities/alouan.cpp +++ b/engines/lastexpress/entities/alouan.cpp @@ -34,10 +34,10 @@ 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_SI(Alouan, enterExitCompartment); + ADD_CALLBACK_FUNCTION_S(Alouan, playSound); + ADD_CALLBACK_FUNCTION_I(Alouan, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Alouan, updateEntity); ADD_CALLBACK_FUNCTION(Alouan, peekF); ADD_CALLBACK_FUNCTION(Alouan, peekH); ADD_CALLBACK_FUNCTION(Alouan, goFtoH); @@ -287,7 +287,7 @@ IMPLEMENT_FUNCTION(16, Alouan, chapter3Handler) label_callback1: if (params->param2 != kTimeInvalid && getState()->time > kTime1989000) { - if (Entity::timeCheckCar(kTime2119500, params->param5, 5, WRAP_SETUP_FUNCTION(Alouan, setup_peekH))) + if (Entity::timeCheckCar(kTime2119500, params->param2, 2, WRAP_SETUP_FUNCTION(Alouan, setup_peekF))) break; } @@ -486,7 +486,7 @@ IMPLEMENT_FUNCTION(23, Alouan, hiding) case 1: setCallback(2); - setup_enterExitCompartment("619AF", kObjectCompartment5); + setup_enterExitCompartment("619AF", kObjectCompartment6); break; case 2: diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp index 52e975086a..2b31c7b5c8 100644 --- a/engines/lastexpress/entities/anna.cpp +++ b/engines/lastexpress/entities/anna.cpp @@ -22,6 +22,8 @@ #include "lastexpress/entities/anna.h" +#include "lastexpress/entities/vesna.h" + #include "lastexpress/fight/fight.h" #include "lastexpress/game/action.h" @@ -41,23 +43,23 @@ 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_S(Anna, draw); + ADD_CALLBACK_FUNCTION_SII(Anna, updatePosition); + ADD_CALLBACK_FUNCTION_SI(Anna, enterExitCompartment); ADD_CALLBACK_FUNCTION(Anna, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Anna, callSavepoint); - ADD_CALLBACK_FUNCTION(Anna, playSound); + ADD_CALLBACK_FUNCTION_SIIS(Anna, callSavepoint); + ADD_CALLBACK_FUNCTION_S(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_II(Anna, savegame); + ADD_CALLBACK_FUNCTION_II(Anna, updateEntity); + ADD_CALLBACK_FUNCTION_I(Anna, updateFromTime); ADD_CALLBACK_FUNCTION(Anna, practiceMusic); - ADD_CALLBACK_FUNCTION(Anna, draw2); - ADD_CALLBACK_FUNCTION(Anna, updateFromTicks); - ADD_CALLBACK_FUNCTION(Anna, compartmentLogic); + ADD_CALLBACK_FUNCTION_SSI(Anna, draw2); + ADD_CALLBACK_FUNCTION_I(Anna, updateFromTicks); + ADD_CALLBACK_FUNCTION_IS(Anna, compartmentLogic); ADD_CALLBACK_FUNCTION(Anna, chapter1); - ADD_CALLBACK_FUNCTION(Anna, doWalkP1); - ADD_CALLBACK_FUNCTION(Anna, diningLogic); + ADD_CALLBACK_FUNCTION_II(Anna, doWalkP1); + ADD_CALLBACK_FUNCTION_I(Anna, diningLogic); ADD_CALLBACK_FUNCTION(Anna, fleeTyler); ADD_CALLBACK_FUNCTION(Anna, waitDinner); ADD_CALLBACK_FUNCTION(Anna, goDinner); @@ -78,13 +80,13 @@ Anna::Anna(LastExpressEngine *engine) : Entity(engine, kEntityAnna) { ADD_CALLBACK_FUNCTION(Anna, goVassili); ADD_CALLBACK_FUNCTION(Anna, function37); ADD_CALLBACK_FUNCTION(Anna, speakTatiana); - ADD_CALLBACK_FUNCTION(Anna, doWalk1019); + ADD_CALLBACK_FUNCTION_II(Anna, doWalk1019); ADD_CALLBACK_FUNCTION(Anna, leaveTatiana); ADD_CALLBACK_FUNCTION(Anna, goBackToSleep); ADD_CALLBACK_FUNCTION(Anna, chapter2); ADD_CALLBACK_FUNCTION(Anna, inPart2); ADD_CALLBACK_FUNCTION(Anna, chapter3); - ADD_CALLBACK_FUNCTION(Anna, exitCompartment); + ADD_CALLBACK_FUNCTION_I(Anna, exitCompartment); ADD_CALLBACK_FUNCTION(Anna, practicing); ADD_CALLBACK_FUNCTION(Anna, goLunch); ADD_CALLBACK_FUNCTION(Anna, lunch); @@ -111,7 +113,7 @@ Anna::Anna(LastExpressEngine *engine) : Entity(engine, kEntityAnna) { ADD_CALLBACK_FUNCTION(Anna, goSalon4); ADD_CALLBACK_FUNCTION(Anna, returnCompartment4); ADD_CALLBACK_FUNCTION(Anna, enterCompartmentCathFollowsAnna); - ADD_CALLBACK_FUNCTION(Anna, doWalkCathFollowsAnna); + ADD_CALLBACK_FUNCTION_II(Anna, doWalkCathFollowsAnna); ADD_CALLBACK_FUNCTION(Anna, letDownHair); ADD_CALLBACK_FUNCTION(Anna, chapter5); ADD_CALLBACK_FUNCTION(Anna, tiedUp); @@ -125,7 +127,7 @@ Anna::Anna(LastExpressEngine *engine) : Entity(engine, kEntityAnna) { ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(1, Anna, reset) - Entity::reset(savepoint, true, true); + Entity::reset(savepoint, kClothes3, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -311,7 +313,7 @@ IMPLEMENT_FUNCTION(12, Anna, practiceMusic) } params->param4 = 0; - params->param5 = 0; + params->param5 = 1; } else { getSoundQueue()->removeFromQueue(kEntityAnna); @@ -335,7 +337,7 @@ IMPLEMENT_FUNCTION(12, Anna, practiceMusic) getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); getObjects()->update(kObjectOutsideAnnaCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); - if (getEntities()->isPlayerPosition(kCarRedSleeping, 49)) + if (getEntities()->isPlayerPosition(kCarRedSleeping, 78)) getScenes()->loadSceneFromPosition(kCarRedSleeping, 49); getEntities()->drawSequenceLeft(kEntityAnna, "418C"); @@ -357,7 +359,7 @@ IMPLEMENT_FUNCTION(12, Anna, practiceMusic) if (getEntities()->isPlayerPosition(kCarRedSleeping, 60)) { ++params->param3; if (params->param3 == 2) { - setCallback(2); + setCallback(5); setup_draw("418B"); } } @@ -606,6 +608,7 @@ IMPLEMENT_FUNCTION_II(17, Anna, doWalkP1, uint32, uint32) break; case kActionDefault: + getData()->inventoryItem = kItemNone; if (getProgress().jacket == kJacketGreen) { if (!getEvent(kEventGotALight) && !getEvent(kEventGotALightD) && !getEvent(kEventAugustPresentAnna) && !getEvent(kEventAugustPresentAnnaFirstIntroduction)) params->param3 = kItemInvalid; @@ -729,7 +732,7 @@ IMPLEMENT_FUNCTION_I(18, Anna, diningLogic, TimeValue) case 2: getAction()->playAnimation(kEventDinerMindJoin); - params->param2 &= 0xFFFFFFF7; + params->param2 &= 0xFFFFFF7F; if (getProgress().jacket == kJacketGreen && !getEvent(kEventAnnaGiveScarfAsk) @@ -992,6 +995,7 @@ IMPLEMENT_FUNCTION(25, Anna, eatingDinner) break; case 2: + setCallback(3); setup_callbackActionRestaurantOrSalon(); break; @@ -1021,10 +1025,10 @@ IMPLEMENT_FUNCTION(26, Anna, leaveDinner) case kActionDefault: getData()->location = kLocationOutsideCompartment; - getEntities()->updatePositionExit(kEntityAnna, kCarRestaurant, 62); + getEntities()->updatePositionEnter(kEntityAnna, kCarRestaurant, 62); setCallback(1); - setup_callSavepoint("001L", kEntityTables0, kActionDrawTablesWithChairs, "001H"); + setup_callSavepoint("001L", kEntityTables0, kActionDrawTablesWithChairs, "001M"); break; case kActionCallback: @@ -1222,7 +1226,7 @@ IMPLEMENT_FUNCTION(29, Anna, waitAugust) case 2: getAction()->playAnimation((getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction)) ? kEventAnnaConversationGoodNight : kEventAnnaIntroductionRejected); - getData()->inventoryItem = (InventoryItem)(getData()->inventoryItem & kItemToggleLow); + getData()->inventoryItem = (InventoryItem)(getData()->inventoryItem & kItemToggleHigh); if (getProgress().jacket == kJacketGreen && !getEvent(kEventAnnaGiveScarfAsk) @@ -1698,7 +1702,7 @@ IMPLEMENT_FUNCTION_II(39, Anna, doWalk1019, CarIndex, EntityPosition) case kActionCallback: if (getCallback() == 1) { - getAction()->playAnimation(getData()->direction == kDirectionNone ? kEventAnnaGoodNight : kEventAnnaGoodNightInverse); + getAction()->playAnimation(getData()->direction == kDirectionUp ? kEventAnnaGoodNight : kEventAnnaGoodNightInverse); getData()->inventoryItem = kItemNone; getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + (750 * (getData()->direction == kDirectionUp ? -1 : 1))), getData()->direction == kDirectionUp); @@ -1807,8 +1811,8 @@ IMPLEMENT_FUNCTION(41, Anna, goBackToSleep) if (!Entity::updateParameter(params->param2, getState()->time, 2700)) break; - params->param5++; - switch (params->param5) { + params->param1++; + switch (params->param1) { default: break; @@ -2127,7 +2131,7 @@ label_callback_4: break; case kActionDefault: - getEntities()->drawSequenceLeft(kEntityAnna, "026C"); + getEntities()->drawSequenceLeft(kEntityAnna, "026c"); getData()->location = kLocationInsideCompartment; setCallback(1); @@ -2220,7 +2224,7 @@ IMPLEMENT_FUNCTION(50, Anna, leaveLunch) case kActionDefault: setCallback(1); - setup_playSound("ann3141"); + setup_playSound("Ann3141"); break; case kActionCallback: @@ -2266,7 +2270,7 @@ IMPLEMENT_FUNCTION(51, Anna, afterLunch) break; case kActionDefault: - getSound()->playSound(kEntityAnna, "Aug3142", kFlagInvalid, 30); + getSound()->playSound(kEntityAnna, "Ann3142", kFlagInvalid, 30); getEntities()->updatePositionEnter(kEntityAnna, kCarRestaurant, 57); getEntities()->drawSequenceRight(kEntityAnna, "112A"); if (getEntities()->isInRestaurant(kEntityPlayer)) @@ -2401,7 +2405,7 @@ IMPLEMENT_FUNCTION(53, Anna, dressing) if (params->param3) { if (Entity::updateParameter(params->param6, getState()->time, 9000)) { params->param4 = !params->param4; - getEntities()->drawSequenceLeft(kEntityAnna, params->param4 ? "417B" : "417A"); + getEntities()->drawSequenceLeft(kEntityAnna, params->param4 ? "417A" : "417B"); params->param6 = 0; } } @@ -2549,7 +2553,7 @@ IMPLEMENT_FUNCTION(54, Anna, giveMaxToConductor2) if (Entity::updateParameter(params->param6, getState()->time, 9000)) { params->param4 = !params->param4; - getEntities()->drawSequenceLeft(kEntityAnna, params->param4 ? "417B" : "417A"); + getEntities()->drawSequenceLeft(kEntityAnna, params->param4 ? "417A" : "417B"); params->param6 = 0; } } @@ -2729,7 +2733,7 @@ IMPLEMENT_FUNCTION(55, Anna, goConcert) case 1: getObjects()->update(kObjectCompartmentF, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); setCallback(2); - setup_updateEntity(kCarRedSleeping, kPosition_9270); + setup_updateEntity(kCarKronos, kPosition_9270); break; case 2: @@ -3072,7 +3076,7 @@ IMPLEMENT_FUNCTION(61, Anna, goBaggageCompartment) getState()->timeDelta = 3; setCallback(1); - setup_savegame(kSavegameTypeIndex, 0); + setup_savegame(kSavegameTypeTime, 0); break; case kActionCallback: @@ -3132,7 +3136,7 @@ IMPLEMENT_FUNCTION(62, Anna, function62) break; case kActionNone: - if (getState()->time > kTime2259000 && !params->param2) { + if (params->param1 && getState()->time > kTime2259000 && !params->param2) { params->param2 = 1; getSavePoints()->push(kEntityAnna, kEntityVesna, kAction189299008); setup_deadBaggageCompartment(); @@ -3222,6 +3226,7 @@ IMPLEMENT_FUNCTION(64, Anna, baggageFight) getScenes()->loadSceneFromPosition(kCarBaggage, 96); getProgress().field_54 = 0; + RESET_ENTITY_STATE(kEntityVesna, Vesna, setup_inCompartment); getState()->time = kTime2266200; setup_prepareVienna(); @@ -3302,7 +3307,7 @@ label_next: case kAction1: getData()->inventoryItem = kItemNone; - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; setCallback(1); setup_savegame(kSavegameTypeEvent, kEventAnnaConversation_34); @@ -3329,9 +3334,11 @@ label_next: break; case kActionDrawScene: - getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); - params->param1 = 0; - params->param2 = 0; + if (params->param1 || params->param2) { + getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorHandKnock, kCursorHand); + params->param1 = 0; + params->param2 = 0; + } break; case kActionCallback: @@ -3743,7 +3750,7 @@ IMPLEMENT_FUNCTION(75, Anna, tiedUp) else getAction()->playAnimation(getEvent(kEventAnnaKissTrainHijacked) ? kEventAnnaBaggageTies3 : kEventAnnaBaggageTies4); - getScenes()->loadSceneFromPosition(kCarBaggage, 8); + getScenes()->loadSceneFromPosition(kCarBaggageRear, 88); setup_function76(); } break; @@ -3806,7 +3813,7 @@ IMPLEMENT_FUNCTION(77, Anna, readyToScore) getObjects()->update(kObject106, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); getAction()->playAnimation(kEventAnnaDialogGoToJerusalem); - getState()->time = kTimeCityConstantinople; + getState()->time = kTime4914000; getState()->timeDelta = 0; getSavePoints()->push(kEntityAnna, kEntityTatiana, kAction236060709); @@ -3837,10 +3844,12 @@ IMPLEMENT_FUNCTION(78, Anna, kidnapped) break; } - getState()->time = kTimeInvalid2; + if (getEntities()->isInSalon(kEntityPlayer)) { + getState()->time = kTime4920300; - setCallback(getInventory()->get(kItemFirebird)->location == kObjectLocation4 ? 2 : 1); - setup_savegame(kSavegameTypeEvent, getInventory()->get(kItemFirebird)->location == kObjectLocation4 ? kEventKronosHostageAnna : kEventKronosHostageAnnaNoFirebird); + setCallback(getInventory()->get(kItemFirebird)->location == kObjectLocation4 ? 2 : 1); + setup_savegame(kSavegameTypeEvent, getInventory()->get(kItemFirebird)->location == kObjectLocation4 ? kEventKronosHostageAnna : kEventKronosHostageAnnaNoFirebird); + } break; case kActionCallback: @@ -3871,9 +3880,9 @@ IMPLEMENT_FUNCTION(79, Anna, waiting) break; case kActionEndSound: - getState()->time = kTime5933; + getState()->time = kTime4923000; setCallback(1); - setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunchBaggageCarEntrance); break; case kActionDrawScene: @@ -3883,7 +3892,7 @@ IMPLEMENT_FUNCTION(79, Anna, waiting) } if (getEntities()->isInSalon(kEntityPlayer) && !getEvent(kEventKahinaPunch)) { - getState()->time = kTime5933; + getState()->time = kTime4923000; setCallback(2); setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); } @@ -3908,7 +3917,7 @@ IMPLEMENT_FUNCTION(79, Anna, waiting) break; case 2: - getAction()->playAnimation(kEventKahinaPunchSalon); + getAction()->playAnimation(kEventKahinaPunch); break; } @@ -3932,17 +3941,17 @@ IMPLEMENT_FUNCTION(80, Anna, finalSequence) case kActionEndSound: getSound()->playSound(kEntityPlayer, "Kro5002", kFlagDefault); - getState()->time = kTime4923000; + getState()->time = kTime4929300; - setCallback(1); - setup_savegame(kSavegameTypeEvent, kEventKronosBringFirebird); + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); break; case kActionDefault: - getState()->time = kTime4929300; + getState()->time = kTime4923000; - setCallback(2); - setup_savegame(kSavegameTypeEvent, kEventKahinaPunch); + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKronosBringFirebird); break; case kActionCallback: @@ -3997,8 +4006,8 @@ IMPLEMENT_FUNCTION(81, Anna, openFirebird) if (!Entity::updateParameter(params->param1, getState()->timeTicks, 180)) break; - getSound()->playSound(kEntityTrain, "LIB069"); - getLogic()->gameOver(kSavegameTypeIndex, 2, kSceneNone, true); + getSound()->playSound(kEntityTrain, "LIB069", kFlagDefault); + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true); break; case kActionCallback: diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp index 1176d9d473..01dc0b76c9 100644 --- a/engines/lastexpress/entities/august.cpp +++ b/engines/lastexpress/entities/august.cpp @@ -43,28 +43,28 @@ 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_I(August, updateFromTime); + ADD_CALLBACK_FUNCTION_S(August, draw); + ADD_CALLBACK_FUNCTION_SII(August, updatePosition); + ADD_CALLBACK_FUNCTION_SI(August, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(August, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_SI(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_SIIS(August, callSavepoint); + ADD_CALLBACK_FUNCTION_IIS(August, callSavepointNoDrawing); + ADD_CALLBACK_FUNCTION_SSI(August, draw2); + ADD_CALLBACK_FUNCTION_S(August, playSound); + ADD_CALLBACK_FUNCTION_S(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_II(August, savegame); + ADD_CALLBACK_FUNCTION_II(August, updateEntity); + ADD_CALLBACK_FUNCTION_I(August, function17); + ADD_CALLBACK_FUNCTION_II(August, updateEntity2); + ADD_CALLBACK_FUNCTION_TYPE(August, function19, EntityParametersIISS); + ADD_CALLBACK_FUNCTION_TYPE(August, function20, EntityParametersISSI); + ADD_CALLBACK_FUNCTION_I(August, function21); ADD_CALLBACK_FUNCTION(August, chapter1); - ADD_CALLBACK_FUNCTION(August, function23); + ADD_CALLBACK_FUNCTION_I(August, function23); ADD_CALLBACK_FUNCTION(August, dinner); ADD_CALLBACK_FUNCTION(August, chapter1Handler); ADD_CALLBACK_FUNCTION(August, function26); @@ -82,8 +82,8 @@ August::August(LastExpressEngine *engine) : Entity(engine, kEntityAugust) { 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_II(August, function41); + ADD_CALLBACK_FUNCTION_III(August, function42); ADD_CALLBACK_FUNCTION(August, chapter3Handler); ADD_CALLBACK_FUNCTION(August, function44); ADD_CALLBACK_FUNCTION(August, function45); @@ -116,7 +116,7 @@ August::August(LastExpressEngine *engine) : Entity(engine, kEntityAugust) { ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(1, August, reset) - Entity::reset(savepoint, true); + Entity::reset(savepoint, kClothes2, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -141,7 +141,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_SI(6, August, enterExitCompartment2, ObjectIndex) - Entity::enterExitCompartment(savepoint, kPosition_6470, kPosition_6130, kCarGreenSleeping, kObjectCompartment3, true); + Entity::enterExitCompartment(savepoint, kPosition_6470, kPosition_6130, kCarGreenSleeping, kObjectCompartment3, true, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -250,7 +250,7 @@ IMPLEMENT_FUNCTION_I(17, August, function17, TimeValue) ENTITY_PARAM(0, 1) = 0; setCallback(1); - setup_updateEntity(kCarRedSleeping, kPosition_540); + setup_updateEntity2(kCarRedSleeping, kPosition_540); break; case kActionCallback: @@ -397,7 +397,7 @@ IMPLEMENT_FUNCTION_II(19, August, function19, bool, bool) strcat((char *)¶meters->seq2, parameters->param1 ? "Fc" : "Dc"); setCallback(3); - setup_enterExitCompartment((char *)¶meters->seq2, kObjectCompartment3); + setup_enterExitCompartment2((char *)¶meters->seq2, kObjectCompartment3); break; case 3: @@ -451,7 +451,7 @@ IMPLEMENT_FUNCTION_I(20, August, function20, bool) break; } - if (params->param1) { + if (parameters->param1) { Common::String sequence = Common::String::format("%s%s", (char *)¶meters->seq1, "Gc"); assert(sequence.size() <= 13); @@ -575,7 +575,7 @@ label_continue: case kActionOpenDoor: if (getProgress().chapter == kChapter1 && !getProgress().eventMetAugust && getProgress().jacket == kJacketGreen) { getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; setCallback(6); setup_savegame(kSavegameTypeEvent, kEventMeetAugustHisCompartment); @@ -648,7 +648,7 @@ label_continue: params->param2 = 0; params->param3 = 0; params->param5 = 0; - params->param6 = 0; + params->param6 = 1; CURRENT_PARAM(1, 1) = 0; break; @@ -694,7 +694,11 @@ label_continue: case 11: case 12: case 13: - getObjects()->update(kObjectCompartment3, kEntityAugust, kObjectLocation1, kCursorTalk, (getProgress().eventMetAugust || getProgress().jacket != kJacketGreen) ? kCursorNormal : kCursorHand); + { + CursorStyle cursor1 = (getCallback() == 12 || getCallback() == 13) ? kCursorNormal : kCursorTalk; + CursorStyle cursor2 = (getProgress().eventMetAugust || getProgress().jacket != kJacketGreen) ? kCursorNormal : kCursorHand; + getObjects()->update(kObjectCompartment3, kEntityAugust, kObjectLocation1, cursor1, cursor2); + } if (getCallback() == 12 || getCallback() == 13) { params->param2 = 0; @@ -806,10 +810,10 @@ IMPLEMENT_FUNCTION_I(23, August, function23, TimeValue) if (!params->param2) { if (!CURRENT_PARAM(1, 3)) - CURRENT_PARAM(1, 3) = getState()->timeTicks + 45; + CURRENT_PARAM(1, 3) = getState()->timeTicks + 75; if (CURRENT_PARAM(1, 3) >= getState()->timeTicks) - break; + goto label_callback_9; if (!params->param5) { setCallback(8); @@ -892,7 +896,7 @@ label_callback_9: } else { if (getProgress().eventCorpseMovedFromFloor && getProgress().jacket != kJacketBlood) { - params->param7 = (getObjects()->get(kObjectCompartment1).model == kObjectModel1) ? 8 : 7; + params->param7 = (getObjects()->get(kObjectCompartment1).model == kObjectModel1) ? kEventMeetAugustTylerCompartmentBed : kEventMeetAugustTylerCompartment; getObjects()->update(kObjectOutsideTylerCompartment, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); setCallback(4); @@ -916,14 +920,14 @@ label_callback_9: getObjects()->update(kObjectCompartment1, kEntityAugust, getObjects()->get(kObjectCompartment1).status, kCursorNormal, kCursorNormal); setCallback(17); - setup_playSound("AUG1002A"); + setup_playSound16("AUG1002A"); } break; case kActionOpenDoor: if (getProgress().eventCorpseMovedFromFloor && getProgress().jacket != kJacketBlood) { if (params->param3) { - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; params->param7 = (getObjects()->get(kObjectCompartment1).model == kObjectModel1) ? kEventMeetAugustHisCompartmentBed : kEventMeetAugustHisCompartment; } else { @@ -1057,7 +1061,7 @@ label_callback_9: break; case 14: - if (!params->param2) + if (!params->param3) getSound()->playSound(kEntityPlayer, getObjects()->get(kObjectCompartment1).status == kObjectLocation1 ? "LIB032" : "LIB014"); getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); @@ -1436,16 +1440,16 @@ IMPLEMENT_FUNCTION(29, August, function29) break; case kActionNone: - if (!getProgress().field_28 || (params->param2 && params->param3 == kTimeInvalid)) + if (!getProgress().field_28 || params->param2 || params->param3 == kTimeInvalid) break; - if (getState()->time < kTime1134000) { + if (getState()->time <= kTime1134000) { if (!getEntities()->isInRestaurant(kEntityPlayer) - || getSoundQueue()->isBuffered("MRB1076") || getSoundQueue()->isBuffered("MRB1078") || getSoundQueue()->isBuffered("MRB1078A")) + || getSoundQueue()->isBuffered("MRB1076") || getSoundQueue()->isBuffered("MRB1078") || getSoundQueue()->isBuffered("MRB1078A") || !params->param3) params->param3 = (uint)getState()->time + 225; - if (params->param3 > getState()->time) + if (params->param3 >= getState()->time) break; } @@ -1528,7 +1532,7 @@ IMPLEMENT_FUNCTION(30, August, restaurant) if (getProgress().eventMetAugust) getData()->inventoryItem = kItemNone; - getSound()->playSound(kEntityAugust, "Aug1003A"); + getSound()->playSound(kEntityAugust, "AUG1003A"); } else { getData()->inventoryItem = kItemNone; getSavePoints()->push(kEntityAugust, kEntityAnna, kAction201437056); @@ -1576,7 +1580,12 @@ IMPLEMENT_FUNCTION(30, August, restaurant) break; case 4: - + getAction()->playAnimation(getProgress().eventMetAugust ? kEventAugustPresentAnna : kEventAugustPresentAnnaFirstIntroduction); + getSavePoints()->push(kEntityAugust, kEntityAnna, kAction201437056); + getEntities()->drawSequenceRight(kEntityAugust, getProgress().eventMetAugust ? "803GS" : "010P"); + getScenes()->loadSceneFromPosition(kCarRestaurant, getProgress().eventMetAugust ? 55 : 65); + setCallback(getProgress().eventMetAugust ? 5 : 6); + setup_callbackActionOnDirection(); break; case 5: @@ -1623,7 +1632,7 @@ IMPLEMENT_FUNCTION(31, August, function31) break; case 2: - setCallback(2); + setCallback(3); setup_function21(kTime1161000); break; @@ -1648,7 +1657,7 @@ IMPLEMENT_FUNCTION(32, August, function32) break; case kActionNone: - if (Entity::updateParameterTime(kTime1179000, (!getEntities()->isInSalon(kEntityAnna) || getEntities()->isInSalon(kEntityPlayer)), params->param6, 0)) { + if (params->param6 != kTimeInvalid && Entity::updateParameterTime(kTime1179000, (!getEntities()->isInSalon(kEntityAnna) || getEntities()->isInSalon(kEntityPlayer)), params->param6, 0)) { getSavePoints()->push(kEntityAugust, kEntityAnna, kAction123712592); } @@ -2003,6 +2012,7 @@ IMPLEMENT_FUNCTION(38, August, function38) case 2: getScenes()->loadSceneFromItemPosition(kItem3); getData()->location = kLocationInsideCompartment; + getEntities()->drawSequenceLeft(kEntityAugust, "109B"); break; case 3: @@ -2125,6 +2135,7 @@ IMPLEMENT_FUNCTION_II(41, August, function41, CarIndex, EntityPosition) getData()->inventoryItem = kItemNone; if (getEntities()->updateEntity(kEntityAugust, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; callbackAction(); break; } @@ -2232,6 +2243,7 @@ IMPLEMENT_FUNCTION(43, August, chapter3Handler) // Set as same position as Anna if (params->param1) { getData()->entityPosition = getEntityData(kEntityAnna)->entityPosition; + getData()->location = getEntityData(kEntityAnna)->location; getData()->car = getEntityData(kEntityAnna)->car; } @@ -2328,7 +2340,7 @@ IMPLEMENT_FUNCTION(44, August, function44) getData()->location = kLocationOutsideCompartment; setCallback(1); - setup_updatePosition("122H", kCarRestaurant, 57); + setup_updatePosition("112H", kCarRestaurant, 57); break; case kActionCallback: @@ -2417,10 +2429,10 @@ IMPLEMENT_FUNCTION_END IMPLEMENT_FUNCTION(46, August, function46) switch (savepoint.action) { default: - Entity::timeCheckCallback(kTime2088000, params->param1, 1, WRAP_SETUP_FUNCTION(August, setup_function47)); break; case kActionNone: + Entity::timeCheckCallback(kTime2088000, params->param1, 1, WRAP_SETUP_FUNCTION(August, setup_function47)); break; case kActionDrawScene: @@ -2655,7 +2667,7 @@ IMPLEMENT_FUNCTION(52, August, function52) case kActionKnock: case kActionOpenDoor: if (getInventory()->hasItem(kItemBriefcase)) { - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; if (savepoint.action == kActionKnock) getSound()->playSound(kEntityPlayer, "LIB012"); @@ -2779,13 +2791,13 @@ IMPLEMENT_FUNCTION(54, August, function54) break; case kActionNone: - if (!params->param4 || params->param2 || getProgress().field_44) + if (!params->param3 || params->param1 || getProgress().field_44) getData()->inventoryItem = kItemNone; else getData()->inventoryItem = kItemInvalid; - if (!params->param2 && params->param1) { - if (!Entity::updateParameter(params->param5, getState()->time, params->param1)) + if (getEvent(kEventAugustTalkCigar) && params->param2 && !params->param1) { + if (!Entity::updateParameter(params->param4, getState()->time, 9000)) break; getData()->inventoryItem = kItemNone; @@ -2811,10 +2823,10 @@ IMPLEMENT_FUNCTION(54, August, function54) break; case kActionDrawScene: - if (!getEntities()->isPlayerPosition(kCarRestaurant, 60) || params->param3) { - if (!params->param2 && getEntities()->isPlayerPosition(kCarRestaurant, 57)) + if (!getEntities()->isPlayerPosition(kCarRestaurant, 60) || params->param2 || params->param1) { + if (!params->param1 && getEntities()->isPlayerPosition(kCarRestaurant, 57)) getScenes()->loadSceneFromPosition(kCarRestaurant, 50); - } else if (!params->param2) { + } else { getEntities()->updatePositionEnter(kEntityAugust, kCarRestaurant, 57); getEntities()->drawSequenceRight(kEntityAugust, "105C3"); } @@ -2837,36 +2849,32 @@ IMPLEMENT_FUNCTION(54, August, function54) getData()->location = kLocationInsideCompartment; getSavePoints()->push(kEntityAugust, kEntityAbbot, kAction123712592); getEntities()->drawSequenceLeft(kEntityAugust, "105B3"); - params->param4 = 1; + params->param3 = 1; break; case 3: getAction()->playAnimation(kEventAugustTalkCigar); - getEntities()->drawSequenceLeft(kEntityAugust, params->param3 ? "122B" : "105B3"); + getEntities()->drawSequenceLeft(kEntityAugust, params->param2 ? "122B" : "105B3"); getScenes()->processScene(); - params->param1 = 9000; - params->param4 = 0; + params->param3 = 0; break; } break; case kAction122288808: getEntities()->drawSequenceLeft(kEntityAugust, "122B"); - params->param2 = 0; - - if (getEvent(kEventAugustTalkCigar)) - params->param1 = 9000; + params->param1 = 0; break; case kAction122358304: getEntities()->drawSequenceLeft(kEntityAugust, "BLANK"); + params->param1 = 1; params->param2 = 1; - params->param3 = 1; break; case kAction136196244: - params->param2 = 1; + params->param1 = 1; getData()->inventoryItem = kItemNone; break; } @@ -2973,7 +2981,7 @@ IMPLEMENT_FUNCTION(58, August, chapter4Handler) case kActionDefault: setCallback(1); - setup_function20(false); + setup_function20(true); break; case kActionCallback: @@ -3047,7 +3055,6 @@ IMPLEMENT_FUNCTION(60, August, function60) case kActionNone: { bool pushSavepoint = false; if (!params->param2) { - pushSavepoint = true; params->param2 = (uint)getState()->time + 450; } @@ -3252,7 +3259,7 @@ IMPLEMENT_FUNCTION(63, August, function63) if (!Entity::updateParameter(params->param5, getState()->timeTicks, params->param1)) break; - params->param2 = (params->param6 < 1 ? 1 : 0); + params->param2 = (params->param2 == 0 ? 1 : 0); getEntities()->drawSequenceLeft(kEntityAugust, params->param2 ? "122H" : "122F"); diff --git a/engines/lastexpress/entities/boutarel.cpp b/engines/lastexpress/entities/boutarel.cpp index 0385eb084d..2ee7136269 100644 --- a/engines/lastexpress/entities/boutarel.cpp +++ b/engines/lastexpress/entities/boutarel.cpp @@ -39,23 +39,23 @@ 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_S(Boutarel, playSound); + ADD_CALLBACK_FUNCTION_S(Boutarel, draw); + ADD_CALLBACK_FUNCTION_I(Boutarel, updateFromTime); + ADD_CALLBACK_FUNCTION_SII(Boutarel, updatePosition); + ADD_CALLBACK_FUNCTION_SI(Boutarel, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(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_II(Boutarel, updateEntity); + ADD_CALLBACK_FUNCTION_I(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_I(Boutarel, function14); + ADD_CALLBACK_FUNCTION_IS(Boutarel, function15); + ADD_CALLBACK_FUNCTION_IS(Boutarel, function16); + ADD_CALLBACK_FUNCTION_IS(Boutarel, function17); + ADD_CALLBACK_FUNCTION_I(Boutarel, function18); ADD_CALLBACK_FUNCTION(Boutarel, chapter1); ADD_CALLBACK_FUNCTION(Boutarel, function20); ADD_CALLBACK_FUNCTION(Boutarel, chapter1Handler); @@ -257,8 +257,8 @@ IMPLEMENT_FUNCTION(12, Boutarel, enterTableWithMmeBoutarel) if (getEntities()->isInSalon(kEntityPlayer)) { getEntities()->updateFrame(kEntityBoutarel); - getEntityData(kEntityMmeBoutarel)->location = getData()->location; - getEntityData(kEntityTables2)->location = getData()->location; + getEntityData(kEntityMmeBoutarel)->field_4A1 = getData()->field_4A1; + getEntityData(kEntityTables2)->field_4A1 = getData()->field_4A1; } break; } @@ -836,7 +836,7 @@ IMPLEMENT_FUNCTION(24, Boutarel, chapter2Handler) break; case kActionNone: - Entity::timeCheckCallback(kTime1759500, params->param2, 1, false, WRAP_SETUP_FUNCTION_B(Boutarel, setup_function14)); + Entity::timeCheckCallback(kTime1759500, params->param2, 1, true, WRAP_SETUP_FUNCTION_B(Boutarel, setup_function14)); break; case kActionDefault: @@ -961,7 +961,7 @@ IMPLEMENT_FUNCTION(29, Boutarel, function29) } } - Entity::timeCheckCallback(kTime2002500, params->param4, 1, true, WRAP_SETUP_FUNCTION_B(Boutarel, setup_function14)); + Entity::timeCheckCallback(kTime2002500, params->param4, 2, true, WRAP_SETUP_FUNCTION_B(Boutarel, setup_function14)); break; case kActionDefault: @@ -974,7 +974,7 @@ IMPLEMENT_FUNCTION(29, Boutarel, function29) break; case 1: - Entity::timeCheckCallback(kTime2002500, params->param4, 1, true, WRAP_SETUP_FUNCTION_B(Boutarel, setup_function14)); + Entity::timeCheckCallback(kTime2002500, params->param4, 2, true, WRAP_SETUP_FUNCTION_B(Boutarel, setup_function14)); break; case 2: diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp index f1a7d02384..8ed458c89c 100644 --- a/engines/lastexpress/entities/chapters.cpp +++ b/engines/lastexpress/entities/chapters.cpp @@ -72,9 +72,9 @@ 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_II(Chapters, savegame); + ADD_CALLBACK_FUNCTION_SI(Chapters, enterStation); + ADD_CALLBACK_FUNCTION_S(Chapters, exitStation); ADD_CALLBACK_FUNCTION(Chapters, chapter1); ADD_CALLBACK_FUNCTION(Chapters, resetMainEntities); ADD_CALLBACK_FUNCTION(Chapters, firstDream); @@ -92,8 +92,8 @@ Chapters::Chapters(LastExpressEngine *engine) : Entity(engine, kEntityChapters) 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); + ADD_CALLBACK_FUNCTION(Chapters, chapter5Init); + ADD_CALLBACK_FUNCTION(Chapters, chapter5Handler); } ////////////////////////////////////////////////////////////////////////// @@ -135,6 +135,7 @@ IMPLEMENT_FUNCTION(5, Chapters, resetMainEntities) RESET_ENTITY_STATE(kEntityHadija, Hadija, setup_reset); RESET_ENTITY_STATE(kEntityIvo, Ivo, setup_reset); RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_reset); + RESET_ENTITY_STATE(kEntityKronos, Kronos, setup_reset); RESET_ENTITY_STATE(kEntityMmeBoutarel, MmeBoutarel, setup_reset); RESET_ENTITY_STATE(kEntityMahmud, Mahmud, setup_reset); RESET_ENTITY_STATE(kEntityMax, Max, setup_reset); @@ -258,17 +259,13 @@ IMPLEMENT_FUNCTION(6, Chapters, firstDream) if (getSoundQueue()->isBuffered("ZFX1005")) getSoundQueue()->processEntry("ZFX1005"); - - if (getSoundQueue()->isBuffered("ZFX1006")) + else if (getSoundQueue()->isBuffered("ZFX1006")) getSoundQueue()->processEntry("ZFX1006"); - - if (getSoundQueue()->isBuffered("ZFX1007")) + else if (getSoundQueue()->isBuffered("ZFX1007")) getSoundQueue()->processEntry("ZFX1007"); - - if (getSoundQueue()->isBuffered("ZFX1007A")) + else if (getSoundQueue()->isBuffered("ZFX1007A")) getSoundQueue()->processEntry("ZFX1007A"); - - if (getSoundQueue()->isBuffered("ZFX1007B")) + else if (getSoundQueue()->isBuffered("ZFX1007B")) getSoundQueue()->processEntry("ZFX1007B"); getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); @@ -321,7 +318,7 @@ IMPLEMENT_FUNCTION(7, Chapters, chapter1Init) getProgress().chapter = kChapter1; getSoundQueue()->resetState(); - getState()->time = kTimeChapter1; + getState()->time = kTimeStartGame; getState()->timeDelta = 0; getProgress().isTrainRunning = true; getProgress().portrait = kPortraitOriginal; @@ -376,8 +373,8 @@ IMPLEMENT_FUNCTION(7, Chapters, chapter1Init) 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(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); + getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorHand); getObjects()->update(kObject101, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); setup_chapter1Handler(); @@ -972,7 +969,7 @@ label_callback_4: break; label_callback_5: - if (timeCheckExitStation(kTimeEnterWels, CURRENT_PARAM(1, 3), 6, "Wels")) + if (timeCheckExitStation(kTimeExitWels, CURRENT_PARAM(1, 3), 6, "Wels")) break; label_callback_6: @@ -980,7 +977,7 @@ label_callback_6: break; label_callback_7: - if (timeCheckExitStation(kTimeCityLinz, CURRENT_PARAM(1, 5), 8, "Linz")) + if (timeCheckExitStation(kTimeExitLinz, CURRENT_PARAM(1, 5), 8, "Linz")) break; label_callback_8: @@ -1024,7 +1021,7 @@ label_callback_8: getSound()->playSteam((CityIndex)ENTITY_PARAM(0, 4)); ENTITY_PARAM(0, 2) = 0; - if (params->param1) + if (params->param3) setup_viennaEvents(); break; @@ -1086,6 +1083,30 @@ IMPLEMENT_FUNCTION(16, Chapters, viennaEvents) break; case kActionDefault: + getEntityData(kEntityPlayer)->car = kCarLocomotive; + if (getSoundQueue()->isBuffered(kEntityAbbot)) + getSoundQueue()->processEntry(kEntityAbbot); + + if (!getEvent(kEventAugustBringBriefcase)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventViennaAugustUnloadGuns); + break; + } + + if (getInventory()->get(kItemFirebird)->location == kObjectLocation5) { + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventViennaKronosFirebird); + break; + } + + if (ENTITY_PARAM(0, 1)) { + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventVergesAnnaDead); + break; + } + + setCallback(4); + setup_savegame(kSavegameTypeEvent, kEventViennaContinueGame); break; case kActionCallback: @@ -1108,10 +1129,7 @@ IMPLEMENT_FUNCTION(16, Chapters, viennaEvents) 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); + getLogic()->gameOver(kSavegameTypeTime, kTime2155500, kSceneGameOverVienna1, true); } else { if (getProgress().field_C0) { if (getEvent(kEventKronosReturnBriefcase)) @@ -1733,7 +1751,7 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) setCallback(1); setup_savegame(kSavegameTypeEvent, kEventTrainStopped); } else { - getLogic()->gameOver(kSavegameTypeTime, kTimeTrainStopped2, kSceneGameOverTrainStopped, true); + getLogic()->gameOver(kSavegameTypeTime, kTime2934000, kSceneGameOverTrainStopped, true); } break; diff --git a/engines/lastexpress/entities/cooks.cpp b/engines/lastexpress/entities/cooks.cpp index 749e93999b..34cd4a787f 100644 --- a/engines/lastexpress/entities/cooks.cpp +++ b/engines/lastexpress/entities/cooks.cpp @@ -35,8 +35,8 @@ namespace LastExpress { Cooks::Cooks(LastExpressEngine *engine) : Entity(engine, kEntityCooks) { - ADD_CALLBACK_FUNCTION(Cooks, draw); - ADD_CALLBACK_FUNCTION(Cooks, playSound); + ADD_CALLBACK_FUNCTION_S(Cooks, draw); + ADD_CALLBACK_FUNCTION_S(Cooks, playSound); ADD_CALLBACK_FUNCTION(Cooks, uptrainVersion); ADD_CALLBACK_FUNCTION(Cooks, downtrainVersion); ADD_CALLBACK_FUNCTION(Cooks, chapter1); @@ -98,26 +98,17 @@ IMPLEMENT_FUNCTION(3, Cooks, uptrainVersion) break; } - if (getEntities()->isPlayerPosition(kCarRestaurant, 46)) { + if (getEntities()->isPlayerPosition(kCarRestaurant, 76)) { getEntities()->drawSequenceLeft(kEntityCooks, "308D"); - if (!getSoundQueue()->isBuffered(kEntityCooks)) { - if (params->param1) { - if (!getEntities()->hasValidFrame(kEntityCooks)) { - getSound()->playSound(kEntityCooks, "LIB015"); - getEntities()->clearSequences(kEntityCooks); - callbackAction(); - } - break; - } - + if (!getSoundQueue()->isBuffered(kEntityCooks) && !params->param1) { // Kitchen apprentice getting a lesson :D getSound()->playSound(kEntityCooks, "KIT1011A"); params->param1 = 1; } } - if (params->param1 && !getEntities()->hasValidFrame(kEntityCooks)) { + if (params->param1 && !getEntities()->hasValidFrame(kEntityCooks) && !getSoundQueue()->isBuffered(kEntityCooks)) { getSound()->playSound(kEntityCooks, "LIB015"); getEntities()->clearSequences(kEntityCooks); callbackAction(); @@ -159,22 +150,21 @@ IMPLEMENT_FUNCTION(4, Cooks, downtrainVersion) switch (getProgress().chapter) { default: + getSound()->playSound(kEntityCooks, "KIT1011"); + setCallback(3); + setup_draw("308B"); break; case kChapter1: - setCallback(2); - setup_playSound("ZFX1011"); + setCallback(1); + setup_playSound("KIT1010"); break; case kChapter3: setCallback(2); - setup_playSound("ZFX1011"); + setup_playSound("KIT1012"); break; } - - getSound()->playSound(kEntityCooks, "KIT1011"); - setCallback(3); - setup_draw("308B"); break; case kActionDrawScene: @@ -187,23 +177,14 @@ IMPLEMENT_FUNCTION(4, Cooks, downtrainVersion) if (getEntities()->isPlayerPosition(kCarRestaurant, 80)) { getEntities()->drawSequenceLeft(kEntityCooks, "308D"); - if (!getSoundQueue()->isBuffered(kEntityCooks)) { - if (params->param1) { - if (!getEntities()->hasValidFrame(kEntityCooks)) { - getSound()->playSound(kEntityCooks, "LIB015"); - getEntities()->clearSequences(kEntityCooks); - callbackAction(); - } - break; - } - + if (!getSoundQueue()->isBuffered(kEntityCooks) && !params->param1) { // Kitchen apprentice getting a lesson :D getSound()->playSound(kEntityCooks, "KIT1011A"); params->param1 = 1; } } - if (params->param1 && !getEntities()->hasValidFrame(kEntityCooks)) { + if (params->param1 && !getEntities()->hasValidFrame(kEntityCooks) && !getSoundQueue()->isBuffered(kEntityCooks)) { getSound()->playSound(kEntityCooks, "LIB015"); getEntities()->clearSequences(kEntityCooks); callbackAction(); @@ -225,7 +206,7 @@ IMPLEMENT_FUNCTION(4, Cooks, downtrainVersion) case 3: getEntities()->drawSequenceLeft(kEntityCooks, "308C"); getEntities()->updatePositionExit(kEntityCooks, kCarRestaurant, 75); - getEntities()->updatePositionEnter(kEntityCooks, kCarRestaurant, 78); + getEntities()->updatePositionExit(kEntityCooks, kCarRestaurant, 78); break; } break; @@ -388,6 +369,9 @@ IMPLEMENT_FUNCTION(9, Cooks, inKitchenBreakfast) break; case kActionDrawScene: + if (!getEntities()->isInKitchen(kEntityPlayer)) + break; + if (params->param2) { setCallback(1); setup_playSound("ZFX1011"); diff --git a/engines/lastexpress/entities/coudert.cpp b/engines/lastexpress/entities/coudert.cpp index 66e6b83620..dd1377da87 100644 --- a/engines/lastexpress/entities/coudert.cpp +++ b/engines/lastexpress/entities/coudert.cpp @@ -39,25 +39,25 @@ namespace LastExpress { 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_S(Coudert, bloodJacket); + ADD_CALLBACK_FUNCTION_SI(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_SIII(Coudert, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_S(Coudert, playSound); + ADD_CALLBACK_FUNCTION_S(Coudert, playSound16); + ADD_CALLBACK_FUNCTION_II(Coudert, savegame); + ADD_CALLBACK_FUNCTION_II(Coudert, updateEntity); + ADD_CALLBACK_FUNCTION_I(Coudert, updateFromTime); + ADD_CALLBACK_FUNCTION_I(Coudert, updateFromTicks); + ADD_CALLBACK_FUNCTION_I(Coudert, excuseMe); + ADD_CALLBACK_FUNCTION_II(Coudert, function13); + ADD_CALLBACK_FUNCTION_I(Coudert, function14); + ADD_CALLBACK_FUNCTION_I(Coudert, function15); ADD_CALLBACK_FUNCTION(Coudert, function16); - ADD_CALLBACK_FUNCTION(Coudert, function17); + ADD_CALLBACK_FUNCTION_I(Coudert, function17); ADD_CALLBACK_FUNCTION(Coudert, function18); - ADD_CALLBACK_FUNCTION(Coudert, function19); - ADD_CALLBACK_FUNCTION(Coudert, function20); + ADD_CALLBACK_FUNCTION_I(Coudert, function19); + ADD_CALLBACK_FUNCTION_II(Coudert, function20); ADD_CALLBACK_FUNCTION(Coudert, function21); ADD_CALLBACK_FUNCTION(Coudert, function22); ADD_CALLBACK_FUNCTION(Coudert, function23); @@ -67,12 +67,12 @@ Coudert::Coudert(LastExpressEngine *engine) : Entity(engine, kEntityCoudert) { 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_TYPE2(Coudert, function30, EntityParametersI5S, EntityParametersSIIS); + ADD_CALLBACK_FUNCTION_I(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_I(Coudert, function34); + ADD_CALLBACK_FUNCTION_I(Coudert, function35); ADD_CALLBACK_FUNCTION(Coudert, chapter1); ADD_CALLBACK_FUNCTION(Coudert, function37); ADD_CALLBACK_FUNCTION(Coudert, function38); @@ -84,7 +84,7 @@ Coudert::Coudert(LastExpressEngine *engine) : Entity(engine, kEntityCoudert) { ADD_CALLBACK_FUNCTION(Coudert, chapter3); ADD_CALLBACK_FUNCTION(Coudert, function45); ADD_CALLBACK_FUNCTION(Coudert, function46); - ADD_CALLBACK_FUNCTION(Coudert, function47); + ADD_CALLBACK_FUNCTION_I(Coudert, function47); ADD_CALLBACK_FUNCTION(Coudert, function48); ADD_CALLBACK_FUNCTION(Coudert, function49); ADD_CALLBACK_FUNCTION(Coudert, function50); @@ -105,7 +105,7 @@ Coudert::Coudert(LastExpressEngine *engine) : Entity(engine, kEntityCoudert) { ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(1, Coudert, reset) - Entity::reset(savepoint, true); + Entity::reset(savepoint, kClothes1, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -115,7 +115,7 @@ IMPLEMENT_FUNCTION_S(2, Coudert, bloodJacket) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionExitCompartment: @@ -142,7 +142,7 @@ IMPLEMENT_FUNCTION_SI(3, Coudert, enterExitCompartment, ObjectIndex) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); return; case kActionCallback: @@ -168,7 +168,7 @@ IMPLEMENT_FUNCTION(4, Coudert, callbackActionOnDirection) break; } - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionExitCompartment: @@ -191,7 +191,7 @@ IMPLEMENT_FUNCTION_SIII(5, Coudert, enterExitCompartment2, ObjectIndex, EntityPo break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); return; case kActionCallback: @@ -212,7 +212,7 @@ IMPLEMENT_FUNCTION_S(6, Coudert, playSound) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionEndSound: @@ -241,7 +241,7 @@ IMPLEMENT_FUNCTION_NOSETUP(7, Coudert, playSound16) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionEndSound: @@ -354,7 +354,7 @@ IMPLEMENT_FUNCTION_I(10, Coudert, updateFromTime, uint32) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); if (!Entity::updateParameter(params->param2, getState()->time, params->param1)) break; @@ -378,7 +378,7 @@ IMPLEMENT_FUNCTION_I(11, Coudert, updateFromTicks, uint32) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); if (!Entity::updateParameter(params->param2, getState()->timeTicks, params->param1)) break; @@ -453,7 +453,8 @@ IMPLEMENT_FUNCTION_II(13, Coudert, function13, bool, EntityIndex) break; case kActionNone: - Entity::savegameBloodJacket(); + if (Entity::savegameBloodJacket(1)) + break; if (!params->param2 && !params->param3) { @@ -576,7 +577,7 @@ IMPLEMENT_FUNCTION_I(14, Coudert, function14, EntityIndex) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(4); break; case kActionDefault: @@ -678,7 +679,7 @@ IMPLEMENT_FUNCTION_I(15, Coudert, function15, bool) if (params->param1) getSound()->playSound(kEntityCoudert, "Tat3163"); else - getSound()->playSound(kEntityCoudert, (getProgress().chapter != kChapter3 || getState()->time > kTime1449000) ? "Tat3162A" : "Tat3161A"); + getSound()->playSound(kEntityCoudert, (getProgress().chapter != kChapter3 || getState()->time >= kTime1449000) ? "Tat3162A" : "Tat3161A"); setCallback(3); setup_enterExitCompartment("627Xb", kObjectCompartmentB); @@ -808,6 +809,7 @@ IMPLEMENT_FUNCTION(18, Coudert, function18) if (ENTITY_PARAM(0, 3) || ENTITY_PARAM(0, 5) || ENTITY_PARAM(0, 4)) { getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); getScenes()->loadSceneFromItemPosition(kItem5); + ENTITY_PARAM(2, 1) = 1; callbackAction(); break; @@ -1305,7 +1307,7 @@ IMPLEMENT_FUNCTION(26, Coudert, function26) break; case kActionNone: - if (params->param1) { + if (!params->param1) { if (!Entity::updateParameter(params->param2, getState()->timeTicks, 75)) break; @@ -1963,7 +1965,7 @@ IMPLEMENT_FUNCTION(36, Coudert, chapter1) break; case kActionNone: - Entity::timeCheckCallback(kTimeChapter1, params->param1, 1, WRAP_SETUP_FUNCTION(Coudert, setup_chapter1Handler)); + Entity::timeCheckCallback(kTimeChapter1, params->param1, 1, WRAP_SETUP_FUNCTION(Coudert, setup_function18)); break; case kActionDefault: @@ -2088,7 +2090,7 @@ switch (savepoint.action) { case kAction191477936: getData()->entityPosition = kPosition_4070; getData()->location = kLocationOutsideCompartment; - getObjects()->update(kObjectCompartment4, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); setCallback(1); setup_updateEntity(kCarRedSleeping, kPosition_2000); @@ -2152,7 +2154,7 @@ IMPLEMENT_FUNCTION(39, Coudert, function39) case 7: setCallback(8); - setup_enterExitCompartment("MME1151", kObjectCompartmentD); + setup_enterExitCompartment("697Ad", kObjectCompartmentD); break; case 8: @@ -2271,7 +2273,7 @@ label_callback_9: if (ENTITY_PARAM(0, 1) && !getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityCoudert, rnd(2) ? "JAC1065" : "JAC1065A"); - if (getState()->time > kTime1107000 && !ENTITY_PARAM(0, 1) && !getEvent(kEventVassiliSeizure)) { + if (getState()->time > kTime1107000 && !params->param1 && !getEvent(kEventVassiliSeizure)) { getData()->inventoryItem = kItemNone; setCallback(10); @@ -2601,7 +2603,7 @@ IMPLEMENT_FUNCTION(43, Coudert, function43) } label_callback1: - if (!ENTITY_PARAM(1, 1)) { + if (ENTITY_PARAM(1, 1)) { setCallback(2); setup_function15(false); break; @@ -3366,7 +3368,7 @@ IMPLEMENT_FUNCTION(51, Coudert, function51) case kActionNone: if (getState()->time > kTime2133000 && !getProgress().field_40) { - getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB); + getEntities()->exitCompartment(kEntityCoudert, kObjectCompartmentB, true); getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); @@ -3439,7 +3441,7 @@ IMPLEMENT_FUNCTION(51, Coudert, function51) break; case 5: - setCallback(5); + setCallback(6); setup_function18(); break; } @@ -4095,7 +4097,7 @@ IMPLEMENT_FUNCTION(62, Coudert, function62) case 3: ++params->param3; - if (params->param3 == 1 || params->param2) { + if (params->param3 == 1 || params->param3 == 2) { getObjects()->update(kObjectCompartmentH, kEntityCoudert, kObjectLocation1, kCursorNormal, kCursorNormal); setCallback(params->param3 == 1 ? 4 : 5); setup_playSound(params->param3 == 1 ? "Jac5002" : "Jac5002A"); diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp index 170248de52..faf937c3e0 100644 --- a/engines/lastexpress/entities/entity.cpp +++ b/engines/lastexpress/entities/entity.cpp @@ -147,11 +147,35 @@ void EntityData::updateParameters(uint32 index) const { error("[EntityData::updateParameters] Invalid param index to update (was:%d, max:32)", index); } -void EntityData::saveLoadWithSerializer(Common::Serializer &s) { - for (uint i = 0; i < ARRAYSIZE(_parameters); i++) - _parameters[i].saveLoadWithSerializer(s); +void EntityData::saveLoadWithSerializer(Common::Serializer &s, const Common::Array<TypeSetter>* paramsTypeSetters) { + if (s.isSaving()) { + for (uint i = 0; i < ARRAYSIZE(_parameters); i++) + _parameters[i].saveLoadWithSerializer(s); - _data.saveLoadWithSerializer(s); + _data.saveLoadWithSerializer(s); + } else { + // to correctly deserialize parameters, we need to know their runtime type + // but we don't know it until callbacks[] array will be deserialized + // all types of parameters are serialized to 32*4 bytes + // (the original game has same-size-PODs and just memcpy-s them. + // *sigh* Why does this implementation even need the extra byte in strings? + // Well, big-endian vs little-endian is also a thing...) + byte buf[ARRAYSIZE(_parameters) * 32 * 4]; + s.syncBytes(buf, sizeof(buf)); + + _data.saveLoadWithSerializer(s); + + for (uint i = 0; i < 8; i++) { + if (!paramsTypeSetters || _data.callbacks[i] >= paramsTypeSetters->size()) + resetParametersType<EntityParametersIIII>(&_parameters[i]); + else + (*paramsTypeSetters)[_data.callbacks[i]](&_parameters[i]); + } + Common::MemoryReadStream paramsStream(buf, sizeof(buf)); + Common::Serializer paramsSerializer(¶msStream, NULL); + for (uint i = 0; i < ARRAYSIZE(_parameters); i++) + _parameters[i].saveLoadWithSerializer(paramsSerializer); + } } ////////////////////////////////////////////////////////////////////////// @@ -162,6 +186,7 @@ Entity::Entity(LastExpressEngine *engine, EntityIndex index) : _engine(engine), // Add first empty entry to callbacks array _callbacks.push_back(NULL); + _paramsTypeSetters.push_back(&EntityData::resetParametersType<EntityData::EntityParametersIIII>); } Entity::~Entity() { @@ -211,7 +236,7 @@ void Entity::setup(ChapterIndex index) { // Shared functions ////////////////////////////////////////////////////////////////////////// -void Entity::reset(const SavePoint &savepoint, bool resetClothes, bool resetItem) { +void Entity::reset(const SavePoint &savepoint, ClothesIndex maxClothes, bool resetItem) { EXPOSE_PARAMS(EntityData::EntityParametersIIII) switch (savepoint.action) { @@ -219,10 +244,10 @@ void Entity::reset(const SavePoint &savepoint, bool resetClothes, bool resetItem break; case kAction1: - if (resetClothes) { + if (maxClothes != kClothesDefault) { // Select next available clothes getData()->clothes = (ClothesIndex)(getData()->clothes + 1); - if (getData()->clothes > kClothes3) + if (getData()->clothes > maxClothes) getData()->clothes = kClothesDefault; } break; @@ -263,26 +288,16 @@ void Entity::savegame(const SavePoint &savepoint) { } } -void Entity::savegameBloodJacket() { +bool Entity::savegameBloodJacket(byte callback) { if (getProgress().jacket == kJacketBlood && getEntities()->isDistanceBetweenEntities(_entityIndex, kEntityPlayer, 1000) && !getEntities()->isInsideCompartments(kEntityPlayer) && !getEntities()->checkFields10(kEntityPlayer)) { - setCallback(1); - - switch (_entityIndex) { - default: - break; - - case kEntityCoudert: - setup_savegame(kSavegameTypeEvent, kEventCoudertBloodJacket); - break; - - case kEntityMertens: - setup_savegame(kSavegameTypeEvent, kEventCoudertBloodJacket); - break; - } + setCallback(callback); + setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket); + return true; } + return false; } void Entity::playSound(const SavePoint &savepoint, bool resetItem, SoundFlag flag) { @@ -355,7 +370,7 @@ void Entity::updateFromTicks(const SavePoint &savepoint) { break; case kActionNone: - if (Entity::updateParameter(params->param2, getState()->timeTicks, params->param1)) + if (!Entity::updateParameter(params->param2, getState()->timeTicks, params->param1)) break; callbackAction(); @@ -371,7 +386,7 @@ void Entity::updateFromTime(const SavePoint &savepoint) { break; case kActionNone: - if (Entity::updateParameter(params->param2, getState()->time, params->param1)) + if (!Entity::updateParameter(params->param2, getState()->time, params->param1)) break; callbackAction(); @@ -388,7 +403,7 @@ void Entity::callbackActionOnDirection(const SavePoint &savepoint) { callbackAction(); break; - case kActionDefault: + case kActionNone: if (getData()->direction != kDirectionRight) callbackAction(); break; @@ -609,22 +624,22 @@ void Entity::callbackAction() { ////////////////////////////////////////////////////////////////////////// // Setup functions ////////////////////////////////////////////////////////////////////////// -void Entity::setup(const char *name, uint index) { +void Entity::setup(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter) { debugC(6, kLastExpressDebugLogic, "Entity: %s()", name); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersIIII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupI(const char *name, uint index, uint param1) { +void Entity::setupI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u)", name, param1); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersIIII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII *)_data->getCurrentParameters(); params->param1 = (unsigned int)param1; @@ -632,12 +647,12 @@ void Entity::setupI(const char *name, uint index, uint param1) { _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupII(const char *name, uint index, uint param1, uint param2) { +void Entity::setupII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u)", name, param1, param2); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersIIII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII *)_data->getCurrentParameters(); params->param1 = param1; @@ -646,12 +661,12 @@ void Entity::setupII(const char *name, uint index, uint param1, uint param2) { _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupIII(const char *name, uint index, uint param1, uint param2, uint param3) { +void Entity::setupIII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, uint param3) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u, %u)", name, param1, param2, param3); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersIIII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII *)_data->getCurrentParameters(); params->param1 = param1; @@ -661,12 +676,12 @@ void Entity::setupIII(const char *name, uint index, uint param1, uint param2, ui _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupS(const char *name, uint index, const char *seq1) { +void Entity::setupS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s)", name, seq1); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSIIS>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters(); strncpy(params->seq1, seq1, 12); @@ -674,12 +689,12 @@ void Entity::setupS(const char *name, uint index, const char *seq1) { _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupSS(const char *name, uint index, const char *seq1, const char *seq2) { +void Entity::setupSS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, const char *seq2) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %s)", name, seq1, seq2); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSSII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersSSII *params = (EntityData::EntityParametersSSII*)_data->getCurrentParameters(); strncpy(params->seq1, seq1, 12); @@ -688,12 +703,12 @@ void Entity::setupSS(const char *name, uint index, const char *seq1, const char _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupSI(const char *name, uint index, const char *seq1, uint param4) { +void Entity::setupSI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u)", name, seq1, param4); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSIIS>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS *)_data->getCurrentParameters(); strncpy(params->seq1, seq1, 12); @@ -702,27 +717,27 @@ void Entity::setupSI(const char *name, uint index, const char *seq1, uint param4 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupSII(const char *name, uint index, const char *seq1, uint param4, uint param5) { +void Entity::setupSII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4, uint param5) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u, %u)", name, seq1, param4, param5); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSIIS>(); + paramsTypeSetter(_data->getCurrentCallParameters()); - EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS *)_data->getCurrentParameters(); - strncpy(params->seq1, seq1, 12); + EntityData::EntityParametersSIII *params = (EntityData::EntityParametersSIII *)_data->getCurrentParameters(); + strncpy(params->seq, seq1, 12); params->param4 = param4; params->param5 = param5; _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupSIII(const char *name, uint index, const char *seq, uint param4, uint param5, uint param6) { +void Entity::setupSIII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq, uint param4, uint param5, uint param6) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u, %u, %u)", name, seq, param4, param5, param6); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSIII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersSIII *params = (EntityData::EntityParametersSIII *)_data->getCurrentParameters(); strncpy(params->seq, seq, 12); @@ -733,12 +748,12 @@ void Entity::setupSIII(const char *name, uint index, const char *seq, uint param _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupSIIS(const char *name, uint index, const char *seq1, uint param4, uint param5, const char *seq2) { +void Entity::setupSIIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4, uint param5, const char *seq2) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u, %u, %s)", name, seq1, param4, param5, seq2); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSIIS>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS *)_data->getCurrentParameters(); strncpy(params->seq1, seq1, 12); @@ -749,12 +764,12 @@ void Entity::setupSIIS(const char *name, uint index, const char *seq1, uint para _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupSSI(const char *name, uint index, const char *seq1, const char *seq2, uint param7) { +void Entity::setupSSI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, const char *seq2, uint param7) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %s, %u)", name, seq1, seq2, param7); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersSSII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersSSII *params = (EntityData::EntityParametersSSII *)_data->getCurrentParameters(); strncpy(params->seq1, seq1, 12); @@ -764,12 +779,12 @@ void Entity::setupSSI(const char *name, uint index, const char *seq1, const char _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupIS(const char *name, uint index, uint param1, const char *seq) { +void Entity::setupIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, const char *seq) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %s)", name, param1, seq); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersISII>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersISII *params = (EntityData::EntityParametersISII *)_data->getCurrentParameters(); params->param1 = (unsigned int)param1; @@ -778,12 +793,12 @@ void Entity::setupIS(const char *name, uint index, uint param1, const char *seq) _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupISS(const char *name, uint index, uint param1, const char *seq1, const char *seq2) { +void Entity::setupISS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, const char *seq1, const char *seq2) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %s, %s)", name, param1, seq1, seq2); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersISSI>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersISSI *params = (EntityData::EntityParametersISSI *)_data->getCurrentParameters(); params->param1 = param1; @@ -793,12 +808,12 @@ void Entity::setupISS(const char *name, uint index, uint param1, const char *seq _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupIIS(const char *name, uint index, uint param1, uint param2, const char *seq) { +void Entity::setupIIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, const char *seq) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u, %s)", name, param1, param2, seq); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersIISI>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersIISI *params = (EntityData::EntityParametersIISI *)_data->getCurrentParameters(); params->param1 = param1; @@ -808,12 +823,12 @@ void Entity::setupIIS(const char *name, uint index, uint param1, uint param2, co _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault); } -void Entity::setupIISS(const char *name, uint index, uint param1, uint param2, const char *seq1, const char *seq2) { +void Entity::setupIISS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, const char *seq1, const char *seq2) { debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u, %s, %s)", name, param1, param2, seq1, seq2); _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]); _data->setCurrentCallback(index); - _data->resetCurrentParameters<EntityData::EntityParametersIISS>(); + paramsTypeSetter(_data->getCurrentCallParameters()); EntityData::EntityParametersIISS *params = (EntityData::EntityParametersIISS *)_data->getCurrentParameters(); params->param1 = param1; @@ -855,12 +870,12 @@ bool Entity::updateParameterTime(TimeValue timeValue, bool check, uint ¶mete } bool Entity::updateParameterCheck(uint ¶meter, uint timeType, uint delta) const { - if (parameter && parameter >= timeType) - return false; - if (!parameter) parameter = (uint)(timeType + delta); + if (parameter && parameter >= timeType) + return false; + return true; } diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h index 25c481c5cf..0e01b08830 100644 --- a/engines/lastexpress/entities/entity.h +++ b/engines/lastexpress/entities/entity.h @@ -76,11 +76,37 @@ struct SavePoint; #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_CALLBACK_FUNCTION_TYPE(class, name, type) \ + _callbacks.push_back(new ENTITY_CALLBACK(class, name, this)); \ + _paramsTypeSetters.push_back(&EntityData::resetParametersType<EntityData::type>); + +#define ADD_CALLBACK_FUNCTION_TYPE2(class, name, type1, type2) \ + _callbacks.push_back(new ENTITY_CALLBACK(class, name, this)); \ + _paramsTypeSetters.push_back(&EntityData::resetParametersType<EntityData::type1, EntityData::type2>); + +#define ADD_CALLBACK_FUNCTION_TYPE3(class, name, type1, type2, type3) \ + _callbacks.push_back(new ENTITY_CALLBACK(class, name, this)); \ + _paramsTypeSetters.push_back(&EntityData::resetParametersType<EntityData::type1, EntityData::type2, EntityData::type3>); + +#define ADD_CALLBACK_FUNCTION(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersIIII) +#define ADD_CALLBACK_FUNCTION_I(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersIIII) +#define ADD_CALLBACK_FUNCTION_II(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersIIII) +#define ADD_CALLBACK_FUNCTION_III(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersIIII) +#define ADD_CALLBACK_FUNCTION_S(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSIIS) +#define ADD_CALLBACK_FUNCTION_SI(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSIIS) +#define ADD_CALLBACK_FUNCTION_SII(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSIII) +#define ADD_CALLBACK_FUNCTION_SIII(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSIII) +#define ADD_CALLBACK_FUNCTION_SIIS(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSIIS) +#define ADD_CALLBACK_FUNCTION_SS(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSSII) +#define ADD_CALLBACK_FUNCTION_SSI(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersSSII) +#define ADD_CALLBACK_FUNCTION_IS(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersISII) +#define ADD_CALLBACK_FUNCTION_ISS(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersISSI) +#define ADD_CALLBACK_FUNCTION_IIS(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersIISI) +#define ADD_CALLBACK_FUNCTION_IISS(class, name) ADD_CALLBACK_FUNCTION_TYPE(class, name, EntityParametersIISS) #define ADD_NULL_FUNCTION() \ - _callbacks.push_back(new ENTITY_CALLBACK(Entity, nullfunction, this)); + _callbacks.push_back(new ENTITY_CALLBACK(Entity, nullfunction, this)); \ + _paramsTypeSetters.push_back(&(EntityData::resetParametersType<EntityData::EntityParametersIIII>)); #define WRAP_SETUP_FUNCTION(className, method) \ new Common::Functor0Mem<void, className>(this, &className::method) @@ -125,7 +151,7 @@ struct SavePoint; // simple setup with no parameters #define IMPLEMENT_FUNCTION(index, class, name) \ void class::setup_##name() { \ - Entity::setup(#class "::setup_" #name, index); \ + Entity::setup(#class "::setup_" #name, index, _paramsTypeSetters[index]); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ @@ -136,13 +162,13 @@ struct SavePoint; // nullfunction call #define IMPLEMENT_NULL_FUNCTION(index, class) \ void class::setup_nullfunction() { \ - Entity::setup(#class "::setup_nullfunction", index); \ + Entity::setup(#class "::setup_nullfunction", index, _paramsTypeSetters[index]); \ } // setup with one uint parameter #define IMPLEMENT_FUNCTION_I(index, class, name, paramType) \ void class::setup_##name(paramType param1) { \ - Entity::setupI(#class "::setup_" #name, index, param1); \ + Entity::setupI(#class "::setup_" #name, index, _paramsTypeSetters[index], param1); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ @@ -151,7 +177,7 @@ struct SavePoint; // setup with two uint parameters #define IMPLEMENT_FUNCTION_II(index, class, name, paramType1, paramType2) \ void class::setup_##name(paramType1 param1, paramType2 param2) { \ - Entity::setupII(#class "::setup_" #name, index, param1, param2); \ + Entity::setupII(#class "::setup_" #name, index, _paramsTypeSetters[index], param1, param2); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ @@ -160,7 +186,7 @@ struct SavePoint; // 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) { \ - Entity::setupIII(#class "::setup_" #name, index, param1, param2, param3); \ + Entity::setupIII(#class "::setup_" #name, index, _paramsTypeSetters[index], param1, param2, param3); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersIIII) \ @@ -169,7 +195,7 @@ struct SavePoint; // setup with one char *parameter #define IMPLEMENT_FUNCTION_S(index, class, name) \ void class::setup_##name(const char *seq1) { \ - Entity::setupS(#class "::setup_" #name, index, seq1); \ + Entity::setupS(#class "::setup_" #name, index, _paramsTypeSetters[index], seq1); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ @@ -178,7 +204,7 @@ struct SavePoint; // setup with one char *parameter and one uint #define IMPLEMENT_FUNCTION_SI(index, class, name, paramType2) \ void class::setup_##name(const char *seq1, paramType2 param4) { \ - Entity::setupSI(#class "::setup_" #name, index, seq1, param4); \ + Entity::setupSI(#class "::setup_" #name, index, _paramsTypeSetters[index], seq1, param4); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ @@ -187,16 +213,16 @@ struct SavePoint; // setup with one 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) { \ - Entity::setupSII(#class "::setup_" #name, index, seq1, param4, param5); \ + Entity::setupSII(#class "::setup_" #name, index, _paramsTypeSetters[index], seq1, param4, param5); \ } \ 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)); + EXPOSE_PARAMS(EntityData::EntityParametersSIII) \ + debugC(6, kLastExpressDebugLogic, "Entity: " #class "::" #name "(%s, %d, %d) - action: %s", (char *)¶ms->seq, params->param4, params->param5, ACTION_NAME(savepoint.action)); // setup with one 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) { \ - Entity::setupSIII(#class "::setup_" #name, index, seq, param4, param5, param6); \ + Entity::setupSIII(#class "::setup_" #name, index, _paramsTypeSetters[index], seq, param4, param5, param6); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersSIII) \ @@ -204,7 +230,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_SIIS(index, class, name, paramType2, paramType3) \ void class::setup_##name(const char *seq1, paramType2 param4, paramType3 param5, const char *seq2) { \ - Entity::setupSIIS(#class "::setup_" #name, index, seq1, param4, param5, seq2); \ + Entity::setupSIIS(#class "::setup_" #name, index, _paramsTypeSetters[index], seq1, param4, param5, seq2); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersSIIS) \ @@ -212,7 +238,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_SS(index, class, name) \ void class::setup_##name(const char *seq1, const char *seq2) { \ - Entity::setupSS(#class "::setup_" #name, index, seq1, seq2); \ + Entity::setupSS(#class "::setup_" #name, index, _paramsTypeSetters[index], seq1, seq2); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersSSII) \ @@ -220,7 +246,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_SSI(index, class, name, paramType3) \ void class::setup_##name(const char *seq1, const char *seq2, paramType3 param7) { \ - Entity::setupSSI(#class "::setup_" #name, index, seq1, seq2, param7); \ + Entity::setupSSI(#class "::setup_" #name, index, _paramsTypeSetters[index], seq1, seq2, param7); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersSSII) \ @@ -228,7 +254,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_IS(index, class, name, paramType) \ void class::setup_##name(paramType param1, const char *seq) { \ - Entity::setupIS(#class "::setup_" #name, index, param1, seq); \ + Entity::setupIS(#class "::setup_" #name, index, _paramsTypeSetters[index], param1, seq); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersISII) \ @@ -236,7 +262,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_ISS(index, class, name, paramType) \ void class::setup_##name(paramType param1, const char *seq1, const char *seq2) { \ - Entity::setupISS(#class "::setup_" #name, index, param1, seq1, seq2); \ + Entity::setupISS(#class "::setup_" #name, index, _paramsTypeSetters[index], param1, seq1, seq2); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersISSI) \ @@ -244,7 +270,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_IIS(index, class, name, paramType1, paramType2) \ void class::setup_##name(paramType1 param1, paramType2 param2, const char *seq) { \ - Entity::setupIIS(#class "::setup_" #name, index, param1, param2, seq); \ + Entity::setupIIS(#class "::setup_" #name, index, _paramsTypeSetters[index], param1, param2, seq); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersIISI) \ @@ -252,7 +278,7 @@ struct SavePoint; #define IMPLEMENT_FUNCTION_IISS(index, class, name, paramType1, paramType2) \ void class::setup_##name(paramType1 param1, paramType2 param2, const char *seq1, const char *seq2) { \ - Entity::setupIISS(#class "::setup_" #name, index, param1, param2, seq1, seq2); \ + Entity::setupIISS(#class "::setup_" #name, index, _paramsTypeSetters[index], param1, param2, seq1, seq2); \ } \ void class::name(const SavePoint &savepoint) { \ EXPOSE_PARAMS(EntityData::EntityParametersIISS) \ @@ -260,7 +286,7 @@ struct SavePoint; ////////////////////////////////////////////////////////////////////////// -class EntityData : Common::Serializable { +class EntityData { public: struct EntityParameters : Common::Serializable { @@ -688,6 +714,23 @@ public: memset(&seq, 0, 13); } + Common::String toString() { + return Common::String::format("I5S: %d %d %d %d %d %s\n", param1, param2, param3, param4, param5, seq); + } + + void update(uint32 index) { + switch (index) { + default: + error("[EntityParametersI5S::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; + } + } + void saveLoadWithSerializer(Common::Serializer &s) { s.syncAsUint32LE(param1); s.syncAsUint32LE(param2); @@ -830,13 +873,13 @@ public: EntityData() {} - template<class T> - void resetCurrentParameters() { - EntityCallParameters *params = &_parameters[_data.currentCall]; + template<class T1, class T2 = EntityParametersIIII, class T3 = EntityParametersIIII> + static void resetParametersType(EntityCallParameters* params) { params->clear(); - - for (int i = 0; i < 4; i++) - params->parameters[i] = new T(); + params->parameters[0] = new T1(); + params->parameters[1] = new T2(); + params->parameters[2] = new T3(); + params->parameters[3] = new EntityParametersIIII(); } EntityCallData *getCallData() { return &_data; } @@ -853,7 +896,8 @@ public: void updateParameters(uint32 index) const; // Serializable - void saveLoadWithSerializer(Common::Serializer &ser); + typedef void(*TypeSetter)(EntityCallParameters*); + void saveLoadWithSerializer(Common::Serializer &ser, const Common::Array<TypeSetter>* paramsTypeSetters); private: @@ -890,7 +934,7 @@ public: virtual void setup_playSound(const char*) { error("[Entity::setup_playSound] Trying to call the parent setup function. Use the specific entity function directly"); } // Serializable - void saveLoadWithSerializer(Common::Serializer &ser) { _data->saveLoadWithSerializer(ser); } + void saveLoadWithSerializer(Common::Serializer &ser) { _data->saveLoadWithSerializer(ser, &_paramsTypeSetters); } void nullfunction(const SavePoint &savepoint) {} @@ -901,6 +945,7 @@ protected: EntityIndex _entityIndex; EntityData *_data; Common::Array<Callback *> _callbacks; + Common::Array<EntityData::TypeSetter> _paramsTypeSetters; /** * Saves the game @@ -914,9 +959,10 @@ protected: /** * Saves the game before being found out with a blood covered jacket. * - * @param saveFunction The setup function to call to save the game + * @param callback argument for setCallback() + * @return true if the event has been processed, false if nothing happened */ - void savegameBloodJacket(); + bool savegameBloodJacket(byte callback); /** * Play sound @@ -968,10 +1014,10 @@ protected: * Resets an entity * * @param savepoint The savepoint. - * @param resetClothes true to reset clothes. + * @param maxClothes cycles clothes from kClothesDefault to maxClothes inclusively * @param resetItem true to reset inventoryItem to kItemInvalid */ - void reset(const SavePoint &savepoint, bool resetClothes = false, bool resetItem = false); + void reset(const SavePoint &savepoint, ClothesIndex maxClothes = kClothesDefault, bool resetItem = false); /** * Process callback action when the entity direction is not kDirectionRight @@ -1064,21 +1110,21 @@ protected: ////////////////////////////////////////////////////////////////////////// // Setup functions ////////////////////////////////////////////////////////////////////////// - void setup(const char *name, uint index); - void setupI(const char *name, uint index, uint param1); - void setupII(const char *name, uint index, uint param1, uint param2); - void setupIII(const char *name, uint index, uint param1, uint param2, uint param3); - void setupS(const char *name, uint index, const char *seq1); - void setupSS(const char *name, uint index, const char *seq1, const char *seq2); - void setupSI(const char *name, uint index, const char *seq1, uint param4); - void setupSII(const char *name, uint index, const char *seq1, uint param4, uint param5); - void setupSIII(const char *name, uint index, const char *seq, uint param4, uint param5, uint param6); - void setupSIIS(const char *name, uint index, const char *seq1, uint param4, uint param5, const char *seq2); - void setupSSI(const char *name, uint index, const char *seq1, const char *seq2, uint param7); - void setupIS(const char *name, uint index, uint param1, const char *seq); - void setupISS(const char *name, uint index, uint param1, const char *seq1, const char *seq2); - void setupIIS(const char *name, uint index, uint param1, uint param2, const char *seq); - void setupIISS(const char *name, uint index, uint param1, uint param2, const char *seq1, const char *seq2); + void setup(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter); + void setupI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1); + void setupII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2); + void setupIII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, uint param3); + void setupS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1); + void setupSS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, const char *seq2); + void setupSI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4); + void setupSII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4, uint param5); + void setupSIII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq, uint param4, uint param5, uint param6); + void setupSIIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4, uint param5, const char *seq2); + void setupSSI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, const char *seq2, uint param7); + void setupIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, const char *seq); + void setupISS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, const char *seq1, const char *seq2); + void setupIIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, const char *seq); + void setupIISS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, const char *seq1, const char *seq2); ////////////////////////////////////////////////////////////////////////// // Helper functions diff --git a/engines/lastexpress/entities/francois.cpp b/engines/lastexpress/entities/francois.cpp index d2fb66c7ce..9eb12fbfce 100644 --- a/engines/lastexpress/entities/francois.cpp +++ b/engines/lastexpress/entities/francois.cpp @@ -38,19 +38,19 @@ 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, doWalk); + ADD_CALLBACK_FUNCTION_I(Francois, updateFromTime); + ADD_CALLBACK_FUNCTION_S(Francois, draw); + ADD_CALLBACK_FUNCTION_SI(Francois, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(Francois, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_S(Francois, playSound); + ADD_CALLBACK_FUNCTION_II(Francois, savegame); + ADD_CALLBACK_FUNCTION_II(Francois, doWalk); ADD_CALLBACK_FUNCTION(Francois, exitCompartment); ADD_CALLBACK_FUNCTION(Francois, enterCompartment); - ADD_CALLBACK_FUNCTION(Francois, rampage); + ADD_CALLBACK_FUNCTION_I(Francois, rampage); ADD_CALLBACK_FUNCTION(Francois, takeWalk); ADD_CALLBACK_FUNCTION(Francois, haremVisit); - ADD_CALLBACK_FUNCTION(Francois, chaseBeetle); + ADD_CALLBACK_FUNCTION_TYPE(Francois, chaseBeetle, EntityParametersIISS); ADD_CALLBACK_FUNCTION(Francois, findCath); ADD_CALLBACK_FUNCTION(Francois, letsGo); ADD_CALLBACK_FUNCTION(Francois, chapter1); @@ -72,7 +72,7 @@ Francois::Francois(LastExpressEngine *engine) : Entity(engine, kEntityFrancois) ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(1, Francois, reset) - Entity::reset(savepoint, true); + Entity::reset(savepoint, kClothes1, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -113,6 +113,7 @@ IMPLEMENT_FUNCTION_II(8, Francois, doWalk, CarIndex, EntityPosition) case kActionNone: if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) { + getData()->inventoryItem = kItemNone; callbackAction(); } else { if (!getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 2000) @@ -126,6 +127,8 @@ IMPLEMENT_FUNCTION_II(8, Francois, doWalk, CarIndex, EntityPosition) && !getEvent(kEventFrancoisShowBeetle) && !getEvent(kEventFrancoisShowBeetleD)) getData()->inventoryItem = kItemMatchBox; + else + getData()->inventoryItem = kItemNone; } else { getData()->inventoryItem = kItemFirebird; } @@ -145,12 +148,12 @@ IMPLEMENT_FUNCTION_II(8, Francois, doWalk, CarIndex, EntityPosition) default: break; - case 1: + case kItemMatchBox: setCallback(2); setup_savegame(kSavegameTypeEvent, kEventFrancoisShowBeetle); break; - case 18: + case kItemFirebird: if (isNight()) getAction()->playAnimation(getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition ? kEventFrancoisShowEggNightD : kEventFrancoisShowEggNight); else @@ -588,6 +591,9 @@ IMPLEMENT_FUNCTION(13, Francois, haremVisit) } getEntities()->drawSequenceLeft(kEntityFrancois, "605He"); + getEntities()->enterCompartment(kEntityFrancois, kObjectCompartmentE, true); + setCallback(8); + setup_playSound(rnd(2) ? "Fra2005B" : "Fra2005C"); break; case 8: @@ -683,7 +689,7 @@ IMPLEMENT_FUNCTION_IIS(14, Francois, chaseBeetle, ObjectIndex, EntityPosition) break; case 8: - getEntities()->exitCompartment(kEntityFrancois, (ObjectIndex)parameters->param1); + getEntities()->exitCompartment(kEntityFrancois, (ObjectIndex)parameters->param1, true); // fall through case 9: @@ -788,6 +794,7 @@ IMPLEMENT_FUNCTION(16, Francois, letsGo) case kActionNone: getData()->entityPosition = getEntityData(kEntityBoutarel)->entityPosition; getData()->location = getEntityData(kEntityBoutarel)->location; + getData()->car = getEntityData(kEntityBoutarel)->car; break; case kActionDefault: @@ -828,6 +835,7 @@ IMPLEMENT_FUNCTION(16, Francois, letsGo) getData()->entityPosition = kPosition_5790; getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityFrancois); callbackAction(); break; @@ -996,8 +1004,22 @@ label_callback_4: } label_callback_5: - if (getInventory()->get(kItemWhistle)->location != kObjectLocation3) { - // TODO: do we also need to check if the whistle is in the inventory? + if (getInventory()->get(kItemBeetle)->location != kObjectLocation3) { + if (!getInventory()->hasItem(kItemWhistle) && getInventory()->get(kItemWhistle)->location != kObjectLocation3) { + // BUG in the original game: condition is always false + if (getState()->time < kTime1782000 && getState()->time > kTime1782000 && !params->param8) { + params->param8 = 1; + setCallback(9); + setup_takeWalk(); + break; + } + if (getState()->time < kTime1813500 && getState()->time > kTime1813500 && !CURRENT_PARAM(1, 1)) { + CURRENT_PARAM(1, 1) = 1; + setCallback(10); + setup_takeWalk(); + break; + } + } break; } @@ -1010,11 +1032,11 @@ label_callback_5: } label_callback_6: - if (timeCheckCallbackCompartment(kTime1782000, params->param6, 7, kObjectCompartmentC, kPosition_6470, "c")) + if (timeCheckCallbackCompartment(kTime1782000, params->param6, 7, kObjectCompartmentF, kPosition_4070, "f")) break; label_callback_7: - timeCheckCallbackCompartment(kTime1813500, params->param7, 8, kObjectCompartmentF, kPosition_4070, "f"); + timeCheckCallbackCompartment(kTime1813500, params->param7, 8, kObjectCompartmentC, kPosition_6470, "c"); break; case kActionCallback: @@ -1128,13 +1150,13 @@ label_callback_10: } label_callback_11: - if (getInventory()->get(kItemWhistle)->location == kObjectLocation3) { + if (getInventory()->get(kItemBeetle)->location == kObjectLocation3) { if (getState()->time <= kTimeEnd) - if (!getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 2000) || !params->param4) - params->param4 = (uint)(getState()->time + 75); + if (!getEntities()->isDistanceBetweenEntities(kEntityFrancois, kEntityPlayer, 2000) || !CURRENT_PARAM(1, 4)) + CURRENT_PARAM(1, 4) = (uint)(getState()->time + 75); - if (params->param4 < getState()->time || getState()->time > kTimeEnd) { - params->param4 = kTimeInvalid; + if (CURRENT_PARAM(1, 4) < getState()->time || getState()->time > kTimeEnd) { + CURRENT_PARAM(1, 4) = kTimeInvalid; setCallback(12); setup_playSound("Fra2010"); @@ -1146,11 +1168,11 @@ label_callback_12: break; label_callback_13: - if (timeCheckCallbackCompartment(kTime2040300, CURRENT_PARAM(1, 6), 14, kObjectCompartmentF, kPosition_4070, "f")) + if (timeCheckCallbackCompartment(kTime2146500, CURRENT_PARAM(1, 6), 14, kObjectCompartmentF, kPosition_4070, "f")) break; label_callback_14: - timeCheckCallbackCompartment(kTime2040300, CURRENT_PARAM(1, 7), 15, kObjectCompartmentB, kPosition_7500, "b"); + timeCheckCallbackCompartment(kTime2218500, CURRENT_PARAM(1, 7), 15, kObjectCompartmentB, kPosition_7500, "b"); } } break; diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp index 572f47c99a..981ad461d6 100644 --- a/engines/lastexpress/entities/gendarmes.cpp +++ b/engines/lastexpress/entities/gendarmes.cpp @@ -37,14 +37,14 @@ namespace LastExpress { Gendarmes::Gendarmes(LastExpressEngine *engine) : Entity(engine, kEntityGendarmes) { ADD_CALLBACK_FUNCTION(Gendarmes, reset); ADD_CALLBACK_FUNCTION(Gendarmes, chapter1); - ADD_CALLBACK_FUNCTION(Gendarmes, doDraw); - ADD_CALLBACK_FUNCTION(Gendarmes, doDialog); - ADD_CALLBACK_FUNCTION(Gendarmes, doDialogFullVolume); - ADD_CALLBACK_FUNCTION(Gendarmes, doWait); - ADD_CALLBACK_FUNCTION(Gendarmes, savegame); - ADD_CALLBACK_FUNCTION(Gendarmes, doWalk); - ADD_CALLBACK_FUNCTION(Gendarmes, doCompartment); - ADD_CALLBACK_FUNCTION(Gendarmes, trappedCath); + ADD_CALLBACK_FUNCTION_S(Gendarmes, doDraw); + ADD_CALLBACK_FUNCTION_S(Gendarmes, doDialog); + ADD_CALLBACK_FUNCTION_S(Gendarmes, doDialogFullVolume); + ADD_CALLBACK_FUNCTION_I(Gendarmes, doWait); + ADD_CALLBACK_FUNCTION_II(Gendarmes, savegame); + ADD_CALLBACK_FUNCTION_II(Gendarmes, doWalk); + ADD_CALLBACK_FUNCTION_TYPE3(Gendarmes, doCompartment, EntityParametersIISS, EntityParametersSSS, EntityParametersISII); + ADD_CALLBACK_FUNCTION_III(Gendarmes, trappedCath); ADD_CALLBACK_FUNCTION(Gendarmes, chapter1Handler); ADD_CALLBACK_FUNCTION(Gendarmes, searchTrain); ADD_CALLBACK_FUNCTION(Gendarmes, function13); @@ -156,7 +156,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, doCompartment, CarIndex, EntityPosition) parameters2->param7 = kPosition_7850; } - if (params->param1 == kCarBaggageRear) + if (params->param1 == kCarRedSleeping) parameters2->param5 += 31; // Switch to next compartment car if (parameters2->param6) { @@ -184,7 +184,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, doCompartment, CarIndex, EntityPosition) setup_trappedCath((CarIndex)params->param1, (EntityPosition)params->param2, (ObjectIndex)parameters2->param5); } else { getEntities()->drawSequenceLeft(kEntityGendarmes, (char *)¶meters1->seq1); - getEntities()->enterCompartment(kEntityGendarmes, (ObjectIndex)CURRENT_PARAM(2, 5)); + getEntities()->enterCompartment(kEntityGendarmes, (ObjectIndex)CURRENT_PARAM(2, 5), true); setCallback(parameters2->param6 ? 2 : 3); setup_doDialog(parameters2->param6 ? "POL1044A" : "POL1044B"); @@ -234,7 +234,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, doCompartment, CarIndex, EntityPosition) case 6: getData()->location = kLocationOutsideCompartment; - getEntities()->exitCompartment(kEntityGendarmes, (ObjectIndex)parameters2->param5); + getEntities()->exitCompartment(kEntityGendarmes, (ObjectIndex)parameters2->param5, true); callbackAction(); break; } @@ -249,10 +249,10 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, trappedCath, CarIndex, EntityPosition, Obj break; case kActionNone: - if (!params->param5 || getState()->timeTicks > (uint32)params->param5) { - if (!params->param5) - params->param5 = getState()->timeTicks + 75; + if (!params->param5) + params->param5 = getState()->timeTicks + 75; + if (getState()->timeTicks > (uint32)params->param5) { if (!getEntities()->isOutsideAlexeiWindow() && getObjects()->get((ObjectIndex)params->param3).status != kObjectLocation1) { setCallback(2); setup_savegame(kSavegameTypeEvent, kEventGendarmesArrestation); @@ -321,7 +321,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, trappedCath, CarIndex, EntityPosition, Obj break; case 3: - getAction()->playAnimation((params->param1 < kCarRedSleeping) ? kEventMertensBloodJacket : kEventCoudertBloodJacket); + getAction()->playAnimation((params->param1 == kCarGreenSleeping) ? kEventMertensBloodJacket : kEventCoudertBloodJacket); getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverBloodJacket, true); getObjects()->update((ObjectIndex)params->param3, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); @@ -338,6 +338,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, trappedCath, CarIndex, EntityPosition, Obj case 5: getObjects()->update((ObjectIndex)params->param3, kEntityGendarmes, getObjects()->get((ObjectIndex)params->param3).status, kCursorNormal, kCursorHand); + params->param4 = 1; break; case 6: @@ -574,7 +575,7 @@ void Gendarmes::handleAction(const SavePoint &savepoint, bool shouldPlaySound, S ENTITY_PARAM(0, 1) = 1; } - if (getEntities()->isDistanceBetweenEntities(kEntityGendarmes, kEntityPlayer, 1000) && !getEntityData(kEntityPlayer)->location) { + if (getEntities()->isDistanceBetweenEntities(kEntityGendarmes, kEntityPlayer, shouldUpdateEntity ? 1750 : 1000) && !getEntityData(kEntityPlayer)->location) { if (shouldUpdateEntity) if (getEntities()->isPlayerPosition(kCarRedSleeping, 22) && !getEntities()->isDistanceBetweenEntities(kEntityGendarmes, kEntityPlayer, 250)) @@ -585,13 +586,21 @@ void Gendarmes::handleAction(const SavePoint &savepoint, bool shouldPlaySound, S } break; + case kActionEndSound: + if (shouldPlaySound && !checkCallback && !shouldUpdateEntity) { + callbackAction(); + } + break; + case kActionExitCompartment: - callbackAction(); + if (!shouldPlaySound && !checkCallback && !shouldUpdateEntity) { + callbackAction(); + } break; case kActionDefault: // Only handle when passing SIIS params - if (!checkCallback) { + if (!checkCallback && !shouldUpdateEntity) { EXPOSE_PARAMS(EntityData::EntityParametersSIIS); if (!shouldPlaySound) diff --git a/engines/lastexpress/entities/hadija.cpp b/engines/lastexpress/entities/hadija.cpp index eb255d77f8..d925dd1163 100644 --- a/engines/lastexpress/entities/hadija.cpp +++ b/engines/lastexpress/entities/hadija.cpp @@ -34,10 +34,10 @@ 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_SI(Hadija, enterExitCompartment); + ADD_CALLBACK_FUNCTION_S(Hadija, playSound); + ADD_CALLBACK_FUNCTION_I(Hadija, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Hadija, updateEntity); ADD_CALLBACK_FUNCTION(Hadija, peekF); ADD_CALLBACK_FUNCTION(Hadija, peekH); ADD_CALLBACK_FUNCTION(Hadija, goFtoH); @@ -151,15 +151,15 @@ label_callback2: return; } } - - if (params->param3 >= getState()->time) - return; } + if (getState()->time > kTime1134000 || getState()->time > params->param3) { - params->param3 = kTimeInvalid; + params->param3 = kTimeInvalid; - setCallback(3); - setup_peekH(); + setCallback(3); + setup_peekH(); + break; + } } label_callback3: @@ -343,10 +343,6 @@ label_callback4: } break; - case kActionDefault: - getSavePoints()->push(kEntityAlouan, kEntityTrain, kAction191070912, kPosition_4840); - break; - case kActionCallback: switch (getCallback()) { default: diff --git a/engines/lastexpress/entities/ivo.cpp b/engines/lastexpress/entities/ivo.cpp index 12a23e7d37..bd38d69b8d 100644 --- a/engines/lastexpress/entities/ivo.cpp +++ b/engines/lastexpress/entities/ivo.cpp @@ -38,15 +38,15 @@ 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_S(Ivo, draw); + ADD_CALLBACK_FUNCTION_SI(Ivo, enterExitCompartment); + ADD_CALLBACK_FUNCTION_I(Ivo, updateFromTime); + ADD_CALLBACK_FUNCTION_I(Ivo, updateFromTicks); + ADD_CALLBACK_FUNCTION_II(Ivo, updateEntity); ADD_CALLBACK_FUNCTION(Ivo, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Ivo, playSound); + ADD_CALLBACK_FUNCTION_S(Ivo, playSound); ADD_CALLBACK_FUNCTION(Ivo, callbackActionRestaurantOrSalon); - ADD_CALLBACK_FUNCTION(Ivo, savegame); + ADD_CALLBACK_FUNCTION_II(Ivo, savegame); ADD_CALLBACK_FUNCTION(Ivo, goCompartment); ADD_CALLBACK_FUNCTION(Ivo, sitAtTableWithSalko); ADD_CALLBACK_FUNCTION(Ivo, leaveTableWithSalko); @@ -270,6 +270,7 @@ IMPLEMENT_FUNCTION(15, Ivo, chapter1Handler) case kActionNone: getData()->entityPosition = getEntityData(kEntityMilos)->entityPosition; getData()->location = getEntityData(kEntityMilos)->location; + getData()->car = getEntityData(kEntityMilos)->car; break; case kActionCallback: @@ -318,7 +319,7 @@ IMPLEMENT_FUNCTION(16, Ivo, inCompartment) case 1: getEntities()->drawSequenceLeft(kEntityIvo, "613Ch"); - getEntities()->enterCompartment(kEntityIvo, kObjectCompartmentH); + getEntities()->enterCompartment(kEntityIvo, kObjectCompartmentH, true); getSavePoints()->push(kEntityIvo, kEntityCoudert, kAction88652208); break; @@ -384,7 +385,7 @@ IMPLEMENT_FUNCTION(18, Ivo, chapter2) getData()->inventoryItem = kItemNone; getObjects()->update(kObjectCompartmentH, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); - getObjects()->update(kObject47, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); + getObjects()->update(kObject47, kEntityPlayer, kObjectLocation1, kCursorKeepValue, kCursorKeepValue); break; } @@ -744,7 +745,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(31, Ivo, chapter5Handler) - if (savepoint.action == kActionProceedChapter5) + if (savepoint.action == kAction192637492) setup_fightCath(); IMPLEMENT_FUNCTION_END @@ -780,7 +781,7 @@ IMPLEMENT_FUNCTION(32, Ivo, fightCath) case 2: params->param1 = getFight()->setup(kFightIvo); if (params->param1) { - getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true); + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, params->param1 == Fight::kFightEndLost); } else { getScenes()->loadSceneFromPosition(kCarBaggageRear, 96); setup_knockedOut(); diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp index 047e3f0bd9..3b150531f5 100644 --- a/engines/lastexpress/entities/kahina.cpp +++ b/engines/lastexpress/entities/kahina.cpp @@ -39,14 +39,14 @@ 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, lookingForCath); - ADD_CALLBACK_FUNCTION(Kahina, updateEntity2); - ADD_CALLBACK_FUNCTION(Kahina, updateEntity); - ADD_CALLBACK_FUNCTION(Kahina, enterExitCompartment); + ADD_CALLBACK_FUNCTION_S(Kahina, playSound); + ADD_CALLBACK_FUNCTION_II(Kahina, savegame); + ADD_CALLBACK_FUNCTION_I(Kahina, updateFromTime); + ADD_CALLBACK_FUNCTION_I(Kahina, updateFromTicks); + ADD_CALLBACK_FUNCTION_I(Kahina, lookingForCath); + ADD_CALLBACK_FUNCTION_II(Kahina, updateEntity2); + ADD_CALLBACK_FUNCTION_II(Kahina, updateEntity); + ADD_CALLBACK_FUNCTION_SI(Kahina, enterExitCompartment); ADD_CALLBACK_FUNCTION(Kahina, chapter1); ADD_CALLBACK_FUNCTION(Kahina, chapter1Handler); ADD_CALLBACK_FUNCTION(Kahina, awaitingCath); @@ -56,7 +56,7 @@ Kahina::Kahina(LastExpressEngine *engine) : Entity(engine, kEntityKahina) { ADD_CALLBACK_FUNCTION(Kahina, chapter2); ADD_CALLBACK_FUNCTION(Kahina, inSeclusionPart2); ADD_CALLBACK_FUNCTION(Kahina, chapter3); - ADD_CALLBACK_FUNCTION(Kahina, function19); + ADD_CALLBACK_FUNCTION_II(Kahina, function19); ADD_CALLBACK_FUNCTION(Kahina, beforeConcert); ADD_CALLBACK_FUNCTION(Kahina, concert); ADD_CALLBACK_FUNCTION(Kahina, finished); @@ -194,12 +194,12 @@ IMPLEMENT_FUNCTION_II(7, Kahina, updateEntity2, CarIndex, EntityPosition) default: break; - case kActionNone: + case kActionDefault: if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) callbackAction(); break; - case kActionDefault: + case kActionNone: if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2)) { callbackAction(); } else if (getEntities()->isDistanceBetweenEntities(kEntityKahina, kEntityPlayer, 1000) @@ -579,14 +579,14 @@ IMPLEMENT_FUNCTION(17, Kahina, inSeclusionPart2) break; case kActionNone: - if (params->param1) { + if (!params->param1) { if (Entity::updateParameter(params->param2, getState()->time, 9000)) { params->param1 = 1; params->param2 = 0; } } - if (getEvent(kEventKahinaAskSpeakFirebird) && getEvent(kEventKronosConversationFirebird) && getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { + if (getEvent(kEventKahinaAskSpeakFirebird) && !getEvent(kEventKronosConversationFirebird) && getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { if (Entity::updateParameter(params->param3, getState()->time, 900)) { setCallback(1); setup_savegame(kSavegameTypeEvent, kEventKronosConversationFirebird); @@ -927,7 +927,7 @@ IMPLEMENT_FUNCTION(21, Kahina, concert) if (!params->param3) params->param3 = (uint)getState()->time + 4500; - if (params->param6 != kTimeInvalid) { + if (params->param5 != kTimeInvalid) { if (Entity::updateParameterTime((TimeValue)params->param3, (getEntities()->isPlayerPosition(kCarKronos, 80) || getEntities()->isPlayerPosition(kCarKronos, 88)), params->param5, 0)) { setCallback(2); setup_findFirebird(); @@ -1043,7 +1043,7 @@ IMPLEMENT_FUNCTION(22, Kahina, finished) break; case kActionDrawScene: - if (getData()->car > kCarGreenSleeping || (getData()->car == kCarGreenSleeping && getData()->entityPosition > kPosition_2740)) + if (getEntityData(kEntityPlayer)->car > kCarGreenSleeping || (getEntityData(kEntityPlayer)->car == kCarGreenSleeping && getEntityData(kEntityPlayer)->entityPosition > kPosition_2740)) params->param1 = 1; break; } @@ -1181,7 +1181,7 @@ IMPLEMENT_FUNCTION(24, Kahina, seekCath) case 2: if (getEntityData(kEntityPlayer)->entityPosition >= getData()->entityPosition) - getAction()->playAnimation(getData()->car < kCarRedSleeping ? kEventKahinaGunYellow : kEventKahinaGunBlue); + getAction()->playAnimation(getData()->car == kCarRedSleeping ? kEventKahinaGunYellow : kEventKahinaGunBlue); else getAction()->playAnimation(kEventKahinaGun); @@ -1396,7 +1396,7 @@ IMPLEMENT_FUNCTION(26, Kahina, searchTatiana) break; case 1: - if (getEntities()->checkFields19(kEntityPlayer, kCarGreenSleeping, kPosition_7850)) { + if (getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_7850)) { setCallback(2); setup_function19(kCarRedSleeping, kPosition_9460); } else { diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp index 61c164115b..60be35e8fa 100644 --- a/engines/lastexpress/entities/kronos.cpp +++ b/engines/lastexpress/entities/kronos.cpp @@ -63,11 +63,11 @@ static const struct { 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_II(Kronos, savegame); + ADD_CALLBACK_FUNCTION_II(Kronos, updateEntity); + ADD_CALLBACK_FUNCTION_S(Kronos, playSound); + ADD_CALLBACK_FUNCTION_I(Kronos, updateFromTime); + ADD_CALLBACK_FUNCTION_I(Kronos, updateFromTicks); ADD_CALLBACK_FUNCTION(Kronos, chapter1); ADD_CALLBACK_FUNCTION(Kronos, chapter1Handler); ADD_CALLBACK_FUNCTION(Kronos, greetCath); @@ -147,7 +147,16 @@ IMPLEMENT_FUNCTION(8, Kronos, chapter1Handler) break; case kActionNone: - Entity::timeCheck(kTime1489500, params->param2, WRAP_SETUP_FUNCTION(Kronos, setup_function11)); + if (Entity::timeCheck(kTime1489500, params->param2, WRAP_SETUP_FUNCTION(Kronos, setup_function11))) + break; + + if (params->param1 && getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { + if (Entity::updateParameter(params->param3, getState()->timeTicks, 150)) { + setup_greetCath(); + break; + } + } + break; case kAction171849314: @@ -260,7 +269,7 @@ IMPLEMENT_FUNCTION(14, Kronos, chapter3Handler) break; case kActionNone: - if (getState()->time > kTime1993500 && !params->param1 && !params->param2 && !params->param3) + if (getState()->time > kTime1993500 && params->param1 && params->param2 && params->param3) setup_function15(); break; @@ -301,7 +310,7 @@ IMPLEMENT_FUNCTION(15, Kronos, function15) if (params->param3 != kTimeInvalid && getState()->time > kTime2002500) { if (getState()->time <= kTime2052000) { - if (!getEntities()->isInSalon(kEntityPlayer) || getEntities()->isInSalon(kEntityPlayer) || !params->param3) + if (!getEntities()->isInSalon(kEntityPlayer) || getEntities()->isInSalon(kEntityBoutarel) || !params->param3) params->param3 = (uint)getState()->time + 900; if (params->param3 >= getState()->time) @@ -381,7 +390,7 @@ IMPLEMENT_FUNCTION(17, Kronos, returnCompartment) getData()->car = kCarRedSleeping; setCallback(1); - setup_updateEntity(kCarGreenSleeping, kPosition_9270); + setup_updateEntity(kCarKronos, kPosition_9270); break; case kActionCallback: @@ -435,6 +444,19 @@ IMPLEMENT_FUNCTION(19, Kronos, startConcert) break; case kActionNone: + if (getState()->time > kTime2115000 && !params->param1) { + params->param1 = 1; + getSound()->playSound(kEntityKronos, "1917.lnk"); + setup_duringConcert(); + break; + } + + if (getEntities()->isInKronosSanctum(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunchSuite4); + break; + } + break; case kActionDefault: @@ -442,6 +464,14 @@ IMPLEMENT_FUNCTION(19, Kronos, startConcert) break; case kActionDrawScene: + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos) + && !getEntities()->isInKronosSanctum(kEntityPlayer) + && !getInventory()->hasItem(kItemFirebird) + && !getEvent(kEventConcertStart)) { + getEntities()->drawSequenceLeft(kEntityKronos, "201a"); + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventConcertStart); + } break; case kActionCallback: @@ -479,6 +509,7 @@ IMPLEMENT_FUNCTION(20, Kronos, duringConcert) break; case kActionNone: + // TODO: should *2 really be there? should it be /2? params->param5 = getSoundQueue()->getEntryTime(kEntityKronos)* 2; if (params->param6 < ARRAYSIZE(concertData) && params->param5 > concertData[params->param6].time) { @@ -734,12 +765,14 @@ IMPLEMENT_FUNCTION(22, Kronos, awaitingCath) break; case kActionNone: - if (getProgress().field_44) { - setCallback(5); - setup_savegame(kSavegameTypeEvent, kEventKahinaPunchBaggageCarEntrance); - } else { - setCallback(6); - setup_savegame(kSavegameTypeEvent, kEventKahinaWrongDoor); + if (getEntities()->isInKronosSanctum(kEntityPlayer)) { + if (getProgress().field_44) { + setCallback(5); + setup_savegame(kSavegameTypeEvent, kEventKahinaPunchBaggageCarEntrance); + } else { + setCallback(6); + setup_savegame(kSavegameTypeEvent, kEventKahinaWrongDoor); + } } break; diff --git a/engines/lastexpress/entities/mahmud.cpp b/engines/lastexpress/entities/mahmud.cpp index 08edda5276..9f43c695ea 100644 --- a/engines/lastexpress/entities/mahmud.cpp +++ b/engines/lastexpress/entities/mahmud.cpp @@ -41,15 +41,15 @@ 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_S(Mahmud, draw); + ADD_CALLBACK_FUNCTION_SI(Mahmud, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SIII(Mahmud, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_S(Mahmud, playSound); + ADD_CALLBACK_FUNCTION_S(Mahmud, playSoundMertens); + ADD_CALLBACK_FUNCTION_I(Mahmud, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Mahmud, savegame); + ADD_CALLBACK_FUNCTION_II(Mahmud, updateEntity); + ADD_CALLBACK_FUNCTION_II(Mahmud, function10); ADD_CALLBACK_FUNCTION(Mahmud, function11); ADD_CALLBACK_FUNCTION(Mahmud, function12); ADD_CALLBACK_FUNCTION(Mahmud, function13); @@ -128,7 +128,7 @@ IMPLEMENT_FUNCTION_END IMPLEMENT_FUNCTION_II(9, Mahmud, updateEntity, CarIndex, EntityPosition) if (savepoint.action == kActionExcuseMeCath) { if (getInventory()->hasItem(kItemPassengerList)) - getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1025" : "CAT1025Q"); + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1025" : "CAT1025A"); else getSound()->excuseMeCath(); @@ -189,7 +189,7 @@ IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) break; case 1: - getSound()->playSound(kEntityMahmud, "MAH1174"); + getSound()->playSound(kEntityMahmud, params->param2 ? "MAH1170E" : "MAH1173A"); break; case 2: @@ -197,7 +197,7 @@ IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) break; case 3: - getSound()->playSound(kEntityMahmud, params->param2 ? "MAH1170E" : "MAH1173A"); + getSound()->playSound(kEntityMahmud, "MAH1174"); break; } } @@ -720,7 +720,7 @@ IMPLEMENT_FUNCTION(14, Mahmud, chaptersHandler) break; case kAction290410610: - params->param3 = (params->param3 < 1) ? 1 : 0; + params->param3 = (params->param3 == 0) ? 1 : 0; setCallback(11); setup_function10((ObjectIndex)savepoint.param.intValue, (bool)params->param3); break; diff --git a/engines/lastexpress/entities/max.cpp b/engines/lastexpress/entities/max.cpp index d75b6af7f5..180bc1d1ca 100644 --- a/engines/lastexpress/entities/max.cpp +++ b/engines/lastexpress/entities/max.cpp @@ -38,10 +38,10 @@ 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_S(Max, playSound); + ADD_CALLBACK_FUNCTION_S(Max, draw); + ADD_CALLBACK_FUNCTION_SI(Max, enterExitCompartment); + ADD_CALLBACK_FUNCTION_II(Max, savegame); ADD_CALLBACK_FUNCTION(Max, withAnna); ADD_CALLBACK_FUNCTION(Max, guardingCompartment); ADD_CALLBACK_FUNCTION(Max, inCageFriendly); @@ -95,12 +95,12 @@ IMPLEMENT_FUNCTION(6, Max, withAnna) if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); params->param2 = 0; break; case kActionDefault: - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); break; case kAction71277948: @@ -111,7 +111,7 @@ IMPLEMENT_FUNCTION(6, Max, withAnna) case kAction158007856: if (!getSoundQueue()->isBuffered(kEntityMax)) { getSound()->playSound(kEntityMax, "Max1122"); - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); } break; } @@ -130,7 +130,7 @@ IMPLEMENT_FUNCTION(7, Max, guardingCompartment) if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); params->param2 = 0; break; @@ -147,7 +147,7 @@ IMPLEMENT_FUNCTION(7, Max, guardingCompartment) break; case kActionDefault: - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); getData()->entityPosition = kPosition_4070; getData()->location = kLocationInsideCompartment; @@ -160,7 +160,7 @@ IMPLEMENT_FUNCTION(7, Max, guardingCompartment) case kActionDrawScene: if (!getSoundQueue()->isBuffered(kEntityMax)) { if (getEntities()->isPlayerPosition(kCarRedSleeping, 56) || getEntities()->isPlayerPosition(kCarRedSleeping, 78)) - getSound()->playSound(kEntityMax, "Max1120"); + getSound()->playSound(kEntityMax, "MAX1120"); } break; @@ -173,7 +173,7 @@ IMPLEMENT_FUNCTION(7, Max, guardingCompartment) case 1: case 2: setCallback(3); - setup_playSound("Max1122"); + setup_playSound("MAX1122"); break; case 3: @@ -201,7 +201,7 @@ IMPLEMENT_FUNCTION(7, Max, guardingCompartment) case kAction158007856: if (!getSoundQueue()->isBuffered(kEntityMax)) { getSound()->playSound(kEntityMax, "Max1122"); - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); } break; } @@ -220,7 +220,7 @@ IMPLEMENT_FUNCTION(8, Max, inCageFriendly) if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max3101"); - params->param2 = 255 * (4 * rnd(20) + 40); + params->param2 = 225 * (4 * rnd(4) + 8); params->param3 = 0; break; @@ -241,7 +241,7 @@ IMPLEMENT_FUNCTION(8, Max, inCageFriendly) break; case kActionDefault: - params->param2 = 255 * (4 * rnd(20) + 40); + params->param2 = 225 * (4 * rnd(4) + 8); getObjects()->update(kObjectCageMax, kEntityMax, kObjectLocationNone, kCursorNormal, kCursorHand); getEntities()->clearSequences(kEntityMax); @@ -360,7 +360,7 @@ IMPLEMENT_FUNCTION(11, Max, chapter2) IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// -IMPLEMENT_FUNCTION(13, Max, chapter3) +IMPLEMENT_FUNCTION(12, Max, chapter3) switch (savepoint.action) { default: break; @@ -390,6 +390,8 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler) case kActionNone: if (params->param2) { getData()->entityPosition = getEntityData(kEntityCoudert)->entityPosition; + getData()->location = getEntityData(kEntityCoudert)->location; + getData()->car = getEntityData(kEntityCoudert)->car; break; } @@ -399,12 +401,12 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler) if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); params->param3 = 0; break; case kActionDefault: - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); getData()->entityPosition = kPosition_4070; getData()->location = kLocationInsideCompartment; @@ -430,7 +432,7 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler) if (!getSoundQueue()->isBuffered(kEntityMax)) { getSound()->playSound(kEntityMax, "Max1122"); - params->param1 = 255 * (4 * rnd(20) + 40); + params->param1 = 225 * (4 * rnd(20) + 40); } break; } @@ -450,7 +452,7 @@ IMPLEMENT_FUNCTION(14, Max, inCageMad) // Save game after freeing Max from his cage case kActionOpenDoor: if (getEvent(kEventCathMaxCage)) { - if (getEvent(kEventCathMaxFree)) { + if (!getEvent(kEventCathMaxFree)) { setCallback(2); setup_savegame(kSavegameTypeEvent, kEventCathMaxFree); } @@ -512,6 +514,7 @@ IMPLEMENT_FUNCTION(15, Max, letMeIn) case kActionNone: if (params->param2) { getData()->entityPosition = getEntityData(kEntityCoudert)->entityPosition; + getData()->location = getEntityData(kEntityCoudert)->location; getData()->car = getEntityData(kEntityCoudert)->car; } @@ -532,7 +535,7 @@ IMPLEMENT_FUNCTION(15, Max, letMeIn) getSound()->playSound(kEntityMax, "Max3010"); setCallback(1); - setup_enterExitCompartment("630Bf", kObjectCompartment4); + setup_enterExitCompartment("630Bf", kObjectCompartmentF); break; case kActionCallback: @@ -585,6 +588,7 @@ IMPLEMENT_FUNCTION(17, Max, function17) case kActionNone: if (params->param1) { getData()->entityPosition = getEntityData(kEntityCoudert)->entityPosition; + getData()->location = getEntityData(kEntityCoudert)->location; getData()->car = getEntityData(kEntityCoudert)->car; } break; diff --git a/engines/lastexpress/entities/mertens.cpp b/engines/lastexpress/entities/mertens.cpp index 7126adbfdc..573a35013e 100644 --- a/engines/lastexpress/entities/mertens.cpp +++ b/engines/lastexpress/entities/mertens.cpp @@ -40,36 +40,36 @@ namespace LastExpress { 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_S(Mertens, bloodJacket); + ADD_CALLBACK_FUNCTION_SI(Mertens, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(Mertens, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_SIII(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_S(Mertens, playSound); + ADD_CALLBACK_FUNCTION_S(Mertens, playSound16); + ADD_CALLBACK_FUNCTION_II(Mertens, savegame); + ADD_CALLBACK_FUNCTION_II(Mertens, updateEntity); + ADD_CALLBACK_FUNCTION_I(Mertens, function11); + ADD_CALLBACK_FUNCTION_I(Mertens, bonsoir); + ADD_CALLBACK_FUNCTION_II(Mertens, function13); + ADD_CALLBACK_FUNCTION_I(Mertens, function14); + ADD_CALLBACK_FUNCTION_I(Mertens, function15); + ADD_CALLBACK_FUNCTION_I(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_II(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_I(Mertens, function26); + ADD_CALLBACK_FUNCTION_I(Mertens, tylerCompartment); + ADD_CALLBACK_FUNCTION_S(Mertens, function28); + ADD_CALLBACK_FUNCTION_SS(Mertens, function29); + ADD_CALLBACK_FUNCTION_I(Mertens, function30); + ADD_CALLBACK_FUNCTION_I(Mertens, function31); ADD_CALLBACK_FUNCTION(Mertens, function32); ADD_CALLBACK_FUNCTION(Mertens, function33); ADD_CALLBACK_FUNCTION(Mertens, chapter1); @@ -107,7 +107,7 @@ IMPLEMENT_FUNCTION_S(2, Mertens, bloodJacket) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionExitCompartment: @@ -134,7 +134,7 @@ IMPLEMENT_FUNCTION_SI(3, Mertens, enterExitCompartment, ObjectIndex) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); return; case kActionCallback: @@ -155,7 +155,7 @@ IMPLEMENT_FUNCTION_SI(4, Mertens, enterExitCompartment2, ObjectIndex) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); return; case kAction4: @@ -181,7 +181,7 @@ IMPLEMENT_FUNCTION_SIII(5, Mertens, enterExitCompartment3, ObjectIndex, EntityPo break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionExitCompartment: @@ -223,7 +223,7 @@ IMPLEMENT_FUNCTION(6, Mertens, callbackActionOnDirection) break; } - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionExitCompartment: @@ -246,7 +246,7 @@ IMPLEMENT_FUNCTION_S(7, Mertens, playSound) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionEndSound: @@ -273,7 +273,7 @@ IMPLEMENT_FUNCTION_S(8, Mertens, playSound16) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(1); break; case kActionEndSound: @@ -352,6 +352,7 @@ IMPLEMENT_FUNCTION_II(10, Mertens, updateEntity, CarIndex, EntityPosition) case kAction1: params->param3 = 0; + getData()->inventoryItem = kItemNone; if (getProgress().eventCorpseFound || getEvent(kEventMertensAskTylerCompartment) || getEvent(kEventMertensAskTylerCompartmentD)) { if (ENTITY_PARAM(0, 4) && getProgress().jacket == kJacketGreen && !getEvent(kEventMertensDontMakeBed) && !getProgress().eventCorpseThrown) { setCallback(6); @@ -462,7 +463,8 @@ IMPLEMENT_FUNCTION_I(11, Mertens, function11, uint32) break; case kActionNone: - Entity::savegameBloodJacket(); + if (Entity::savegameBloodJacket(1)) + break; if (!Entity::updateParameter(params->param2, getState()->time, params->param1)) break; @@ -483,7 +485,7 @@ IMPLEMENT_FUNCTION_END IMPLEMENT_FUNCTION_I(12, Mertens, bonsoir, EntityIndex) EntityIndex entity = (EntityIndex)params->param1; - if (savepoint.action == kActionDefault) + if (savepoint.action != kActionDefault) return; if (getSoundQueue()->isBuffered(kEntityMertens)) { @@ -495,7 +497,7 @@ IMPLEMENT_FUNCTION_I(12, Mertens, bonsoir, EntityIndex) if (Entities::isFemale(entity)) { getSound()->playSound(kEntityMertens, rnd(2) ? "CON1112" : "CON1112A"); } else { - if (entity || getProgress().field_18 != 2) { + if (entity != kEntityPlayer || getProgress().field_18 != 2) { getSound()->playSound(kEntityMertens, "CON1112F"); } else { switch (rnd(3)) { @@ -525,15 +527,16 @@ IMPLEMENT_FUNCTION_I(12, Mertens, bonsoir, EntityIndex) IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// -IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) +IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, EntityIndex) switch (savepoint.action) { default: break; case kActionNone: - Entity::savegameBloodJacket(); + if (Entity::savegameBloodJacket(4)) + break; - if (!params->param2 && !params->param3) { + if (params->param2 == kEntityPlayer && !params->param3) { if (Entity::updateParameter(params->param4, getState()->timeTicks, 75)) { getData()->inventoryItem = kItemNone; setCallback(5); @@ -569,11 +572,29 @@ IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) break; case kActionDefault: - if (params->param2) + if (params->param2 != kEntityPlayer) params->param3 = 1; if (!getSoundQueue()->isBuffered(kEntityMertens)) { - + if (getProgress().chapter == kChapter3 && !params->param1 && getState()->time < kTime2173500 && + (getState()->time > kTime2106000 || params->param2 != kEntityPlayer && getState()->time > kTime2079000)) { + // guide guests to the concert + if (params->param2 == kEntityAugust) + getSound()->playSound(kEntityMertens, "CON3052"); + else if (Entities::isFemale((EntityIndex)params->param2)) + getSound()->playSound(kEntityMertens, "CON3051"); + else if (params->param2 == kEntityPlayer) + getSound()->playSound(kEntityMertens, getProgress().field_40 ? "CON3054" : "CON3053"); + else { + setCallback(1); + setup_bonsoir((EntityIndex)params->param2); + break; + } + } else { + setCallback(2); + setup_bonsoir((EntityIndex)params->param2); + break; + } } setCallback(3); @@ -583,7 +604,7 @@ IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) case kAction16: params->param3--; - if (params->param2 && !params->param3) { + if (params->param2 != kEntityPlayer && !params->param3) { getData()->inventoryItem = kItemNone; setCallback(10); setup_function18(); @@ -594,6 +615,12 @@ IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23) && ENTITY_PARAM(0, 7) && !getEvent(kEventKronosConversation)) { setCallback(8); setup_savegame(kSavegameTypeEvent, kEventMertensKronosInvitation); + break; + } + if (!params->param3) { + getData()->inventoryItem = kItemNone; + setCallback(9); + setup_function18(); } break; @@ -631,13 +658,14 @@ IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) case 8: getAction()->playAnimation(kEventMertensKronosInvitation); + getProgress().eventMertensKronosInvitation = true; ENTITY_PARAM(0, 6) = 0; ENTITY_PARAM(0, 7) = 0; getScenes()->processScene(); if (!params->param3) { getData()->inventoryItem = kItemNone; - setCallback(10); + setCallback(9); setup_function18(); } break; @@ -653,7 +681,7 @@ IMPLEMENT_FUNCTION_I(14, Mertens, function14, EntityIndex) break; case kActionNone: - Entity::savegameBloodJacket(); + Entity::savegameBloodJacket(4); break; case kActionDefault: @@ -1167,7 +1195,7 @@ IMPLEMENT_FUNCTION(22, Mertens, function22) case 4: getEntities()->drawSequenceLeft(kEntityMertens, "601Nh"); - getEntities()->enterCompartment(kEntityMertens, kObjectCompartment8); + getEntities()->enterCompartment(kEntityMertens, kObjectCompartment8, true); getSavePoints()->push(kEntityMertens, kEntityMahmud, kAction225563840); break; @@ -1257,7 +1285,7 @@ IMPLEMENT_FUNCTION(23, Mertens, function23) break; case 4: - getEntities()->exitCompartment(kEntityMertens, kObjectCompartment4); + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment4, true); getData()->location = kLocationInsideCompartment; getEntities()->clearSequences(kEntityMertens); @@ -1669,7 +1697,7 @@ label_callback11: break; } } else { - setCallback(26); + setCallback(19); setup_function26(false); } @@ -1742,7 +1770,7 @@ label_callback11: case kActionKnock: if (params->param1) { - getObjects()->update(kObjectCompartment1, kEntityMertens, getObjects()->get(kObjectCompartment1).status, kCursorNormal, kCursorNormal); + getObjects()->update(kObjectCompartment1, kEntityPlayer, getObjects()->get(kObjectCompartment1).status, kCursorNormal, kCursorNormal); switch (params->param1) { default: @@ -1774,7 +1802,7 @@ label_callback11: break; case kActionOpenDoor: - getSound()->playSound(kEntityPlayer, getObjects()->get(kObjectCompartment1).status == kObjectLocation1 ? "LIB012" : "LIB014"); + getSound()->playSound(kEntityPlayer, getObjects()->get(kObjectCompartment1).status == kObjectLocation1 ? "LIB032" : "LIB014"); if (getProgress().eventCorpseMovedFromFloor) { @@ -1855,7 +1883,7 @@ label_callback11: } else { if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarGreenSleeping)) { setCallback(2); - setup_enterExitCompartment("601Ra", kObjectCompartment1); + setup_enterExitCompartment2("601Ra", kObjectCompartment1); } else { getScenes()->loadSceneFromPosition(kCarNone, 1); @@ -2222,7 +2250,7 @@ IMPLEMENT_FUNCTION_I(30, Mertens, function30, MertensActionType) if (params->param3) getObjects()->update(kObjectCompartment2, kEntityPlayer, getObjects()->get(kObjectCompartment2).status, kCursorHandKnock, kCursorHand); - getEntities()->exitCompartment(kEntityMertens, kObjectCompartment2); + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment2, true); if (getProgress().field_14 == 3) getProgress().field_14 = 0; @@ -2243,7 +2271,7 @@ IMPLEMENT_FUNCTION_I(30, Mertens, function30, MertensActionType) if (params->param3) getObjects()->update(kObjectCompartment3, kEntityPlayer, getObjects()->get(kObjectCompartment3).status, kCursorHandKnock, kCursorHand); - getEntities()->exitCompartment(kEntityMertens, kObjectCompartment3); + getEntities()->exitCompartment(kEntityMertens, kObjectCompartment3, true); if (getProgress().field_14 == 3) getProgress().field_14 = 0; @@ -2465,6 +2493,7 @@ IMPLEMENT_FUNCTION(33, Mertens, function33) break; } + ENTITY_PARAM(1, 8) = 0; callbackAction(); break; @@ -2478,12 +2507,14 @@ IMPLEMENT_FUNCTION(33, Mertens, function33) break; } + ENTITY_PARAM(1, 8) = 0; callbackAction(); break; case 13: ENTITY_PARAM(2, 2) = 0; + ENTITY_PARAM(1, 8) = 0; callbackAction(); break; } @@ -2631,14 +2662,12 @@ IMPLEMENT_FUNCTION(36, Mertens, function36) 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); - } + if (ENTITY_PARAM(0, 6) && getEntities()->isPlayerInCar(kCarGreenSleeping) && getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition) { + setCallback(3); + setup_updateEntity(kCarGreenSleeping, kPosition_9460); + } else if (!getProgress().eventMertensKronosInvitation) { + setCallback(7); + setup_tylerCompartment(kMertensAction2); } else { ENTITY_PARAM(0, 6) = 0; ENTITY_PARAM(0, 7) = 0; @@ -2657,7 +2686,7 @@ IMPLEMENT_FUNCTION(36, Mertens, function36) break; case 4: - if (ENTITY_PARAM(0, 6)) { + if (!getProgress().eventMertensKronosInvitation) { setCallback(7); setup_tylerCompartment(kMertensAction2); } else { @@ -2720,9 +2749,9 @@ IMPLEMENT_FUNCTION(37, Mertens, function37) break; case kActionEndSound: - ++params->param6; + ++params->param1; - if (params->param6 == 1) + if (params->param1 == 1) getSound()->playSound(kEntityMertens, getEntities()->isDistanceBetweenEntities(kEntityMertens, kEntityPlayer, 2000) ? "CON1152" : "CON1151"); break; @@ -2737,7 +2766,7 @@ IMPLEMENT_FUNCTION(37, Mertens, function37) break; case 1: - setCallback(1); + setCallback(2); setup_updateEntity(kCarRedSleeping, kPosition_1500); break; @@ -3039,10 +3068,10 @@ label_callback_8: break; } +label_callback_9: if (getProgress().field_14 == 29) goto label_callback_13; -label_callback_9: if (ENTITY_PARAM(1, 6)) { getData()->inventoryItem = kItemNone; setCallback(10); @@ -3141,7 +3170,7 @@ label_callback_19: if (!ENTITY_PARAM(0, 1) && !ENTITY_PARAM(2, 1)) { getData()->inventoryItem = kItemNone; setCallback(20); - setup_function13((bool)savepoint.param.intValue, (bool)savepoint.entity2); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2); } break; @@ -3172,13 +3201,13 @@ 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); + setup_function13(getEntities()->isPlayerPosition(kCarGreenSleeping, 1), kEntityPlayer); break; } label_callback_5_6: if (getEntities()->isPlayerInCar(kCarGreenSleeping) && getData()->entityPosition < getEntityData(kEntityPlayer)->entityPosition) { - if (getProgress().jacket == kJacketOriginal || ENTITY_PARAM(0, 7)) { + if (getProgress().jacket == kJacketBlood || ENTITY_PARAM(0, 7)) { getData()->inventoryItem = kItemNone; setCallback(7); setup_function32(); @@ -3325,13 +3354,13 @@ IMPLEMENT_FUNCTION(43, Mertens, chapter2) 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; + 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; break; case kActionCallback: @@ -3380,7 +3409,7 @@ label_callback3: case kAction11: if (!ENTITY_PARAM(2, 1)) { setCallback(5); - setup_function13((bool)savepoint.param.intValue, (bool)savepoint.entity2); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2); } break; @@ -3390,11 +3419,11 @@ label_callback3: if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { setCallback(6); - setup_function13(true, false); + setup_function13(true, kEntityPlayer); } else if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { setCallback(7); - setup_function13(false, false); + setup_function13(false, kEntityPlayer); } break; @@ -3470,7 +3499,7 @@ IMPLEMENT_FUNCTION(45, Mertens, chapter3) ENTITY_PARAM(1, 6) = 0; ENTITY_PARAM(1, 7) = 0; - ENTITY_PARAM(2, 3) = 0; + ENTITY_PARAM(2, 4) = 0; break; case kActionCallback: @@ -3554,7 +3583,7 @@ label_callback_10: case kAction11: if (!ENTITY_PARAM(2, 1)) { setCallback(12); - setup_function13((bool)savepoint.param.intValue, savepoint.entity2 != kEntityPlayer); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2); } break; @@ -3565,10 +3594,10 @@ label_callback_10: if (!ENTITY_PARAM(2, 1)) { if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { setCallback(13); - setup_function13(true, false); + setup_function13(true, kEntityPlayer); } else if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { setCallback(14); - setup_function13(false, false); + setup_function13(false, kEntityPlayer); } } break; @@ -3668,7 +3697,7 @@ IMPLEMENT_FUNCTION(47, Mertens, chapter4) ENTITY_PARAM(1, 6) = 0; ENTITY_PARAM(1, 7) = 0; - ENTITY_PARAM(2, 4) = 0; + ENTITY_PARAM(2, 3) = 0; break; case kActionCallback: @@ -3762,7 +3791,7 @@ label_callback_8: case kAction11: if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { setCallback(9); - setup_function13((bool)savepoint.param.intValue, savepoint.entity2 != kEntityPlayer); + setup_function13((bool)savepoint.param.intValue, savepoint.entity2); } break; @@ -3778,10 +3807,10 @@ label_callback_8: if (!ENTITY_PARAM(2, 1) && !ENTITY_PARAM(0, 1)) { if (getEntities()->isPlayerPosition(kCarGreenSleeping, 1)) { setCallback(10); - setup_function13(true, false); + setup_function13(true, kEntityPlayer); } else if (getEntities()->isPlayerPosition(kCarGreenSleeping, 23)) { setCallback(11); - setup_function13(false, false); + setup_function13(false, kEntityPlayer); } } break; @@ -4008,7 +4037,7 @@ IMPLEMENT_FUNCTION(53, Mertens, function53) break; params->param1 = 0; - params->param2 = 0; + params->param2 = 1; getObjects()->update(kObjectCompartment4, kEntityMertens, kObjectLocation1, kCursorNormal, kCursorNormal); } diff --git a/engines/lastexpress/entities/mertens.h b/engines/lastexpress/entities/mertens.h index 1b6d1d2f31..55c2ddd0bc 100644 --- a/engines/lastexpress/entities/mertens.h +++ b/engines/lastexpress/entities/mertens.h @@ -126,7 +126,7 @@ public: * @param entity The entity */ DECLARE_FUNCTION_1(bonsoir, EntityIndex entity) - DECLARE_FUNCTION_2(function13, bool, bool) + DECLARE_FUNCTION_2(function13, bool, EntityIndex entity) DECLARE_FUNCTION_1(function14, EntityIndex entity) DECLARE_FUNCTION_1(function15, bool) DECLARE_FUNCTION_1(function16, bool) diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp index 65cad07b1b..8177f99ff6 100644 --- a/engines/lastexpress/entities/milos.cpp +++ b/engines/lastexpress/entities/milos.cpp @@ -43,16 +43,16 @@ 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_S(Milos, draw); + ADD_CALLBACK_FUNCTION_SI(Milos, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(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_S(Milos, playSound); + ADD_CALLBACK_FUNCTION_S(Milos, playSound16); + ADD_CALLBACK_FUNCTION_II(Milos, savegame); + ADD_CALLBACK_FUNCTION_I(Milos, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Milos, enterCompartmentDialog); + ADD_CALLBACK_FUNCTION_I(Milos, function11); ADD_CALLBACK_FUNCTION(Milos, chapter1); ADD_CALLBACK_FUNCTION(Milos, function13); ADD_CALLBACK_FUNCTION(Milos, function14); @@ -67,8 +67,8 @@ Milos::Milos(LastExpressEngine *engine) : Entity(engine, kEntityMilos) { 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_I(Milos, function26); + ADD_CALLBACK_FUNCTION_II(Milos, function27); ADD_CALLBACK_FUNCTION(Milos, chapter4); ADD_CALLBACK_FUNCTION(Milos, chapter4Handler); ADD_CALLBACK_FUNCTION(Milos, function30); @@ -180,11 +180,12 @@ IMPLEMENT_FUNCTION_I(11, Milos, function11, TimeValue) params->param2 = 0; params->param3 = 1; getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation1, kCursorNormal, kCursorNormal); + params->param8 = 0; } + } else { + params->param8 = 0; } - params->param8 = 0; - if (getProgress().chapter != kChapter1 || params->param5) break; @@ -344,7 +345,7 @@ IMPLEMENT_FUNCTION_I(11, Milos, function11, TimeValue) break; case kAction123852928: - params->param1 = 13; + setCallback(13); setup_enterExitCompartment("611Dg", kObjectCompartmentG); break; @@ -737,6 +738,7 @@ IMPLEMENT_FUNCTION(15, Milos, chapter1Handler) } } +label_callback_1: if (getEntities()->isPlayerPosition(kCarRestaurant, 70) && !params->param2) { if (!Entity::updateParameter(params->param5, getState()->timeTicks, 45)) break; @@ -759,7 +761,7 @@ IMPLEMENT_FUNCTION(15, Milos, chapter1Handler) case 1: getEntities()->drawSequenceLeft(kEntityMilos, "009A"); params->param1 = 1; - break; + goto label_callback_1; case 2: getEntities()->drawSequenceLeft(kEntityMilos, "009A"); @@ -891,9 +893,11 @@ IMPLEMENT_FUNCTION(19, Milos, chapter2) case kActionDefault: getEntities()->clearSequences(kEntityMilos); - getData()->entityPosition = kPosition_4689; - getData()->location = kLocationInsideCompartment; - getData()->car = kCarRestaurant; + getData()->entityPosition = kPosition_540; + getData()->location = kLocationOutsideCompartment; + getData()->car = kCarRedSleeping; + getData()->inventoryItem = kItemNone; + getData()->clothes = kClothesDefault; getObjects()->update(kObjectCompartmentG, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); getObjects()->update(kObject46, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); @@ -969,6 +973,7 @@ IMPLEMENT_FUNCTION(21, Milos, function21) case kActionOpenDoor: getObjects()->update(kObjectCompartmentG, kEntityMilos, kObjectLocation3, kCursorNormal, kCursorNormal); + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; setCallback(3); setup_savegame(kSavegameTypeEvent, kEventMilosCompartmentVisitAugust); @@ -1156,7 +1161,7 @@ IMPLEMENT_FUNCTION(24, Milos, function24) setCallback(12); setup_playSound("LIB013"); } else { - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; setCallback(11); setup_savegame(kSavegameTypeEvent, kEventMilosCompartmentVisitAugust); @@ -1354,7 +1359,7 @@ IMPLEMENT_FUNCTION(25, Milos, function25) RESET_ENTITY_STATE(kEntityVesna, Vesna, setup_inCompartment); - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; setCallback(4); setup_savegame(kSavegameTypeEvent, kEventMilosCompartmentVisitTyler); @@ -1390,6 +1395,7 @@ IMPLEMENT_FUNCTION_I(26, Milos, function26, TimeValue) case kActionNone: if (params->param1 < getState()->time && !params->param2) { + params->param2 = 1; callbackAction(); break; } @@ -1556,7 +1562,7 @@ IMPLEMENT_FUNCTION(29, Milos, chapter4Handler) break; case 2: - getEntities()->exitCompartment(kEntityMilos, kObjectCompartmentG); + getEntities()->exitCompartment(kEntityMilos, kObjectCompartmentG, true); getData()->location = kLocationInsideCompartment; getData()->entityPosition = kPosition_3050; @@ -1600,7 +1606,7 @@ IMPLEMENT_FUNCTION(30, Milos, function30) default: break; - case kActionNone: + case kActionDefault: setCallback(1); setup_function11(kTime2410200); break; @@ -1638,7 +1644,7 @@ IMPLEMENT_FUNCTION(31, Milos, function31) default: break; - case kActionNone: + case kActionDefault: setCallback(1); setup_enterExitCompartment("609CG", kObjectCompartmentG); break; @@ -1721,7 +1727,7 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) break; case 1: - getAction()->playAnimation(isNight() ? kEventLocomotiveMilosShovelingNight : kEventLocomotiveMilosShovelingDay); + getAction()->playAnimation(getProgress().isNightTime ? kEventLocomotiveMilosShovelingDay : kEventLocomotiveMilosShovelingNight); getScenes()->processScene(); break; @@ -1733,7 +1739,7 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) getSoundQueue()->removeFromQueue("ARRIVE"); getSoundQueue()->processEntries(); - getAction()->playAnimation(isNight() ? kEventLocomotiveMilosNight : kEventLocomotiveMilosDay); + getAction()->playAnimation(getProgress().isNightTime ? kEventLocomotiveMilosDay : kEventLocomotiveMilosNight); getSoundQueue()->setupEntry(kSoundType7, kEntityMilos); getScenes()->loadSceneFromPosition(kCarCoalTender, 1); break; @@ -1787,11 +1793,12 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) if (!getProgress().isNightTime) { setCallback(3); setup_savegame(kSavegameTypeEvent, kEventLocomotiveAnnaStopsTrain); + break; } getSoundQueue()->processEntry(kEntityMilos); - if (getState()->time < kTimeTrainStopped2) - getState()->time = kTimeTrainStopped2; + if (getState()->time < kTime2949300) + getState()->time = kTime2949300; setCallback(4); setup_savegame(kSavegameTypeEvent, kEventLocomotiveRestartTrain); diff --git a/engines/lastexpress/entities/mmeboutarel.cpp b/engines/lastexpress/entities/mmeboutarel.cpp index f00fb7a9cb..994a0ceda6 100644 --- a/engines/lastexpress/entities/mmeboutarel.cpp +++ b/engines/lastexpress/entities/mmeboutarel.cpp @@ -38,13 +38,13 @@ 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_S(MmeBoutarel, playSound); + ADD_CALLBACK_FUNCTION_S(MmeBoutarel, draw); + ADD_CALLBACK_FUNCTION_I(MmeBoutarel, updateFromTime); + ADD_CALLBACK_FUNCTION_SI(MmeBoutarel, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(MmeBoutarel, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_II(MmeBoutarel, updateEntity); + ADD_CALLBACK_FUNCTION_S(MmeBoutarel, function8); ADD_CALLBACK_FUNCTION(MmeBoutarel, function9); ADD_CALLBACK_FUNCTION(MmeBoutarel, chapter1); ADD_CALLBACK_FUNCTION(MmeBoutarel, function11); @@ -163,6 +163,7 @@ IMPLEMENT_FUNCTION(9, MmeBoutarel, function9) if (!params->param1) { getData()->entityPosition = getEntityData(kEntityBoutarel)->entityPosition; getData()->location = getEntityData(kEntityBoutarel)->location; + getData()->car = getEntityData(kEntityBoutarel)->car; } break; @@ -912,6 +913,7 @@ IMPLEMENT_FUNCTION(21, MmeBoutarel, chapter3Handler) getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); getObjects()->update(kObject43, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); + getSavePoints()->push(kEntityMmeBoutarel, kEntityFrancois, kAction189872836); break; case kActionCallback: @@ -968,6 +970,7 @@ IMPLEMENT_FUNCTION(21, MmeBoutarel, chapter3Handler) case 9: getEntities()->drawSequenceLeft(kEntityMmeBoutarel, "501"); params->param1 = 1; + getSavePoints()->push(kEntityMmeBoutarel, kEntityFrancois, kAction190390860); break; } break; diff --git a/engines/lastexpress/entities/pascale.cpp b/engines/lastexpress/entities/pascale.cpp index 24b7f0409b..f5fa1aab30 100644 --- a/engines/lastexpress/entities/pascale.cpp +++ b/engines/lastexpress/entities/pascale.cpp @@ -36,13 +36,13 @@ namespace LastExpress { Pascale::Pascale(LastExpressEngine *engine) : Entity(engine, kEntityPascale) { - ADD_CALLBACK_FUNCTION(Pascale, draw); + ADD_CALLBACK_FUNCTION_S(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_I(Pascale, updateFromTime); + ADD_CALLBACK_FUNCTION_SII(Pascale, updatePosition); + ADD_CALLBACK_FUNCTION_S(Pascale, playSound); + ADD_CALLBACK_FUNCTION_SSI(Pascale, draw2); ADD_CALLBACK_FUNCTION(Pascale, welcomeSophieAndRebecca); ADD_CALLBACK_FUNCTION(Pascale, sitSophieAndRebecca); ADD_CALLBACK_FUNCTION(Pascale, welcomeCath); @@ -188,9 +188,9 @@ IMPLEMENT_FUNCTION(9, Pascale, sitSophieAndRebecca) break; case kActionDefault: - getEntities()->drawSequenceLeft(kEntityPascale, "012C1"); - getEntities()->drawSequenceLeft(kEntityRebecca, "012C2"); - getEntities()->drawSequenceLeft(kEntityTables3, "012C3"); + getEntities()->drawSequenceRight(kEntityPascale, "012C1"); + getEntities()->drawSequenceRight(kEntityRebecca, "012C2"); + getEntities()->drawSequenceRight(kEntityTables3, "012C3"); break; } IMPLEMENT_FUNCTION_END @@ -353,7 +353,7 @@ IMPLEMENT_FUNCTION(13, Pascale, greetAugust) break; case 2: - getEntities()->drawSequenceLeft(kEntityPascale, "010B"); + getEntities()->drawSequenceLeft(kEntityAugust, "010B"); setCallback(3); setup_draw("905"); @@ -739,7 +739,7 @@ IMPLEMENT_FUNCTION(24, Pascale, welcomeAbbot) default: break; - case kActionNone: + case kActionEndSound: if (!params->param1) { getSound()->playSound(kEntityPascale, "ABB3015A"); params->param1 = 1; @@ -1132,7 +1132,7 @@ label_callback1: break; params->param1 = 0; - params->param2 = 2; + params->param2 = 1; getObjects()->update(kObjectCompartmentG, kEntityPascale, kObjectLocation1, kCursorNormal, kCursorNormal); } @@ -1192,7 +1192,7 @@ label_callback1: 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"); + setup_playSound(params->param3 == 1 ? "Wat5001" : "Wat5001A"); } break; diff --git a/engines/lastexpress/entities/rebecca.cpp b/engines/lastexpress/entities/rebecca.cpp index b8b4aa1275..acb58f7870 100644 --- a/engines/lastexpress/entities/rebecca.cpp +++ b/engines/lastexpress/entities/rebecca.cpp @@ -23,6 +23,7 @@ #include "lastexpress/entities/rebecca.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" @@ -37,25 +38,25 @@ 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_I(Rebecca, updateFromTime); + ADD_CALLBACK_FUNCTION_S(Rebecca, playSound); + ADD_CALLBACK_FUNCTION_S(Rebecca, playSound16); + ADD_CALLBACK_FUNCTION_SIIS(Rebecca, callSavepoint); + ADD_CALLBACK_FUNCTION_S(Rebecca, draw); + ADD_CALLBACK_FUNCTION_SI(Rebecca, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(Rebecca, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_SI(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_II(Rebecca, updateEntity); + ADD_CALLBACK_FUNCTION_SII(Rebecca, updatePosition); + ADD_CALLBACK_FUNCTION_SSI(Rebecca, draw2); ADD_CALLBACK_FUNCTION(Rebecca, function15); - ADD_CALLBACK_FUNCTION(Rebecca, function16); - ADD_CALLBACK_FUNCTION(Rebecca, function17); + ADD_CALLBACK_FUNCTION_I(Rebecca, function16); + ADD_CALLBACK_FUNCTION_I(Rebecca, function17); ADD_CALLBACK_FUNCTION(Rebecca, function18); ADD_CALLBACK_FUNCTION(Rebecca, function19); - ADD_CALLBACK_FUNCTION(Rebecca, function20); + ADD_CALLBACK_FUNCTION_I(Rebecca, function20); ADD_CALLBACK_FUNCTION(Rebecca, chapter1); ADD_CALLBACK_FUNCTION(Rebecca, chapter1Handler); ADD_CALLBACK_FUNCTION(Rebecca, function23); @@ -129,6 +130,11 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_SI(9, Rebecca, enterExitCompartment3, ObjectIndex) + if (savepoint.action == kAction4) { + getEntities()->exitCompartment(_entityIndex, (ObjectIndex)params->param4); + callbackAction(); + return; + } Entity::enterExitCompartment(savepoint); IMPLEMENT_FUNCTION_END @@ -239,7 +245,7 @@ IMPLEMENT_FUNCTION_I(16, Rebecca, function16, bool) if (getEntities()->isInSalon(kEntityPlayer)) getEntities()->updateFrame(kEntityRebecca); - setCallback(4); + setCallback(5); setup_callbackActionOnDirection(); break; @@ -442,7 +448,7 @@ IMPLEMENT_FUNCTION(19, Rebecca, function19) if (getEntities()->isInRestaurant(kEntityPlayer)) getEntities()->updateFrame(kEntityRebecca); - setCallback(4); + setCallback(3); setup_callbackActionOnDirection(); break; @@ -563,6 +569,30 @@ label_callback: case kActionKnock: case kActionOpenDoor: + if (params->param2) { + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + if (savepoint.param.intValue == kObject52) { + setCallback(8); + setup_playSound(getSound()->justAMinuteCath()); + } else if (getInventory()->hasItem(kItemPassengerList)) { + if (rnd(2)) { + setCallback(9); + setup_playSound(getSound()->wrongDoorCath()); + } else { + setCallback(10); + setup_playSound(params->param4 ? "CAT1509" : (rnd(2) ? "CAT1508" : "CAT1508A")); + } + } else { + setCallback(11); + setup_playSound(getSound()->wrongDoorCath()); + } + } else { + getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + getObjects()->update(kObject52, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); + setCallback(savepoint.action == kActionKnock ? 4 : 5); + setup_playSound(savepoint.action == kActionKnock ? "LIB012" : "LIB013"); + } break; case kActionDefault: @@ -955,7 +985,7 @@ IMPLEMENT_FUNCTION(25, Rebecca, function25) case 1: setCallback(2); - setup_function17(false); + setup_function17(true); break; case 2: @@ -1109,7 +1139,7 @@ IMPLEMENT_FUNCTION(30, Rebecca, function30) } } - if (!params->param3 && !params->param2 && params->param5 != kTimeInvalid) { + if (params->param3 && !params->param2 && params->param5 != kTimeInvalid) { if (getState()->time <= kTime10881000) { if (!getEntities()->isInSalon(kEntityPlayer) || !params->param5) @@ -1231,13 +1261,15 @@ IMPLEMENT_FUNCTION(34, Rebecca, function34) break; case kActionNone: - if (params->param2 == kTimeInvalid) { + if (params->param2 != kTimeInvalid) { if (getState()->time <= kTime1386000) { if (!getEntities()->isInRestaurant(kEntityPlayer) || !params->param2) params->param2 = (uint)getState()->time; if (params->param2 >= getState()->time) { - Entity::timeCheckCallback(kTime2052000, params->param3, 1, WRAP_SETUP_FUNCTION(Rebecca, setup_function19)); + if (params->param1) { + Entity::timeCheckCallback(kTime2052000, params->param3, 3, WRAP_SETUP_FUNCTION(Rebecca, setup_function19)); + } break; } } @@ -1247,7 +1279,9 @@ IMPLEMENT_FUNCTION(34, Rebecca, function34) getSavePoints()->push(kEntityRebecca, kEntityWaiter1, kAction223712416); } - Entity::timeCheckCallback(kTime2052000, params->param3, 1, WRAP_SETUP_FUNCTION(Rebecca, setup_function19)); + if (params->param1) { + Entity::timeCheckCallback(kTime2052000, params->param3, 3, WRAP_SETUP_FUNCTION(Rebecca, setup_function19)); + } break; case kActionEndSound: @@ -1785,7 +1819,7 @@ IMPLEMENT_FUNCTION(48, Rebecca, function48) getObjects()->update(kObjectCompartmentE, kEntityRebecca, kObjectLocation1, kCursorNormal, kCursorNormal); if (params->param1) { - params->param1 = 0; + params->param2 = 1; setCallback(2); setup_playSound(getSound()->justCheckingCath()); diff --git a/engines/lastexpress/entities/salko.cpp b/engines/lastexpress/entities/salko.cpp index 26f512b900..f93d13c849 100644 --- a/engines/lastexpress/entities/salko.cpp +++ b/engines/lastexpress/entities/salko.cpp @@ -40,12 +40,12 @@ 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_SI(Salko, enterExitCompartment); + ADD_CALLBACK_FUNCTION_S(Salko, draw); + ADD_CALLBACK_FUNCTION_II(Salko, updateEntity); + ADD_CALLBACK_FUNCTION_I(Salko, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Salko, savegame); + ADD_CALLBACK_FUNCTION_II(Salko, function7); ADD_CALLBACK_FUNCTION(Salko, function8); ADD_CALLBACK_FUNCTION(Salko, chapter1); ADD_CALLBACK_FUNCTION(Salko, chapter1Handler); @@ -176,6 +176,7 @@ IMPLEMENT_FUNCTION(10, Salko, chapter1Handler) case kActionNone: getData()->entityPosition = getEntityData(kEntityIvo)->entityPosition; getData()->location = getEntityData(kEntityIvo)->location; + getData()->car = getEntityData(kEntityIvo)->car; break; case kActionCallback: @@ -357,6 +358,8 @@ label_callback3: break; case 2: + getEntities()->drawSequenceLeft(kEntitySalko, "612AF"); + getEntities()->enterCompartment(kEntitySalko, kObjectCompartmentF, true); break; case 3: @@ -416,7 +419,7 @@ IMPLEMENT_FUNCTION(17, Salko, function17) getData()->inventoryItem = kItemNone; setCallback(1); - setup_updateEntity(kCarGreenSleeping, kPosition_2740); + setup_updateEntity(kCarRedSleeping, kPosition_2740); break; case kActionCallback: diff --git a/engines/lastexpress/entities/sophie.cpp b/engines/lastexpress/entities/sophie.cpp index ac4732556d..cda72bdfff 100644 --- a/engines/lastexpress/entities/sophie.cpp +++ b/engines/lastexpress/entities/sophie.cpp @@ -33,7 +33,7 @@ namespace LastExpress { Sophie::Sophie(LastExpressEngine *engine) : Entity(engine, kEntitySophie) { ADD_CALLBACK_FUNCTION(Sophie, reset); - ADD_CALLBACK_FUNCTION(Sophie, updateEntity); + ADD_CALLBACK_FUNCTION_II(Sophie, updateEntity); ADD_CALLBACK_FUNCTION(Sophie, chaptersHandler); ADD_CALLBACK_FUNCTION(Sophie, chapter1); ADD_CALLBACK_FUNCTION(Sophie, function5); @@ -70,8 +70,8 @@ IMPLEMENT_FUNCTION_II(2, Sophie, updateEntity, CarIndex, 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)) { + || (direction == kDirectionUp && (car > rebeccaCar || car == rebeccaCar && position > rebecca_position)) + || (direction == kDirectionDown && (car < rebeccaCar || car == rebeccaCar && position < rebecca_position))) { getData()->field_49B = 0; params->param3 = 1; } @@ -108,6 +108,7 @@ IMPLEMENT_FUNCTION(3, Sophie, chaptersHandler) case kActionNone: getData()->entityPosition = getEntityData(kEntityRebecca)->entityPosition; + getData()->location = getEntityData(kEntityRebecca)->location; getData()->car = getEntityData(kEntityRebecca)->car; break; diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp index 807a8449c4..5dd61e3f46 100644 --- a/engines/lastexpress/entities/tatiana.cpp +++ b/engines/lastexpress/entities/tatiana.cpp @@ -42,21 +42,21 @@ 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_S(Tatiana, playSound); + ADD_CALLBACK_FUNCTION_S(Tatiana, draw); + ADD_CALLBACK_FUNCTION_SII(Tatiana, updatePosition); + ADD_CALLBACK_FUNCTION_SI(Tatiana, enterExitCompartment); + ADD_CALLBACK_FUNCTION_SI(Tatiana, enterExitCompartment2); + ADD_CALLBACK_FUNCTION_SIIS(Tatiana, callSavepoint); ADD_CALLBACK_FUNCTION(Tatiana, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Tatiana, updateFromTicks); - ADD_CALLBACK_FUNCTION(Tatiana, updateFromTime); + ADD_CALLBACK_FUNCTION_I(Tatiana, updateFromTicks); + ADD_CALLBACK_FUNCTION_I(Tatiana, updateFromTime); ADD_CALLBACK_FUNCTION(Tatiana, callbackActionRestaurantOrSalon); - ADD_CALLBACK_FUNCTION(Tatiana, savegame); - ADD_CALLBACK_FUNCTION(Tatiana, updateEntity); + ADD_CALLBACK_FUNCTION_II(Tatiana, savegame); + ADD_CALLBACK_FUNCTION_II(Tatiana, updateEntity); ADD_CALLBACK_FUNCTION(Tatiana, enterCompartment); ADD_CALLBACK_FUNCTION(Tatiana, exitCompartment); - ADD_CALLBACK_FUNCTION(Tatiana, handleCompartment); + ADD_CALLBACK_FUNCTION_I(Tatiana, handleCompartment); ADD_CALLBACK_FUNCTION(Tatiana, chapter1); ADD_CALLBACK_FUNCTION(Tatiana, function18); ADD_CALLBACK_FUNCTION(Tatiana, chapter1Handler); @@ -72,7 +72,7 @@ Tatiana::Tatiana(LastExpressEngine *engine) : Entity(engine, kEntityTatiana) { ADD_CALLBACK_FUNCTION(Tatiana, leaveBreakfast); ADD_CALLBACK_FUNCTION(Tatiana, returnToCompartment2); ADD_CALLBACK_FUNCTION(Tatiana, chapter3); - ADD_CALLBACK_FUNCTION(Tatiana, playChess); + ADD_CALLBACK_FUNCTION_TYPE2(Tatiana, playChess, EntityParametersI5S, EntityParametersSIII); ADD_CALLBACK_FUNCTION(Tatiana, returnToCompartment3); ADD_CALLBACK_FUNCTION(Tatiana, beforeConcert); ADD_CALLBACK_FUNCTION(Tatiana, concert); @@ -82,11 +82,11 @@ Tatiana::Tatiana(LastExpressEngine *engine) : Entity(engine, kEntityTatiana) { ADD_CALLBACK_FUNCTION(Tatiana, function39); ADD_CALLBACK_FUNCTION(Tatiana, function40); ADD_CALLBACK_FUNCTION(Tatiana, trapCath); - ADD_CALLBACK_FUNCTION(Tatiana, function42); + ADD_CALLBACK_FUNCTION_II(Tatiana, function42); ADD_CALLBACK_FUNCTION(Tatiana, chapter4); ADD_CALLBACK_FUNCTION(Tatiana, inCompartment4); ADD_CALLBACK_FUNCTION(Tatiana, meetAlexei); - ADD_CALLBACK_FUNCTION(Tatiana, withAlexei); + ADD_CALLBACK_FUNCTION_TYPE(Tatiana, withAlexei, EntityParametersI5S); ADD_CALLBACK_FUNCTION(Tatiana, thinking); ADD_CALLBACK_FUNCTION(Tatiana, seekCath); ADD_CALLBACK_FUNCTION(Tatiana, function49); @@ -100,7 +100,7 @@ Tatiana::Tatiana(LastExpressEngine *engine) : Entity(engine, kEntityTatiana) { ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(1, Tatiana, reset) - Entity::reset(savepoint, true); + Entity::reset(savepoint, kClothes3, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -421,7 +421,7 @@ IMPLEMENT_FUNCTION(19, Tatiana, chapter1Handler) break; case kActionNone: - if (getSoundQueue()->isBuffered(kEntityTatiana) || !params->param4 || params->param3 == 2 || getSoundQueue()->isBuffered("TAT1066")) + if (getSoundQueue()->isBuffered(kEntityTatiana) || !params->param4 || params->param3 >= 2 || getSoundQueue()->isBuffered("TAT1066")) goto label_tatiana_chapter1_2; if (Entity::updateParameter(params->param5, getState()->timeTicks, 450)) { @@ -616,6 +616,8 @@ IMPLEMENT_FUNCTION(22, Tatiana, getSomeAir) goto label_update; if (Entity::updateParameterTime(kTime1233000, ((!getEvent(kEventTatianaAskMatchSpeakRussian) && !getEvent(kEventTatianaAskMatch)) || getEntities()->isInGreenCarEntrance(kEntityPlayer)), params->param1, 0)) { + params->param1 = kTimeInvalid; + label_update: if (!getEvent(kEventTatianaAskMatchSpeakRussian) && !getEvent(kEventTatianaAskMatch) @@ -624,10 +626,9 @@ label_update: getObjects()->update(kObject25, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorForward); getObjects()->update(kObjectTrainTimeTable, kEntityTatiana, kObjectLocation1, kCursorNormal, kCursorForward); } + break; } - params->param1 = kTimeInvalid; - getObjects()->update(kObject25, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); getObjects()->update(kObjectTrainTimeTable, kEntityPlayer, kObjectLocationNone, kCursorKeepValue, kCursorKeepValue); getEntities()->updatePositionExit(kEntityTatiana, kCarGreenSleeping, 70); @@ -796,7 +797,7 @@ IMPLEMENT_FUNCTION(26, Tatiana, chapter2Handler) case kAction1: getData()->inventoryItem = kItemNone; - setup_joinAlexei(); + setup_breakfastClick(); break; case kActionDefault: @@ -1023,7 +1024,7 @@ IMPLEMENT_FUNCTION(32, Tatiana, playChess) } if (parameters->param4 && parameters->param5) { - if (Entity::updateParameterCheck(parameters->param4, getState()->time, 6300)) { + if (Entity::updateParameterCheck(parameters1->param4, getState()->time, 6300)) { if (getEntities()->isSomebodyInsideRestaurantOrSalon()) { getData()->location = kLocationOutsideCompartment; @@ -1035,7 +1036,6 @@ IMPLEMENT_FUNCTION(32, Tatiana, playChess) break; case kActionEndSound: - parameters->param2 = 0; ++parameters->param3; switch (parameters->param3) { @@ -1080,7 +1080,7 @@ IMPLEMENT_FUNCTION(32, Tatiana, playChess) case 6: parameters->param1 = 4500; getEntities()->drawSequenceLeft(kEntityTatiana, "110B"); - strcpy((char *)¶meters->seq, "Tat3160B"); + strcpy((char *)¶meters->seq, "Tat3160F"); break; } break; @@ -1165,6 +1165,7 @@ IMPLEMENT_FUNCTION(34, Tatiana, beforeConcert) getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); getObjects()->update(kObject49, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + setCallback(2); setup_exitCompartment(); break; @@ -1238,7 +1239,7 @@ IMPLEMENT_FUNCTION(36, Tatiana, leaveConcert) getData()->location = kLocationOutsideCompartment; setCallback(1); - setup_updateEntity(kCarGreenSleeping, kPosition_7500); + setup_updateEntity(kCarRedSleeping, kPosition_7500); break; case kActionCallback: @@ -1247,7 +1248,7 @@ IMPLEMENT_FUNCTION(36, Tatiana, leaveConcert) break; case 1: - if (!getEntities()->checkFields19(kEntityPlayer, kCarGreenSleeping, kPosition_7850) || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { + if (!getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_7850) || getEntities()->isInsideCompartment(kEntityPlayer, kCarRedSleeping, kPosition_8200)) { setCallback(2); setup_enterCompartment(); break; @@ -1262,6 +1263,7 @@ IMPLEMENT_FUNCTION(36, Tatiana, leaveConcert) } getScenes()->loadSceneFromObject(kObjectCompartmentB); + setup_afterConcert(); break; case 2: @@ -1543,7 +1545,7 @@ IMPLEMENT_FUNCTION(40, Tatiana, function40) case kActionExcuseMe: if (getEvent(kEventTatianaAskMatchSpeakRussian) || getEvent(kEventTatianaAskMatch) || getEvent(kEventVassiliSeizure)) - getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1001A" : "CAT1010"); + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1010A" : "CAT1010"); else getSound()->excuseMeCath(); break; @@ -1732,7 +1734,7 @@ IMPLEMENT_FUNCTION(45, Tatiana, meetAlexei) getObjects()->update(kObjectCompartmentB, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); getData()->location = kLocationOutsideCompartment; - setCallback(1); + setCallback(2); setup_updateEntity(kCarGreenSleeping, kPosition_540); break; @@ -1782,7 +1784,7 @@ IMPLEMENT_FUNCTION(46, Tatiana, withAlexei) if (CURRENT_PARAM(1, 1) == kTimeInvalid || getState()->time <= kTime2394000) break; - if (getState()->time >= kTime2398500) { + if (getState()->time > kTime2398500) { CURRENT_PARAM(1, 1) = kTimeInvalid; } else { if (getEntities()->isInGreenCarEntrance(kEntityPlayer) || !CURRENT_PARAM(1, 1)) diff --git a/engines/lastexpress/entities/train.cpp b/engines/lastexpress/entities/train.cpp index f707b02ccf..c8cfe8cca8 100644 --- a/engines/lastexpress/entities/train.cpp +++ b/engines/lastexpress/entities/train.cpp @@ -38,14 +38,14 @@ namespace LastExpress { Train::Train(LastExpressEngine *engine) : Entity(engine, kEntityTrain) { - ADD_CALLBACK_FUNCTION(Train, savegame); + ADD_CALLBACK_FUNCTION_II(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); + ADD_CALLBACK_FUNCTION_II(Train, harem); + ADD_CALLBACK_FUNCTION_TYPE2(Train, process, EntityParametersIIII, EntityParametersIIIS); } ////////////////////////////////////////////////////////////////////////// @@ -111,7 +111,7 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) } params->param4 = getEntities()->isInsideCompartment(kEntityAlouan, kCarGreenSleeping, (EntityPosition)params->param3); - params->param5 = (ENTITY_PARAM(0, 7) - params->param3) < 1 ? true : false; + params->param5 = (ENTITY_PARAM(0, 7) == params->param3) ? true : false; params->param6 = getEntities()->isInsideCompartment(kEntityYasmin, kCarGreenSleeping, (EntityPosition)params->param3); params->param7 = getEntities()->isInsideCompartment(kEntityHadija, kCarGreenSleeping, (EntityPosition)params->param3); @@ -374,7 +374,10 @@ label_process: break; case kCarRestaurant: - getEntities()->drawSequenceLeft(kEntityTrain, isNight() ? "RCWNN" : "RCWND"); + if (getProgress().isNightTime) + getEntities()->drawSequenceLeft(kEntityTrain, "RCWNM"); + else + getEntities()->drawSequenceLeft(kEntityTrain, isNight() ? "RCWNN" : "RCWND"); break; } @@ -478,7 +481,7 @@ label_process: break; case kAction203863200: - if (!strcmp(savepoint.param.charValue, "")) { + if (strcmp(savepoint.param.charValue, "")) { params->param8 = 1; strcpy((char *)¶ms1->seq, savepoint.param.charValue); // this is the sound file name } @@ -502,7 +505,7 @@ label_process: case kObjectCompartment4: case kObjectCompartmentC: case kObjectCompartmentD: - params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param1 = (savepoint.param.intValue == kObjectCompartment3 || savepoint.param.intValue == kObjectCompartment4) ? kCarGreenSleeping : kCarRedSleeping; params1->param2 = (savepoint.param.intValue == kObjectCompartment3 || savepoint.param.intValue == kObjectCompartmentC) ? kPosition_6470 : kPosition_5790; params1->param3 = kPosition_6130; break; @@ -511,7 +514,7 @@ label_process: case kObjectCompartment6: case kObjectCompartmentE: case kObjectCompartmentF: - params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param1 = (savepoint.param.intValue == kObjectCompartment5 || savepoint.param.intValue == kObjectCompartment6) ? kCarGreenSleeping : kCarRedSleeping; params1->param2 = (savepoint.param.intValue == kObjectCompartment5 || savepoint.param.intValue == kObjectCompartmentE) ? kPosition_4840 : kPosition_4070; params1->param3 = kPosition_4455; break; @@ -520,7 +523,7 @@ label_process: case kObjectCompartment8: case kObjectCompartmentG: case kObjectCompartmentH: - params1->param1 = (savepoint.param.intValue == kObjectCompartment1 || savepoint.param.intValue == kObjectCompartment2) ? kCarGreenSleeping : kCarRedSleeping; + params1->param1 = (savepoint.param.intValue == kObjectCompartment7 || savepoint.param.intValue == kObjectCompartment8) ? kCarGreenSleeping : kCarRedSleeping; params1->param2 = (savepoint.param.intValue == kObjectCompartment7 || savepoint.param.intValue == kObjectCompartmentG) ? kPosition_3050 : kPosition_2740; params1->param3 = kPositionNone; break; diff --git a/engines/lastexpress/entities/vassili.cpp b/engines/lastexpress/entities/vassili.cpp index e28ace95be..1c25ce2cb0 100644 --- a/engines/lastexpress/entities/vassili.cpp +++ b/engines/lastexpress/entities/vassili.cpp @@ -42,8 +42,8 @@ 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_S(Vassili, draw); + ADD_CALLBACK_FUNCTION_II(Vassili, savegame); ADD_CALLBACK_FUNCTION(Vassili, chapter1); ADD_CALLBACK_FUNCTION(Vassili, chapter1Handler); ADD_CALLBACK_FUNCTION(Vassili, inBed); @@ -103,14 +103,10 @@ IMPLEMENT_FUNCTION(5, Vassili, chapter1Handler) if (params->param1) { getData()->entityPosition = getEntityData(kEntityTatiana)->entityPosition; getData()->location = getEntityData(kEntityTatiana)->location; + getData()->car = getEntityData(kEntityTatiana)->car; } else { - if (params->param3 && params->param3 >= getState()->time) { + if (!Entity::updateParameterCheck(params->param3, getState()->time, 450)) break; - }else { - params->param3 = (uint)getState()->time + 450; - if (params->param3 == 0) - break; - } if (!params->param2 && getObjects()->get(kObjectCompartmentA).status == kObjectLocation1) { params->param2 = 1; @@ -215,9 +211,9 @@ IMPLEMENT_FUNCTION(7, Vassili, function7) if (params->param1 != kTimeInvalid && getState()->time > kTime1503000) { if (getState()->time <= kTime1512000) { - if (getEntities()->isPlayerInCar(kCarRedSleeping) || !params->param1) { + if (!getEntities()->isPlayerInCar(kCarRedSleeping) || !params->param1) { params->param1 = (uint)getState()->time + 150; - if (params->param1) { + if (!params->param1) { setup_function8(); break; } @@ -345,7 +341,7 @@ IMPLEMENT_FUNCTION(10, Vassili, seizure) if (getCallback() != 1) break; - getData()->location = kLocationInsideCompartment; + getEntityData(kEntityPlayer)->location = kLocationInsideCompartment; getAction()->playAnimation(kEventVassiliSeizure); getObjects()->update(kObjectCompartmentA, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp index b16217b5eb..c3e56d98c1 100644 --- a/engines/lastexpress/entities/verges.cpp +++ b/engines/lastexpress/entities/verges.cpp @@ -39,21 +39,21 @@ namespace LastExpress { Verges::Verges(LastExpressEngine *engine) : Entity(engine, kEntityVerges) { ADD_CALLBACK_FUNCTION(Verges, reset); - ADD_CALLBACK_FUNCTION(Verges, draw); + ADD_CALLBACK_FUNCTION_S(Verges, draw); ADD_CALLBACK_FUNCTION(Verges, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Verges, playSound); - ADD_CALLBACK_FUNCTION(Verges, playSound16); + ADD_CALLBACK_FUNCTION_S(Verges, playSound); + ADD_CALLBACK_FUNCTION_S(Verges, playSound16); ADD_CALLBACK_FUNCTION(Verges, callbackActionRestaurantOrSalon); - ADD_CALLBACK_FUNCTION(Verges, savegame); - ADD_CALLBACK_FUNCTION(Verges, updateEntity); - ADD_CALLBACK_FUNCTION(Verges, walkBetweenCars); - ADD_CALLBACK_FUNCTION(Verges, makeAnnouncement); + ADD_CALLBACK_FUNCTION_II(Verges, savegame); + ADD_CALLBACK_FUNCTION_II(Verges, updateEntity); + ADD_CALLBACK_FUNCTION_S(Verges, walkBetweenCars); + ADD_CALLBACK_FUNCTION_IIS(Verges, makeAnnouncement); ADD_CALLBACK_FUNCTION(Verges, function11); ADD_CALLBACK_FUNCTION(Verges, function12); - ADD_CALLBACK_FUNCTION(Verges, baggageCar); - ADD_CALLBACK_FUNCTION(Verges, updateFromTime); - ADD_CALLBACK_FUNCTION(Verges, dialog); - ADD_CALLBACK_FUNCTION(Verges, dialog2); + ADD_CALLBACK_FUNCTION_I(Verges, baggageCar); + ADD_CALLBACK_FUNCTION_I(Verges, updateFromTime); + ADD_CALLBACK_FUNCTION_IS(Verges, dialog); + ADD_CALLBACK_FUNCTION_ISS(Verges, dialog2); ADD_CALLBACK_FUNCTION(Verges, talkAboutPassengerList); ADD_CALLBACK_FUNCTION(Verges, chapter1); ADD_CALLBACK_FUNCTION(Verges, talkHarem); @@ -67,7 +67,7 @@ Verges::Verges(LastExpressEngine *engine) : Entity(engine, kEntityVerges) { ADD_CALLBACK_FUNCTION(Verges, chapter2); ADD_CALLBACK_FUNCTION(Verges, chapter2Handler); ADD_CALLBACK_FUNCTION(Verges, chapter3); - ADD_CALLBACK_FUNCTION(Verges, function30); + ADD_CALLBACK_FUNCTION_S(Verges, function30); ADD_CALLBACK_FUNCTION(Verges, talkAboutMax); ADD_CALLBACK_FUNCTION(Verges, function32); ADD_CALLBACK_FUNCTION(Verges, function33); @@ -492,7 +492,7 @@ IMPLEMENT_FUNCTION_ISS(16, Verges, dialog2, EntityIndex) break; case kActionNone: - if (CURRENT_PARAM(1, 1) && params->param8) { + if (CURRENT_PARAM(1, 1) >= 2 && params->param8) { getSavePoints()->push(kEntityVerges, (EntityIndex)params->param1, kAction125499160); if (!getEntities()->isPlayerPosition(kCarGreenSleeping, 2) && !getEntities()->isPlayerPosition(kCarRedSleeping, 2)) @@ -742,7 +742,7 @@ IMPLEMENT_FUNCTION(25, Verges, policeSearch) getData()->car = kCarRedSleeping; getData()->entityPosition = kPosition_9270; } else { - if (getEntityData(kEntityPlayer)->car > kCarGreenSleeping + if (getEntityData(kEntityPlayer)->car < kCarGreenSleeping || (getEntityData(kEntityPlayer)->car == kCarGreenSleeping && getEntityData(kEntityPlayer)->entityPosition < kPosition_4840)) { getSound()->playSound(kEntityPlayer, "BUMP"); getScenes()->loadSceneFromObject(kObjectCompartment5, true); @@ -777,7 +777,7 @@ IMPLEMENT_FUNCTION(25, Verges, policeSearch) setup_makeAnnouncement(kCarGreenSleeping, kPosition_540, "TRA1005"); } else { setCallback(7); - setup_makeAnnouncement(kCarRedSleeping, kPosition_9460, "TRA1006"); + setup_makeAnnouncement(kCarRedSleeping, kPosition_9460, "TRA1005"); } break; } @@ -911,15 +911,13 @@ label_callback3: break; label_callback4: - if (Entity::timeCheckCallback(kTime1089000, params->param8, 5, WRAP_SETUP_FUNCTION(Verges, setup_function12))) - break; - - params->param8 = 1; - - if (!params->param5) { - setCallback(5); - setup_function12(); - break; + if (getState()->time > kTime1089000 && !params->param8) { + params->param8 = 1; + if (!params->param5) { + setCallback(5); + setup_function12(); + break; + } } label_callback8: @@ -970,7 +968,7 @@ label_callback15: case kActionOpenDoor: setCallback(17); - setup_baggageCar(savepoint.param.intValue < 106 ? true : false); + setup_baggageCar(savepoint.param.intValue == kObject105 ? true : false); break; case kActionDefault: @@ -1130,7 +1128,7 @@ label_callback_6: case kActionOpenDoor: setCallback(8); - setup_baggageCar(savepoint.param.intValue < 106); + setup_baggageCar(savepoint.param.intValue == kObject105); break; case kActionDefault: @@ -1318,7 +1316,7 @@ IMPLEMENT_FUNCTION(32, Verges, function32) break; case 1: - getData()->entityPosition = kPosition_8500; + getData()->entityPosition = kPosition_5800; getData()->location = kLocationOutsideCompartment; getSound()->playSound(kEntityVerges, "TRA3004"); @@ -1400,12 +1398,12 @@ IMPLEMENT_FUNCTION(33, Verges, function33) getData()->entityPosition = kPosition_5799; setCallback(getProgress().field_3C ? 4 : 5); - setup_playSound(getProgress().field_3C ? "ABB3035A" : "ABB3035"); + setup_playSound(getProgress().field_3C ? "ABB3035A" : "Abb3035"); break; case 4: setCallback(5); - setup_playSound("ABB3035"); + setup_playSound("Abb3035"); break; case 5: @@ -1480,7 +1478,7 @@ label_callback_9: case kActionOpenDoor: setCallback(11); - setup_baggageCar(savepoint.param.intValue < 106); + setup_baggageCar(savepoint.param.intValue == kObject105); break; case kActionCallback: @@ -1542,7 +1540,7 @@ IMPLEMENT_FUNCTION(35, Verges, organizeConcertInvitations) case 2: setCallback(3); - setup_dialog(kEntityMertens, "Tra3011A"); + setup_dialog(kEntityCoudert, "Tra3011A"); break; case 3: @@ -1614,7 +1612,7 @@ IMPLEMENT_FUNCTION(37, Verges, chapter4Handler) } label_callback_1: - if (ENTITY_PARAM(0, 6)) { + if (!ENTITY_PARAM(0, 6)) { if (ENTITY_PARAM(0, 3)) { setCallback(2); setup_talkAboutPassengerList(); @@ -1652,7 +1650,7 @@ label_callback_8: case kActionOpenDoor: setCallback(10); - setup_baggageCar(savepoint.param.intValue < 106); + setup_baggageCar(savepoint.param.intValue == kObject105); break; case kActionDefault: @@ -1739,7 +1737,7 @@ IMPLEMENT_FUNCTION(38, Verges, resetState) getData()->entityPosition = kPosition_5790; setCallback(1); - setup_updateEntity(kCarGreenSleeping, kPosition_540); + setup_updateEntity(kCarRedSleeping, kPosition_540); break; } IMPLEMENT_FUNCTION_END @@ -1905,6 +1903,7 @@ void Verges::talk(const SavePoint &savepoint, const char *sound1, const char *so break; case 5: + setCallback(6); setup_function11(); break; diff --git a/engines/lastexpress/entities/vesna.cpp b/engines/lastexpress/entities/vesna.cpp index 8ab3902b16..7ac53ce6e7 100644 --- a/engines/lastexpress/entities/vesna.cpp +++ b/engines/lastexpress/entities/vesna.cpp @@ -38,16 +38,16 @@ 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_S(Vesna, playSound); + ADD_CALLBACK_FUNCTION_SI(Vesna, enterExitCompartment); + ADD_CALLBACK_FUNCTION_S(Vesna, draw); + ADD_CALLBACK_FUNCTION_II(Vesna, updateEntity); + ADD_CALLBACK_FUNCTION_I(Vesna, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Vesna, updateEntity2); ADD_CALLBACK_FUNCTION(Vesna, callbackActionRestaurantOrSalon); ADD_CALLBACK_FUNCTION(Vesna, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Vesna, savegame); - ADD_CALLBACK_FUNCTION(Vesna, homeAlone); + ADD_CALLBACK_FUNCTION_II(Vesna, savegame); + ADD_CALLBACK_FUNCTION_TYPE(Vesna, homeAlone, EntityParametersIIIS); ADD_CALLBACK_FUNCTION(Vesna, chapter1); ADD_CALLBACK_FUNCTION(Vesna, withMilos); ADD_CALLBACK_FUNCTION(Vesna, homeTogether); @@ -56,7 +56,7 @@ Vesna::Vesna(LastExpressEngine *engine) : Entity(engine, kEntityVesna) { ADD_CALLBACK_FUNCTION(Vesna, chapter2Handler); ADD_CALLBACK_FUNCTION(Vesna, checkTrain); ADD_CALLBACK_FUNCTION(Vesna, chapter3); - ADD_CALLBACK_FUNCTION(Vesna, inCompartment); + ADD_CALLBACK_FUNCTION_TYPE(Vesna, inCompartment, EntityParametersIIIS); ADD_CALLBACK_FUNCTION(Vesna, takeAWalk); ADD_CALLBACK_FUNCTION(Vesna, killAnna); ADD_CALLBACK_FUNCTION(Vesna, killedAnna); @@ -93,7 +93,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_II(5, Vesna, updateEntity, CarIndex, EntityPosition) if (savepoint.action == kActionExcuseMeCath) { - getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT10150" : "CAT1015A"); + getSound()->playSound(kEntityPlayer, rnd(2) ? "CAT1015" : "CAT1015A"); return; } @@ -116,8 +116,8 @@ IMPLEMENT_FUNCTION_II(7, Vesna, updateEntity2, CarIndex, EntityPosition) 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()->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; } @@ -277,6 +277,7 @@ IMPLEMENT_FUNCTION(13, Vesna, withMilos) case kActionNone: getData()->entityPosition = getEntityData(kEntityMilos)->entityPosition; getData()->location = getEntityData(kEntityMilos)->location; + getData()->car = getEntityData(kEntityMilos)->car; break; case kActionCallback: @@ -373,7 +374,7 @@ IMPLEMENT_FUNCTION(18, Vesna, checkTrain) case kActionDefault: setCallback(1); - setup_enterExitCompartment("610Bg", kObjectCompartmentG); + setup_enterExitCompartment("610BG", kObjectCompartmentG); break; case kActionCallback: @@ -449,7 +450,7 @@ IMPLEMENT_FUNCTION(18, Vesna, checkTrain) case 10: setCallback(11); - setup_enterExitCompartment("610Ag", kObjectCompartmentG); + setup_enterExitCompartment("610AG", kObjectCompartmentG); break; case 11: @@ -538,6 +539,8 @@ IMPLEMENT_FUNCTION(20, Vesna, inCompartment) switch (parameters->param3) { default: + strcpy((char *)¶meters->seq, "VES1015C"); + parameters->param3 = 0; break; case 1: @@ -547,11 +550,6 @@ IMPLEMENT_FUNCTION(20, Vesna, inCompartment) 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); @@ -1083,7 +1081,7 @@ IMPLEMENT_FUNCTION(30, Vesna, climbing) case kActionNone: if (!params->param1) { if (Entity::updateParameter(params->param3, getState()->timeTicks, 120)) { - getSound()->playSound(kEntityVesna, "Ves50001", kFlagDefault); + getSound()->playSound(kEntityVesna, "Ves5001", kFlagDefault); params->param1 = 1; } } @@ -1117,7 +1115,7 @@ IMPLEMENT_FUNCTION(30, Vesna, climbing) params->param2 = getFight()->setup(kFightVesna); if (params->param2) { - getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, params->param2 != Fight::kFightEndExit); + getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, params->param2 == Fight::kFightEndLost); } else { getSound()->playSound(kEntityPlayer, "TUNNEL"); diff --git a/engines/lastexpress/entities/waiter1.cpp b/engines/lastexpress/entities/waiter1.cpp index 80ec471f1b..0743d7760b 100644 --- a/engines/lastexpress/entities/waiter1.cpp +++ b/engines/lastexpress/entities/waiter1.cpp @@ -40,12 +40,12 @@ namespace LastExpress { } Waiter1::Waiter1(LastExpressEngine *engine) : Entity(engine, kEntityWaiter1) { - ADD_CALLBACK_FUNCTION(Waiter1, callSavepoint); - ADD_CALLBACK_FUNCTION(Waiter1, updateFromTime); - ADD_CALLBACK_FUNCTION(Waiter1, draw); - ADD_CALLBACK_FUNCTION(Waiter1, updatePosition); + ADD_CALLBACK_FUNCTION_SIIS(Waiter1, callSavepoint); + ADD_CALLBACK_FUNCTION_I(Waiter1, updateFromTime); + ADD_CALLBACK_FUNCTION_S(Waiter1, draw); + ADD_CALLBACK_FUNCTION_SII(Waiter1, updatePosition); ADD_CALLBACK_FUNCTION(Waiter1, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Waiter1, playSound); + ADD_CALLBACK_FUNCTION_S(Waiter1, playSound); ADD_CALLBACK_FUNCTION(Waiter1, rebeccaFeedUs); ADD_CALLBACK_FUNCTION(Waiter1, rebeccaClearOurTable); ADD_CALLBACK_FUNCTION(Waiter1, abbotCheckMe); @@ -296,7 +296,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(18, Waiter1, clearAugust1) - serveTable(savepoint, "911", kEntityTables3, "010L", "010H", "913", &ENTITY_PARAM(0, 7)); + serveTable(savepoint, "911", kEntityTables3, "010L", "010M", "913", &ENTITY_PARAM(0, 7)); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -325,7 +325,7 @@ IMPLEMENT_FUNCTION(20, Waiter1, servingDinner) } } - if (!getEntities()->isInKitchen(kEntityWaiter1) && !getEntities()->isSomebodyInsideRestaurantOrSalon()) + if (!getEntities()->isInKitchen(kEntityWaiter1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) break; HANDLE_TABLE(0, 1, 1, setup_annaOrder); @@ -536,7 +536,7 @@ IMPLEMENT_FUNCTION(28, Waiter1, serving3) break; case kActionNone: - if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + if (!getEntities()->isInKitchen(kEntityWaiter1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) break; if (ENTITY_PARAM(1, 5)) { @@ -734,12 +734,14 @@ IMPLEMENT_FUNCTION(32, Waiter1, serving4) break; case kActionNone: - if (Entity::updateParameter(params->param2, getState()->time, 3600)) { - ENTITY_PARAM(1, 8) = 1; - params->param1 = 0; + if (params->param1) { + if (Entity::updateParameter(params->param2, getState()->time, 3600)) { + ENTITY_PARAM(1, 8) = 1; + params->param1 = 0; + } } - if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) + if (!getEntities()->isInKitchen(kEntityWaiter1) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) break; if (ENTITY_PARAM(1, 7)) { @@ -964,7 +966,7 @@ void Waiter1::handleServer(const SavePoint &savepoint, const char *name, EntityI case kActionCallback: if (getCallback() == 1) { // Prepare or draw sequences depending of value of string - if (strcmp(name2, "")) + if (!strcmp(name2, "")) getEntities()->clearSequences(kEntityWaiter1); else getEntities()->drawSequenceLeft(kEntityWaiter1, name2); diff --git a/engines/lastexpress/entities/waiter2.cpp b/engines/lastexpress/entities/waiter2.cpp index 52a48a77d5..2be7b4e7c6 100644 --- a/engines/lastexpress/entities/waiter2.cpp +++ b/engines/lastexpress/entities/waiter2.cpp @@ -33,12 +33,12 @@ namespace LastExpress { Waiter2::Waiter2(LastExpressEngine *engine) : Entity(engine, kEntityWaiter2) { - ADD_CALLBACK_FUNCTION(Waiter2, updateFromTime); - ADD_CALLBACK_FUNCTION(Waiter2, draw); - ADD_CALLBACK_FUNCTION(Waiter2, updatePosition); + ADD_CALLBACK_FUNCTION_I(Waiter2, updateFromTime); + ADD_CALLBACK_FUNCTION_S(Waiter2, draw); + ADD_CALLBACK_FUNCTION_SII(Waiter2, updatePosition); ADD_CALLBACK_FUNCTION(Waiter2, callbackActionOnDirection); - ADD_CALLBACK_FUNCTION(Waiter2, callSavepoint); - ADD_CALLBACK_FUNCTION(Waiter2, playSound); + ADD_CALLBACK_FUNCTION_SIIS(Waiter2, callSavepoint); + ADD_CALLBACK_FUNCTION_S(Waiter2, playSound); ADD_CALLBACK_FUNCTION(Waiter2, monsieurServeUs); ADD_CALLBACK_FUNCTION(Waiter2, chapter1); ADD_CALLBACK_FUNCTION(Waiter2, milosOrder); @@ -260,7 +260,7 @@ IMPLEMENT_FUNCTION(10, Waiter2, monsieurOrder) case 3: getEntities()->clearSequences(kEntityWaiter2); getData()->entityPosition = kPosition_5900; - ENTITY_PARAM(0, 2) = 0; + ENTITY_PARAM(1, 2) = 0; callbackAction(); break; @@ -290,7 +290,7 @@ switch (savepoint.action) { default: break; - case kActionDefault: + case kActionNone: if (!getEntities()->isInKitchen(kEntityWaiter2) || !getEntities()->isSomebodyInsideRestaurantOrSalon()) break; @@ -524,7 +524,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(24, Waiter2, annaBringTea3) - serveSalon(savepoint, "927", "Ann3143A", kEntityAnna, "Ann31444", "112C", kAction122288808, "928", &ENTITY_PARAM(1, 1)); + serveSalon(savepoint, "927", "Ann3143A", kEntityAnna, "Ann3144", "112C", kAction122288808, "928", &ENTITY_PARAM(1, 1)); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -562,7 +562,7 @@ IMPLEMENT_FUNCTION(26, Waiter2, serving4) break; case kActionNone: - if (params->param2) { + if (params->param1) { if (Entity::updateParameter(params->param2, getState()->time, 900)) { ENTITY_PARAM(1, 5) = 1; params->param1 = 0; @@ -740,7 +740,7 @@ void Waiter2::serveSalon(const SavePoint &savepoint, const char *seq1, const cha if (getEntities()->isInRestaurant(kEntityPlayer)) getEntities()->updateFrame(kEntityWaiter2); - if (!strcmp(snd1, "")) + if (strcmp(snd1, "")) getSound()->playSound(kEntityWaiter2, snd1); setCallback(2); @@ -753,7 +753,9 @@ void Waiter2::serveSalon(const SavePoint &savepoint, const char *seq1, const cha getSound()->playSound(kEntityWaiter2, snd2); setCallback(3); - setup_updatePosition(seq2, kCarRestaurant, 57); + // the last arg is actually a constant varying between calls, + // but this function already has too many args to add yet another one + setup_updatePosition(seq2, kCarRestaurant, strcmp(seq2, "127D") ? 57 : 56); break; case 3: diff --git a/engines/lastexpress/entities/yasmin.cpp b/engines/lastexpress/entities/yasmin.cpp index 971799fb9b..45837e73ee 100644 --- a/engines/lastexpress/entities/yasmin.cpp +++ b/engines/lastexpress/entities/yasmin.cpp @@ -28,6 +28,7 @@ #include "lastexpress/game/savepoint.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" #include "lastexpress/lastexpress.h" @@ -35,10 +36,10 @@ 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_SI(Yasmin, enterExitCompartment); + ADD_CALLBACK_FUNCTION_S(Yasmin, playSound); + ADD_CALLBACK_FUNCTION_I(Yasmin, updateFromTime); + ADD_CALLBACK_FUNCTION_II(Yasmin, updateEntity); ADD_CALLBACK_FUNCTION(Yasmin, goEtoG); ADD_CALLBACK_FUNCTION(Yasmin, goGtoE); ADD_CALLBACK_FUNCTION(Yasmin, chapter1); @@ -492,19 +493,46 @@ IMPLEMENT_FUNCTION(21, Yasmin, hiding) break; case kActionNone: + if (!getSoundQueue()->isBuffered(kEntityYasmin)) { + if (Entity::updateParameter(params->param1, getState()->timeTicks, 450)) { + getSound()->playSound(kEntityYasmin, "Har5001"); + params->param1 = 0; + } + } + break; + case kActionDefault: - if (getEntities()->updateEntity(kEntityYasmin, (CarIndex)params->param1, (EntityPosition)params->param2)) - callbackAction(); + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_4840); break; - case kActionExcuseMeCath: - getSound()->excuseMeCath(); + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + setCallback(2); + setup_enterExitCompartment("615BE", kObjectCompartment5); + break; + + case 2: + getEntities()->clearSequences(kEntityYasmin); + getData()->location = kLocationInsideCompartment; + getData()->entityPosition = kPosition_3050; + getObjects()->update(kObjectCompartment7, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); + getSound()->playSound(kEntityYasmin, "Har5001"); + break; + } break; - case kActionExcuseMe: - getSound()->excuseMe(kEntityYasmin); + case kAction135800432: + setup_nullfunction(); break; } IMPLEMENT_FUNCTION_END +////////////////////////////////////////////////////////////////////////// +IMPLEMENT_NULL_FUNCTION(22, Yasmin) + } // End of namespace LastExpress diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp index b881d34ebe..1afebbbfaf 100644 --- a/engines/lastexpress/game/entities.cpp +++ b/engines/lastexpress/game/entities.cpp @@ -241,7 +241,7 @@ int Entities::getCompartments1(int index) const { // Savegame ////////////////////////////////////////////////////////////////////////// void Entities::saveLoadWithSerializer(Common::Serializer &s) { - _header->saveLoadWithSerializer(s); + _header->saveLoadWithSerializer(s, NULL); for (uint i = 1; i < _entities.size(); i++) _entities[i]->saveLoadWithSerializer(s); } @@ -1931,7 +1931,7 @@ void Entities::loadSceneFromEntityPosition(CarIndex car, EntityPosition entityPo // Determine position Position position = (alternate ? 1 : 40); do { - if (entityPosition > entityPositions[position]) { + if (alternate ? entityPosition < entityPositions[position] : entityPosition > entityPositions[position]) { if (alternate) break; @@ -1945,7 +1945,7 @@ void Entities::loadSceneFromEntityPosition(CarIndex car, EntityPosition entityPo } while (alternate ? position <= 18 : position >= 22); // For position outside bounds, use minimal value - if ((alternate && position > 18) || (alternate && position < 22)) { + if ((alternate && position > 18) || (!alternate && position < 22)) { getScenes()->loadSceneFromPosition(car, alternate ? 18 : 22); return; } @@ -2117,7 +2117,7 @@ label_process_entity: if (checkDistanceFromPosition(entity, kPosition_1500, 750) && entity != kEntityFrancois) { - if (data->entity != kEntityPlayer) { + if (data->entity == kEntityPlayer) { if (data->direction != kDirectionUp || (position <= kPosition_2000 && data->car == car)) { if (data->direction == kDirectionDown && (position < kPosition_1500 || data->car != car)) { if (data->entityPosition > kPosition_1500 && (data->car == kCarGreenSleeping || data->car == kCarRedSleeping)) { @@ -2282,8 +2282,8 @@ label_process_entity: } } } - return false; } + return false; } } else if (!flag1) { drawSequences(entity, direction, true); diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp index e2682ba0d1..ce53e6eadf 100644 --- a/engines/lastexpress/game/savegame.cpp +++ b/engines/lastexpress/game/savegame.cpp @@ -802,7 +802,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b // Skip padding uint32 offset = (uint32)_savegame->pos() - originalPosition; if (offset & 0xF) { - _savegame->seek((~offset & 0xF) + 1, SEEK_SET); + _savegame->seek((~offset & 0xF) + 1, SEEK_CUR); } } diff --git a/engines/lastexpress/game/savepoint.cpp b/engines/lastexpress/game/savepoint.cpp index a8483e6d5c..bd134c637c 100644 --- a/engines/lastexpress/game/savepoint.cpp +++ b/engines/lastexpress/game/savepoint.cpp @@ -162,8 +162,8 @@ void SavePoints::call(EntityIndex entity2, EntityIndex entity1, ActionIndex acti point.action = action; point.entity2 = entity2; - assert(param.size() <= 5); - strncpy((char *)&point.param.charValue, param.c_str(), 5); + assert(param.size() <= 6); // "MUS%03d" + strncpy((char *)&point.param.charValue, param.c_str(), 6); Callback *callback = getCallback(entity1); if (callback != NULL && callback->isValid()) { @@ -230,6 +230,8 @@ bool SavePoints::updateEntityFromData(const SavePoint &savepoint) { void SavePoints::saveLoadWithSerializer(Common::Serializer &s) { // Serialize savepoint data + if (s.isLoading()) + _data.clear(); uint32 dataSize = (s.isLoading() ? _savePointsMaxSize : _data.size()); for (uint i = 0; i < dataSize; i++) { if (s.isLoading()) { diff --git a/engines/lastexpress/game/savepoint.h b/engines/lastexpress/game/savepoint.h index ab6490796b..ea73e7c25d 100644 --- a/engines/lastexpress/game/savepoint.h +++ b/engines/lastexpress/game/savepoint.h @@ -58,7 +58,7 @@ struct SavePoint { EntityIndex entity2; union { uint32 intValue; - char charValue[5]; + char charValue[7]; // "MUS%03d" with terminating zero } param; SavePoint() { @@ -66,6 +66,7 @@ struct SavePoint { action = kActionNone; entity2 = kEntityPlayer; param.intValue = 0; + param.charValue[6] = 0; } Common::String toString() { diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h index 38cd851aaa..b46807b40e 100644 --- a/engines/lastexpress/game/state.h +++ b/engines/lastexpress/game/state.h @@ -313,13 +313,14 @@ public: * @return true if equal, false if not. */ bool isEqual(uint index, uint val) { - return getValueName(index) == val; + return getOrSetValueName(index) == val; } - uint32 getValueName(uint index, Common::String *name = NULL) { - #define EXPOSE_VALUE(idx, entryName) \ + uint32 getOrSetValueName(uint index, Common::String *name = NULL, const uint32* newValue = NULL) { + #define EXPOSE_VALUE(idx, entryName, fieldType) \ case idx: { \ if (name) (*name) = "" #entryName; \ + if (newValue) {entryName = (fieldType)*newValue;} \ return (uint32)entryName; \ } @@ -328,134 +329,134 @@ public: error("[GameProgress::getValueName] Invalid index value (was: %d, max:127)", index); break; - EXPOSE_VALUE(0, field_0); - EXPOSE_VALUE(1, jacket); - EXPOSE_VALUE(2, eventCorpseMovedFromFloor); - EXPOSE_VALUE(3, field_C); - EXPOSE_VALUE(4, eventCorpseFound); - EXPOSE_VALUE(5, field_14); - EXPOSE_VALUE(6, field_18); - EXPOSE_VALUE(7, portrait); - EXPOSE_VALUE(8, eventCorpseThrown); - EXPOSE_VALUE(9, field_24); - EXPOSE_VALUE(10, field_28); - EXPOSE_VALUE(11, chapter); - EXPOSE_VALUE(12, field_30); - EXPOSE_VALUE(13, eventMetAugust); - EXPOSE_VALUE(14, isNightTime); - EXPOSE_VALUE(15, field_3C); - EXPOSE_VALUE(16, field_40); - EXPOSE_VALUE(17, field_44); - EXPOSE_VALUE(18, field_48); - EXPOSE_VALUE(19, field_4C); - EXPOSE_VALUE(20, isTrainRunning); - EXPOSE_VALUE(21, field_54); - EXPOSE_VALUE(22, field_58); - EXPOSE_VALUE(23, field_5C); - EXPOSE_VALUE(24, field_60); - EXPOSE_VALUE(25, field_64); - EXPOSE_VALUE(26, field_68); - EXPOSE_VALUE(27, eventMertensAugustWaiting); - EXPOSE_VALUE(28, eventMertensKronosInvitation); - EXPOSE_VALUE(29, isEggOpen); - EXPOSE_VALUE(30, field_78); - EXPOSE_VALUE(31, field_7C); - EXPOSE_VALUE(32, field_80); - EXPOSE_VALUE(33, field_84); - EXPOSE_VALUE(34, field_88); - EXPOSE_VALUE(35, field_8C); - EXPOSE_VALUE(36, field_90); - EXPOSE_VALUE(37, field_94); - EXPOSE_VALUE(38, field_98); - EXPOSE_VALUE(39, field_9C); - EXPOSE_VALUE(40, field_A0); - EXPOSE_VALUE(41, field_A4); - EXPOSE_VALUE(42, field_A8); - EXPOSE_VALUE(43, field_AC); - EXPOSE_VALUE(44, field_B0); - EXPOSE_VALUE(45, field_B4); - EXPOSE_VALUE(46, field_B8); - EXPOSE_VALUE(47, field_BC); - EXPOSE_VALUE(48, field_C0); - EXPOSE_VALUE(49, field_C4); - EXPOSE_VALUE(50, field_C8); - EXPOSE_VALUE(51, field_CC); - EXPOSE_VALUE(52, eventMetBoutarel); - EXPOSE_VALUE(53, eventMetHadija); - EXPOSE_VALUE(54, eventMetYasmin); - EXPOSE_VALUE(55, field_DC); - EXPOSE_VALUE(56, field_E0); - EXPOSE_VALUE(57, field_E4); - EXPOSE_VALUE(58, field_E8); - EXPOSE_VALUE(59, field_EC); - EXPOSE_VALUE(60, field_F0); - EXPOSE_VALUE(61, field_F4); - EXPOSE_VALUE(62, field_F8); - EXPOSE_VALUE(63, field_FC); - EXPOSE_VALUE(64, field_100); - EXPOSE_VALUE(65, field_104); - EXPOSE_VALUE(66, field_108); - EXPOSE_VALUE(67, field_10C); - EXPOSE_VALUE(68, field_110); - EXPOSE_VALUE(69, field_114); - EXPOSE_VALUE(70, field_118); - EXPOSE_VALUE(71, field_11C); - EXPOSE_VALUE(72, field_120); - EXPOSE_VALUE(73, field_124); - EXPOSE_VALUE(74, field_128); - EXPOSE_VALUE(75, field_12C); - EXPOSE_VALUE(76, field_130); - EXPOSE_VALUE(77, field_134); - EXPOSE_VALUE(78, field_138); - EXPOSE_VALUE(79, field_13C); - EXPOSE_VALUE(80, field_140); - EXPOSE_VALUE(81, field_144); - EXPOSE_VALUE(82, field_148); - EXPOSE_VALUE(83, field_14C); - EXPOSE_VALUE(84, field_150); - EXPOSE_VALUE(85, field_154); - EXPOSE_VALUE(86, field_158); - EXPOSE_VALUE(87, field_15C); - EXPOSE_VALUE(88, field_160); - EXPOSE_VALUE(89, field_164); - EXPOSE_VALUE(90, field_168); - EXPOSE_VALUE(91, field_16C); - EXPOSE_VALUE(92, field_170); - EXPOSE_VALUE(93, field_174); - EXPOSE_VALUE(94, field_178); - EXPOSE_VALUE(95, field_17C); - EXPOSE_VALUE(96, field_180); - EXPOSE_VALUE(97, field_184); - EXPOSE_VALUE(98, field_188); - EXPOSE_VALUE(99, field_18C); - EXPOSE_VALUE(100, field_190); - EXPOSE_VALUE(101, field_194); - EXPOSE_VALUE(102, field_198); - EXPOSE_VALUE(103, field_19C); - EXPOSE_VALUE(104, field_1A0); - EXPOSE_VALUE(105, field_1A4); - EXPOSE_VALUE(106, field_1A8); - EXPOSE_VALUE(107, field_1AC); - EXPOSE_VALUE(108, field_1B0); - EXPOSE_VALUE(109, field_1B4); - EXPOSE_VALUE(110, field_1B8); - EXPOSE_VALUE(111, field_1BC); - EXPOSE_VALUE(112, field_1C0); - EXPOSE_VALUE(113, field_1C4); - EXPOSE_VALUE(114, field_1C8); - EXPOSE_VALUE(115, field_1CC); - EXPOSE_VALUE(116, field_1D0); - EXPOSE_VALUE(117, field_1D4); - EXPOSE_VALUE(118, field_1D8); - EXPOSE_VALUE(119, field_1DC); - EXPOSE_VALUE(120, field_1E0); - EXPOSE_VALUE(121, field_1E4); - EXPOSE_VALUE(122, field_1E8); - EXPOSE_VALUE(123, field_1EC); - EXPOSE_VALUE(124, field_1F0); - EXPOSE_VALUE(125, field_1F4); - EXPOSE_VALUE(126, field_1F8); - EXPOSE_VALUE(127, field_1FC); + EXPOSE_VALUE(0, field_0, uint32); + EXPOSE_VALUE(1, jacket, JacketType); + EXPOSE_VALUE(2, eventCorpseMovedFromFloor, bool); + EXPOSE_VALUE(3, field_C, uint32); + EXPOSE_VALUE(4, eventCorpseFound, bool); + EXPOSE_VALUE(5, field_14, uint32); + EXPOSE_VALUE(6, field_18, uint32); + EXPOSE_VALUE(7, portrait, uint32); + EXPOSE_VALUE(8, eventCorpseThrown, bool); + EXPOSE_VALUE(9, field_24, uint32); + EXPOSE_VALUE(10, field_28, uint32); + EXPOSE_VALUE(11, chapter, ChapterIndex); + EXPOSE_VALUE(12, field_30, uint32); + EXPOSE_VALUE(13, eventMetAugust, bool); + EXPOSE_VALUE(14, isNightTime, bool); + EXPOSE_VALUE(15, field_3C, uint32); + EXPOSE_VALUE(16, field_40, uint32); + EXPOSE_VALUE(17, field_44, uint32); + EXPOSE_VALUE(18, field_48, uint32); + EXPOSE_VALUE(19, field_4C, uint32); + EXPOSE_VALUE(20, isTrainRunning, bool); + EXPOSE_VALUE(21, field_54, uint32); + EXPOSE_VALUE(22, field_58, uint32); + EXPOSE_VALUE(23, field_5C, uint32); + EXPOSE_VALUE(24, field_60, uint32); + EXPOSE_VALUE(25, field_64, uint32); + EXPOSE_VALUE(26, field_68, uint32); + EXPOSE_VALUE(27, eventMertensAugustWaiting, bool); + EXPOSE_VALUE(28, eventMertensKronosInvitation, bool); + EXPOSE_VALUE(29, isEggOpen, bool); + EXPOSE_VALUE(30, field_78, uint32); + EXPOSE_VALUE(31, field_7C, uint32); + EXPOSE_VALUE(32, field_80, uint32); + EXPOSE_VALUE(33, field_84, uint32); + EXPOSE_VALUE(34, field_88, uint32); + EXPOSE_VALUE(35, field_8C, uint32); + EXPOSE_VALUE(36, field_90, uint32); + EXPOSE_VALUE(37, field_94, uint32); + EXPOSE_VALUE(38, field_98, uint32); + EXPOSE_VALUE(39, field_9C, uint32); + EXPOSE_VALUE(40, field_A0, uint32); + EXPOSE_VALUE(41, field_A4, uint32); + EXPOSE_VALUE(42, field_A8, uint32); + EXPOSE_VALUE(43, field_AC, uint32); + EXPOSE_VALUE(44, field_B0, uint32); + EXPOSE_VALUE(45, field_B4, uint32); + EXPOSE_VALUE(46, field_B8, uint32); + EXPOSE_VALUE(47, field_BC, uint32); + EXPOSE_VALUE(48, field_C0, uint32); + EXPOSE_VALUE(49, field_C4, uint32); + EXPOSE_VALUE(50, field_C8, uint32); + EXPOSE_VALUE(51, field_CC, uint32); + EXPOSE_VALUE(52, eventMetBoutarel, bool); + EXPOSE_VALUE(53, eventMetHadija, bool); + EXPOSE_VALUE(54, eventMetYasmin, bool); + EXPOSE_VALUE(55, field_DC, uint32); + EXPOSE_VALUE(56, field_E0, uint32); + EXPOSE_VALUE(57, field_E4, uint32); + EXPOSE_VALUE(58, field_E8, uint32); + EXPOSE_VALUE(59, field_EC, uint32); + EXPOSE_VALUE(60, field_F0, uint32); + EXPOSE_VALUE(61, field_F4, uint32); + EXPOSE_VALUE(62, field_F8, uint32); + EXPOSE_VALUE(63, field_FC, uint32); + EXPOSE_VALUE(64, field_100, uint32); + EXPOSE_VALUE(65, field_104, uint32); + EXPOSE_VALUE(66, field_108, uint32); + EXPOSE_VALUE(67, field_10C, uint32); + EXPOSE_VALUE(68, field_110, uint32); + EXPOSE_VALUE(69, field_114, uint32); + EXPOSE_VALUE(70, field_118, uint32); + EXPOSE_VALUE(71, field_11C, uint32); + EXPOSE_VALUE(72, field_120, uint32); + EXPOSE_VALUE(73, field_124, uint32); + EXPOSE_VALUE(74, field_128, uint32); + EXPOSE_VALUE(75, field_12C, uint32); + EXPOSE_VALUE(76, field_130, uint32); + EXPOSE_VALUE(77, field_134, uint32); + EXPOSE_VALUE(78, field_138, uint32); + EXPOSE_VALUE(79, field_13C, uint32); + EXPOSE_VALUE(80, field_140, uint32); + EXPOSE_VALUE(81, field_144, uint32); + EXPOSE_VALUE(82, field_148, uint32); + EXPOSE_VALUE(83, field_14C, uint32); + EXPOSE_VALUE(84, field_150, uint32); + EXPOSE_VALUE(85, field_154, uint32); + EXPOSE_VALUE(86, field_158, uint32); + EXPOSE_VALUE(87, field_15C, uint32); + EXPOSE_VALUE(88, field_160, uint32); + EXPOSE_VALUE(89, field_164, uint32); + EXPOSE_VALUE(90, field_168, uint32); + EXPOSE_VALUE(91, field_16C, uint32); + EXPOSE_VALUE(92, field_170, uint32); + EXPOSE_VALUE(93, field_174, uint32); + EXPOSE_VALUE(94, field_178, uint32); + EXPOSE_VALUE(95, field_17C, uint32); + EXPOSE_VALUE(96, field_180, uint32); + EXPOSE_VALUE(97, field_184, uint32); + EXPOSE_VALUE(98, field_188, uint32); + EXPOSE_VALUE(99, field_18C, uint32); + EXPOSE_VALUE(100, field_190, uint32); + EXPOSE_VALUE(101, field_194, uint32); + EXPOSE_VALUE(102, field_198, uint32); + EXPOSE_VALUE(103, field_19C, uint32); + EXPOSE_VALUE(104, field_1A0, uint32); + EXPOSE_VALUE(105, field_1A4, uint32); + EXPOSE_VALUE(106, field_1A8, uint32); + EXPOSE_VALUE(107, field_1AC, uint32); + EXPOSE_VALUE(108, field_1B0, uint32); + EXPOSE_VALUE(109, field_1B4, uint32); + EXPOSE_VALUE(110, field_1B8, uint32); + EXPOSE_VALUE(111, field_1BC, uint32); + EXPOSE_VALUE(112, field_1C0, uint32); + EXPOSE_VALUE(113, field_1C4, uint32); + EXPOSE_VALUE(114, field_1C8, uint32); + EXPOSE_VALUE(115, field_1CC, uint32); + EXPOSE_VALUE(116, field_1D0, uint32); + EXPOSE_VALUE(117, field_1D4, uint32); + EXPOSE_VALUE(118, field_1D8, uint32); + EXPOSE_VALUE(119, field_1DC, uint32); + EXPOSE_VALUE(120, field_1E0, uint32); + EXPOSE_VALUE(121, field_1E4, uint32); + EXPOSE_VALUE(122, field_1E8, uint32); + EXPOSE_VALUE(123, field_1EC, uint32); + EXPOSE_VALUE(124, field_1F0, uint32); + EXPOSE_VALUE(125, field_1F4, uint32); + EXPOSE_VALUE(126, field_1F8, uint32); + EXPOSE_VALUE(127, field_1FC, uint32); } } @@ -464,7 +465,7 @@ public: for (uint i = 0; i < 128; i++) { Common::String name = ""; - uint val = getValueName(i, &name); + uint val = getOrSetValueName(i, &name, NULL); ret += Common::String::format("(%03d) %s = %d\n", i, name.c_str(), val); } @@ -472,9 +473,17 @@ public: } void saveLoadWithSerializer(Common::Serializer &s) { - for (uint i = 0; i < 128; i++) { - uint32 val = getValueName(i); - s.syncAsUint32LE(val); + if (s.isLoading()) { + for (uint i = 0; i < 128; i++) { + uint32 val; + s.syncAsUint32LE(val); + getOrSetValueName(i, NULL, &val); + } + } else { + for (uint i = 0; i < 128; i++) { + uint32 val = getOrSetValueName(i); + s.syncAsUint32LE(val); + } } } }; diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index 724c4b3fb4..1b703acd09 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -274,6 +274,7 @@ enum TimeValue { kTime2097000 = 2097000, // Day 2, 14:50 kTimeEnterLinz = 2099700, // Day 2, 14:53 kTimeCityLinz = 2101500, // Day 2, 14:55 + kTimeExitLinz = 2105100, // Day 2, 14:59 kTime2106000 = 2106000, // Day 2, 15:00 kTime2110500 = 2110500, // Day 2, 15:05 kTime2115000 = 2115000, // Day 2, 15:10 @@ -373,14 +374,18 @@ enum TimeValue { kTimeTrainStopped = 2898000, // Day 3, 05:40 kTime2907000 = 2907000, // Day 3, 05:50 kTime2916000 = 2916000, // Day 3, 06:00 - kTimeCityBelgrade = 2952000, // Day 3, 06:40 + kTime2934000 = 2934000, // Day 3, 06:20 kTimeTrainStopped2 = 2943000, // Day 3, 06:30 + kTime2949300 = 2949300, // Day 3, 06:37 + kTimeCityBelgrade = 2952000, // Day 3, 06:40 kTime2983500 = 2983500, // Day 3, 07:15 kTimeCityNish = 3205800, // Day 3, 11:22 kTimeCityTzaribrod = 3492000, // Day 3, 16:40 kTime3645000 = 3645000, // Day 3, 19:30 kTimeCitySofia = 3690000, // Day 3, 20:20 kTimeCityAdrianople = 4320900, // Day 4, 08:01 + kTime4914000 = 4914000, // Day 4, 19:00 + kTime4920300 = 4920300, // Day 4, 19:07 kTime4923000 = 4923000, // Day 4, 19:10 kTime4929300 = 4929300, // Day 4, 19:17 kTimeCityConstantinople = 4941000, // Day 4, 19:30 @@ -1193,8 +1198,8 @@ enum EventIndex { kEventVergesSuitcaseNightOtherEntryStart = 137, kEventMertensAskTylerCompartment = 138, kEventMertensAskTylerCompartmentD = 139, - kEventMertensPushCall = 140, - kEventMertensPushCallNight = 141, + kEventMertensPushCallNight = 140, + kEventMertensPushCall = 141, kEventMertensAugustWaiting = 142, kEventMertensAugustWaitingCompartment = 143, kEventIntroBroderbrund = 144, @@ -1232,8 +1237,8 @@ enum EventIndex { kEventCathSalkoTrainTopWin = 176, kEventFrancoisWhistle = 177, kEventFrancoisWhistleD = 178, - kEventFrancoisWhistleNight = 179, - kEventFrancoisWhistleNightD = 180, + kEventFrancoisWhistleNightD = 179, + kEventFrancoisWhistleNight = 180, kEventFrancoisShowBeetle = 181, kEventFrancoisShowBeetleD = 182, kEventFrancoisTradeWhistle = 183, diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 7308214551..87ecd26cdb 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -93,7 +93,7 @@ void SoundEntry::close() { _status.status |= kSoundStatusClosed; // Loop until ready - //while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) + //while (!(_status.b.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) // ; // empty loop body // The original game remove the entry from the cache here, @@ -246,7 +246,7 @@ void SoundEntry::loadStream(Common::String name) { } void SoundEntry::update(uint val) { - if (!(_status.status3 & 64)) { + if (!(_status.b.status3 & 64)) { int value2 = val; _status.status |= kSoundStatus_100000; @@ -271,10 +271,10 @@ bool SoundEntry::updateSound() { bool result; char sub[16]; - if (_status.status2 & 4) { + if (_status.b.status2 & 4) { result = false; } else { - if (_status.status2 & 0x80) { + if (_status.b.status2 & 0x80) { if (_field_48 <= getSound()->getData2()) { _status.status |= 0x20; _status.status &= ~0x8000; @@ -288,7 +288,7 @@ bool SoundEntry::updateSound() { } } else { if (!(getSoundQueue()->getFlag() & 0x20)) { - if (!(_status.status3 & 8)) { + if (!(_status.b.status3 & 8)) { if (_entity) { if (_entity < 0x80) { updateEntryFlag(getSound()->getSoundFlag(_entity)); @@ -296,7 +296,7 @@ bool SoundEntry::updateSound() { } } } - //if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer) + //if (status.b.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer) // Sound_FillSoundBuffer(v1); } result = true; @@ -354,7 +354,7 @@ void SoundEntry::showSubtitle(Common::String filename) { _subtitle = new SubtitleEntry(_engine); _subtitle->load(filename, this); - if (_subtitle->getStatus().status2 & 4) { + if (_subtitle->getStatus().b.status2 & 4) { _subtitle->draw(); SAFE_DELETE(_subtitle); } else { diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index d92b16a5dd..0ebe550a02 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -76,12 +76,15 @@ namespace LastExpress { class LastExpressEngine; class SubtitleEntry; +// TODO: this union assumes little-endian machine union SoundStatusUnion { uint32 status; - byte status1; - byte status2; - byte status3; - byte status4; + struct { + byte status1; + byte status2; + byte status3; + byte status4; + } b; SoundStatusUnion() { status = 0; diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index fe6d6f2251..a088da319f 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -132,7 +132,7 @@ void SoundQueue::updateQueue() { // and if the sound data buffer is not full, loads a new entry to be played based on // its priority and filter id - if (!entry->updateSound() && !(entry->getStatus().status3 & 0x8)) { + if (!entry->updateSound() && !(entry->getStatus().b.status3 & 0x8)) { entry->close(); SAFE_DELETE(entry); it = _soundList.reverse_erase(it); diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp index 3a2d0c075c..ca79915c66 100644 --- a/engines/lastexpress/sound/sound.cpp +++ b/engines/lastexpress/sound/sound.cpp @@ -136,7 +136,7 @@ SoundManager::~SoundManager() { // Sound-related functions ////////////////////////////////////////////////////////////////////////// void SoundManager::playSound(EntityIndex entity, Common::String filename, SoundFlag flag, byte a4) { - if (_queue->isBuffered(entity) && entity) + if (_queue->isBuffered(entity) && entity && entity < kEntityTrain) _queue->removeFromQueue(entity); SoundFlag currentFlag = (flag == -1) ? getSoundFlag(entity) : (SoundFlag)(flag | 0x80000); @@ -372,6 +372,8 @@ void SoundManager::playLocomotiveSound() { } const char *SoundManager::getDialogName(EntityIndex entity) const { + if (_queue->isBuffered(kEntityTables4)) + return NULL; switch (entity) { case kEntityAnna: if (getEvent(kEventAnnaDialogGoToJerusalem)) @@ -558,7 +560,7 @@ const char *SoundManager::getDialogName(EntityIndex entity) const { return "XKRO4"; if (getEvent(kEventKronosConversation)) { - if (!getEvent(kEventMilosCompartmentVisitAugust)) + if (getEvent(kEventMilosCompartmentVisitAugust)) return "XKRO3"; else return "XKRO2"; @@ -675,7 +677,7 @@ const char *SoundManager::getDialogName(EntityIndex entity) const { // Letters & Messages ////////////////////////////////////////////////////////////////////////// void SoundManager::readText(int id) { - if (!_queue->isBuffered(kEntityTables4)) + if (_queue->isBuffered(kEntityTables4)) return; if (id < 0 || (id > 8 && id < 50) || id > 64) @@ -840,9 +842,9 @@ void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compar } if (rnd(2) || getEntities()->isInsideCompartment(kEntityAnna, kCarRedSleeping, kPosition_4070)) - getSound()->playSound(kEntityCoudert, "Jac1503", kFlagDefault); - else getSound()->playSound(kEntityCoudert, "Jac1503A", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, "Jac1503", kFlagDefault); break; case kObjectCompartmentG: @@ -851,6 +853,10 @@ void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compar break; } + // BUG: the original game got isInsideCompartment() inverted + // Jac1502A is "the serbian gentleman is not in, monsier", + // Jac1502 is a generic response, + // so Coudert only says "Milos is not in" when Milos is actually in. if (rnd(2) || getEntities()->isInsideCompartment(kEntityMilos, kCarRedSleeping, kPosition_3050)) getSound()->playSound(kEntityCoudert, "Jac1502", kFlagDefault); else @@ -922,7 +928,7 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f if (Entities::isFemale(entity2)) { playSound(kEntityPlayer, (rnd(2) ? "CON1111" : "CON1111A"), flag); } else { - if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) { + if (entity2 != kEntityPlayer || getProgress().jacket != kJacketGreen || !rnd(2)) { switch(rnd(3)) { default: break; @@ -941,9 +947,9 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f } } else { if (isNight()) { - playSound(kEntityPlayer, (getProgress().field_18 == 2 ? "CON1110F" : "CON1110E")); + playSound(kEntityPlayer, (getProgress().field_18 == 2 ? "CON1110F" : "CON1110E"), flag); } else { - playSound(kEntityPlayer, "CON1110D"); + playSound(kEntityPlayer, "CON1110D", flag); } } } @@ -953,7 +959,7 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f if (Entities::isFemale(entity2)) { playSound(kEntityPlayer, "JAC1111D", flag); } else { - if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) { + if (entity2 != kEntityPlayer || getProgress().jacket != kJacketGreen || !rnd(2)) { switch(rnd(4)) { default: break; @@ -981,7 +987,7 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f break; case kEntityPascale: - playSound(kEntityPlayer, (rnd(2) ? "HDE1002" : "HED1002A"), flag); + playSound(kEntityPlayer, (rnd(2) ? "HED1002" : "HED1002A"), flag); break; case kEntityWaiter1: @@ -1006,7 +1012,7 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f case kEntityVerges: if (Entities::isFemale(entity2)) { - playSound(kEntityPlayer, (rnd(2) ? "TRA1113A" : "TRA1113B")); + playSound(kEntityPlayer, (rnd(2) ? "TRA1113A" : "TRA1113B"), flag); } else { playSound(kEntityPlayer, "TRA1112", flag); } @@ -1097,7 +1103,7 @@ void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag f break; case kEntityRebecca: - playSound(kEntityPlayer, (rnd(2) ? "REB1106" : "REB110A"), flag); + playSound(kEntityPlayer, (rnd(2) ? "REB1106" : "Reb1106A"), flag); break; case kEntitySophie: { @@ -1239,8 +1245,8 @@ SoundFlag SoundManager::getSoundFlag(EntityIndex entity) const { if (index < 32) ret = soundFlags[index]; - if (getEntityData(entity)->location == kLocationOutsideTrain) { - if (getEntityData(entity)->car != kCarKronos + if (getEntityData(kEntityPlayer)->location == kLocationOutsideTrain) { + if (getEntityData(kEntityPlayer)->car != kCarKronos && !getEntities()->isOutsideAlexeiWindow() && !getEntities()->isOutsideAnnaWindow()) return kFlagNone; @@ -1254,25 +1260,24 @@ SoundFlag SoundManager::getSoundFlag(EntityIndex entity) const { case kCarKronos: if (getEntities()->isInKronosSalon(entity) != getEntities()->isInKronosSalon(kEntityPlayer)) - ret = (SoundFlag)(ret * 2); + ret = (SoundFlag)(ret / 2); break; case kCarGreenSleeping: case kCarRedSleeping: - if (getEntities()->isInGreenCarEntrance(kEntityPlayer) && !getEntities()->isInKronosSalon(entity)) - ret = (SoundFlag)(ret * 2); + if (getEntities()->isInGreenCarEntrance(kEntityPlayer) && !getEntities()->isInGreenCarEntrance(entity)) + ret = (SoundFlag)(ret / 2); - if (getEntityData(kEntityPlayer)->location - && (getEntityData(entity)->entityPosition != kPosition_1 || !getEntities()->isDistanceBetweenEntities(kEntityPlayer, entity, 400))) - ret = (SoundFlag)(ret * 2); + if (getEntityData(kEntityPlayer)->location == kLocationInsideCompartment + && (getEntityData(entity)->location != kLocationInsideCompartment || !getEntities()->isDistanceBetweenEntities(kEntityPlayer, entity, 400))) + ret = (SoundFlag)(ret / 2); break; case kCarRestaurant: - if (getEntities()->isInSalon(entity) == getEntities()->isInSalon(kEntityPlayer) - && (getEntities()->isInRestaurant(entity) != getEntities()->isInRestaurant(kEntityPlayer))) - ret = (SoundFlag)(ret * 2); - else - ret = (SoundFlag)(ret * 4); + if (getEntities()->isInSalon(entity) != getEntities()->isInSalon(kEntityPlayer)) + ret = (SoundFlag)(ret / 4); + else if (getEntities()->isInRestaurant(entity) != getEntities()->isInRestaurant(kEntityPlayer)) + ret = (SoundFlag)(ret / 2); break; } @@ -1314,7 +1319,7 @@ void SoundManager::playLoopingSound(int param) { partNumber = 6; } else { if (getEntities()->isInsideCompartments(kEntityPlayer)) { - int objNum = (getEntityData(kEntityPlayer)->car - 3) < 1 ? 9 : 40; // Weird numbers + int objNum = (getEntityData(kEntityPlayer)->car == kCarGreenSleeping) ? 9 : 40; // Weird numbers numLoops[0] = 0; @@ -1323,7 +1328,7 @@ void SoundManager::playLoopingSound(int param) { break; if (getEntities()->isInsideCompartment(kEntityPlayer, getEntityData(kEntityPlayer)->car, positions[pos])) { numLoops[0] = 1; - partNumber = (getObjects()->get((ObjectIndex)objNum).status - 2) < 1 ? 6 : 1; + partNumber = (getObjects()->get((ObjectIndex)objNum).status == kObjectLocation2) ? 6 : 1; } objNum++; } |