From def40a625a0767ddf30c42f03aba44ec58ea5a07 Mon Sep 17 00:00:00 2001 From: Julien Templier Date: Thu, 21 Oct 2010 23:41:22 +0000 Subject: LASTEXPRESS: Implement remaining AI logic functions for Kahina and Kronos svn-id: r53684 --- engines/lastexpress/entities/kahina.cpp | 255 +++++++++++++++++++++++++++++++- engines/lastexpress/entities/kronos.cpp | 228 +++++++++++++++++++++++++++- engines/lastexpress/game/sound.cpp | 9 ++ engines/lastexpress/game/sound.h | 8 +- engines/lastexpress/shared.h | 3 + 5 files changed, 499 insertions(+), 4 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp index 1655e90394..2180ea2a0d 100644 --- a/engines/lastexpress/entities/kahina.cpp +++ b/engines/lastexpress/entities/kahina.cpp @@ -391,7 +391,163 @@ IMPLEMENT_FUNCTION(14, Kahina, function14) ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(15, Kahina, function15) - error("Kahina: callback function 15 not implemented!"); + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param2 != kTimeInvalid) { + UPDATE_PARAM_PROC_TIME(params->param1, !getEntities()->isPlayerInCar(kCarRedSleeping), params->param2, 0) + setCallback(9); + setup_updateEntity(kCarRedSleeping, kPosition_4070); + UPDATE_PARAM_PROC_END + } + break; + + case kActionDefault: + getProgress().field_14 = 19; + + setCallback(1); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + if (getEntities()->hasValidFrame(kEntityKahina)) { + setCallback(2); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + } + // Fallback to next case + + case 4: + if (getEntities()->isInsideCompartment(kEntityPlayer, kCarGreenSleeping, kPosition_8200) + || getEntities()->isOutsideAlexeiWindow() + || getEntities()->isDistanceBetweenEntities(kEntityKahina, kEntityPlayer, 2000)) { + if (getProgress().field_14 == 19) + getProgress().field_14 = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_9460); + } else { + setCallback(5); + setup_enterExitCompartment("616Aa", kObjectCompartment1); + } + break; + + case 2: + setCallback(3); + setup_updateFromTime(1800); + break; + + case 3: + setCallback(4); + setup_updateEntity(kCarGreenSleeping, kPosition_8200); + break; + + case 5: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityKahina); + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + getObjects()->update(kObjectHandleBathroom, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + + setCallback(6); + setup_updateFromTime(900); + break; + + case 6: + getObjects()->update(kObjectCompartment1, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + getObjects()->update(kObjectHandleBathroom, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + setCallback(7); + setup_enterExitCompartment("616Ba", kObjectCompartment1); + break; + + case 7: + getData()->location = kLocationOutsideCompartment; + + if (getProgress().field_14 == 19) + getProgress().field_14 = 0; + + setCallback(8); + setup_updateEntity(kCarGreenSleeping, kPosition_9460); + break; + + case 8: + getEntities()->clearSequences(kEntityKahina); + params->param1 = getState()->time + 4500; + break; + + case 9: + setCallback(10); + setup_function14(); + break; + + case 10: + setCallback(11); + setup_updateEntity(kCarRedSleeping, kPosition_6470); + break; + + case 11: + if (getEntities()->checkFields19(kEntityPlayer, kCarRedSleeping, kPosition_6130)) { + setCallback(15); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + } else { + setCallback(12); + setup_enterExitCompartment("616Ac", kObjectCompartmentC); + } + break; + + case 12: + getData()->location = kLocationInsideCompartment; + getEntities()->clearSequences(kEntityKahina); + + getObjects()->update(kObjectCompartmentC, kEntityPlayer, getObjects()->get(kObjectCompartmentC).location, kCursorNormal, kCursorNormal); + getObjects()->update(kObject50, kEntityPlayer, getObjects()->get(kObject50).location, kCursorNormal, kCursorNormal); + + setCallback(13); + setup_updateFromTime(900); + break; + + case 13: + getObjects()->update(kObjectCompartmentC, kEntityPlayer, getObjects()->get(kObjectCompartmentC).location, kCursorHandKnock, kCursorHand); + getObjects()->update(kObject50, kEntityPlayer, getObjects()->get(kObject50).location, kCursorHandKnock, kCursorHand); + + setCallback(14); + setup_enterExitCompartment("616Bc", kObjectCompartmentC); + break; + + case 14: + getData()->location = kLocationOutsideCompartment; + + setCallback(15); + setup_updateEntity(kCarRedSleeping, kPosition_9460); + break; + + case 15: + getEntities()->clearSequences(kEntityKahina); + + setCallback(16); + setup_updateFromTime(900); + break; + + case 16: + setCallback(17); + setup_updateEntity(kCarKronos, kPosition_9270); + break; + + case 17: + getEntities()->clearSequences(kEntityKahina); + + CALLBACK_ACTION(); + break; + } + break; + } } ////////////////////////////////////////////////////////////////////////// @@ -763,7 +919,102 @@ label_callback_2: ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(21, Kahina, function21) - error("Kahina: callback function 21 not implemented!"); + switch (savepoint.action) { + default: + break; + + case kActionNone: + if (params->param1) { + if (!params->param3) + params->param3 = getState()->time + 4500; + + if (params->param6 != kTimeInvalid) { + UPDATE_PARAM_PROC_TIME(params->param3, (getEntities()->isPlayerPosition(kCarKronos, 80) || getEntities()->isPlayerPosition(kCarKronos, 88)), params->param5, 0) + setCallback(2); + setup_function23(); + break; + UPDATE_PARAM_PROC_END + } + } + +label_callback_2: + if (params->param2) { + + if (!params->param4) + params->param4 = getState()->time + 4500; + + if (params->param6 != kTimeInvalid) { + UPDATE_PARAM_PROC_TIME(params->param3, (getEntities()->isPlayerPosition(kCarKronos, 80) || getEntities()->isPlayerPosition(kCarKronos, 88)), params->param6, 0) + getSound()->playSound(kEntityPlayer, "LIB014", getSound()->getSoundFlag(kEntityKahina)); + getSound()->playSound(kEntityPlayer, "LIB015", getSound()->getSoundFlag(kEntityKahina)); + + getEntities()->drawSequenceLeft(kEntityKahina, "202a"); + + params->param2 = 0; + UPDATE_PARAM_PROC_END + } + } + + if (!getProgress().field_44 + && getState()->time > kTime2214000) { + + ObjectLocation location = getInventory()->get(kItemFirebird)->location; + + if (location == kObjectLocation3 || location == kObjectLocation7) { + setCallback(3); + setup_function25(); + } else if (location == kObjectLocation1 || location == kObjectLocation2) { + setCallback(4); + setup_function26(); + } + } + break; + + case kActionDefault: + getData()->car = kCarKronos; + getData()->entityPosition = kPosition_5000; + getData()->location = kLocationOutsideCompartment; + + getEntities()->drawSequenceLeft(kEntityKahina, "202a"); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + params->param1 = 0; + params->param2 = 1; + break; + + case 2: + params->param1 = 0; + params->param2 = 1; + goto label_callback_2; + } + break; + + case kAction92186062: + if (params->param1) { + setCallback(1); + setup_function23(); + } + break; + + case kAction134611040: + if (getEvent(kEventConcertLeaveWithBriefcase)) + setup_function24(); + break; + + case kAction137503360: + setup_function22(); + break; + + case kAction237555748: + params->param1 = 1; + break; + } } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp index c73cac3fbc..935f707e43 100644 --- a/engines/lastexpress/entities/kronos.cpp +++ b/engines/lastexpress/entities/kronos.cpp @@ -27,6 +27,7 @@ #include "lastexpress/entities/anna.h" #include "lastexpress/entities/august.h" +#include "lastexpress/entities/kahina.h" #include "lastexpress/entities/rebecca.h" #include "lastexpress/entities/sophie.h" #include "lastexpress/entities/tatiana.h" @@ -46,6 +47,23 @@ namespace LastExpress { +static const struct { + uint32 time; + char *sequence; +} concertData[54] = { + {735, "201d"}, {1395, "201a"}, {1965, "201d"}, {2205, "201a"}, {3405, "201d"}, + {3750, "201a"}, {3975, "201d"}, {4365, "201a"}, {4650, "201d"}, {4770, "201a"}, + {4995, "201e"}, {5085, "201d"}, {5430, "201a"}, {5685, "201d"}, {5850, "201a"}, + {7515, "201d"}, {7620, "201a"}, {7785, "201d"}, {7875, "201a"}, {8235, "201d"}, + {8340, "201a"}, {8745, "201d"}, {8805, "201a"}, {8925, "201d"}, {8985, "201a"}, + {9765, "201d"}, {9930, "201a"}, {12375, "201e"}, {12450, "201d"}, {12705, "201c"}, + {13140, "201d"}, {13305, "201a"}, {13380, "201d"}, {13560, "201a"}, {14145, "201d"}, + {14385, "201a"}, {14445, "201c"}, {14805, "201a"}, {16485, "201d"}, {16560, "201a"}, + {16755, "201d"}, {16845, "201a"}, {17700, "201d"}, {17865, "201a"}, {18645, "201d"}, + {18720, "201a"}, {19410, "201e"}, {19500, "201a"}, {22020, "201d"}, {22185, "201a"}, + {22590, "201d"}, {22785, "201a"}, {23085, "201d"}, {23265, "201a"} +}; + Kronos::Kronos(LastExpressEngine *engine) : Entity(engine, kEntityKronos) { ADD_CALLBACK_FUNCTION(Kronos, reset); ADD_CALLBACK_FUNCTION(Kronos, savegame); @@ -460,7 +478,215 @@ IMPLEMENT_FUNCTION(19, Kronos, function19) ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(20, Kronos, function20) - error("Kronos: callback function 20 not implemented!"); + switch (savepoint.action) { + default: + break; + + case kActionNone: + params->param5 = getSound()->getEntryTime(kEntityKronos)* 2; + + if (params->param6 < ARRAYSIZE(concertData) && params->param5 > concertData[params->param6].time) { + + getEntities()->drawSequenceLeft(kEntityKronos, (char *)&concertData[params->param6].sequence); + + if (stricmp((char *)&concertData[params->param6].sequence, "201e")) { + + if (stricmp((char *)&concertData[params->param6].sequence, "201c")) { + + if (!stricmp((char *)&concertData[params->param6].sequence, "201d")) { + if (getEntities()->isPlayerPosition(kCarKronos, 86)) + getScenes()->loadSceneFromPosition(kCarKronos, 83); + + getEntities()->updatePositionEnter(kEntityKronos, kCarKronos, 86); + getEntities()->updatePositionExit(kEntityKronos, kCarKronos, 85); + } else { + getEntities()->updatePositionExit(kEntityKronos, kCarKronos, 85); + getEntities()->updatePositionExit(kEntityKronos, kCarKronos, 86); + } + } else { + if (getEntities()->isPlayerPosition(kCarKronos, 85)) + getScenes()->loadSceneFromPosition(kCarKronos, 83); + + getEntities()->updatePositionEnter(kEntityKronos, kCarKronos, 85); + getEntities()->updatePositionExit(kEntityKronos, kCarKronos, 86); + } + } else { + if (getEntities()->isPlayerPosition(kCarKronos, 85) || getEntities()->isPlayerPosition(kCarKronos, 86)) + getScenes()->loadSceneFromPosition(kCarKronos, 83); + + getEntities()->updatePositionEnter(kEntityKronos, kCarKronos, 85); + getEntities()->updatePositionEnter(kEntityKronos, kCarKronos, 86); + } + + ++params->param6; + } + + getObjects()->update(kObject76, kEntityKronos, kObjectLocationNone, kCursorNormal, getInventory()->hasItem(kItemBriefcase) ? kCursorHand : kCursorNormal); + + if (!params->param7) { + params->param7 = getState()->time + 2700; + params->param8 = getState()->time + 13500; + } + + if (CURRENT_PARAMS(1, 2) != kTimeInvalid && params->param7 < getState()->time) { + UPDATE_PARAM_PROC_TIME(params->param8, !params->param1, CURRENT_PARAMS(1, 2), 450) + getSavePoints()->push(kEntityKronos, kEntityKahina, kAction237555748); + UPDATE_PARAM_PROC_END + } + + if (!params->param1) + params->param2 = params->param3; + + params->param2 -= getState()->timeDelta; + + if (params->param2 < getState()->timeDelta) { + + getSavePoints()->push(kEntityKronos, kEntityKahina, kAction92186062); + + ++params->param4; + switch (params->param4) { + default: + break; + + case 1: + getAction()->playAnimation(kEventCathWakingUp); + getScenes()->processScene(); + params->param3 = 1800; + break; + + case 2: + getAction()->playAnimation(kEventCathWakingUp); + getScenes()->processScene(); + params->param3 = 3600; + break; + + case 3: + getAction()->playAnimation(kEventCathFallingAsleep); + + while (getSound()->isBuffered("1919.LNK")) + getSound()->updateQueue(); + + getAction()->playAnimation(kEventCathWakingUp); + getScenes()->processScene(); + params->param3 = 162000; + break; + } + params->param2 = params->param3; + } + + if (params->param5 > 23400 || CURRENT_PARAMS(1, 1)) { + if (getEntities()->isInKronosSanctum(kEntityPlayer)) { + setCallback(1); + setup_savegame(kSavegameTypeEvent, kEventKahinaWrongDoor); + } + } + break; + + case kActionEndSound: + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorHandKnock, kCursorHand); + + if (CURRENT_PARAMS(1, 1)) { + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 26); + + setup_function21(); + break; + } + + if (getEntities()->isInKronosSalon(kEntityPlayer)) { + setCallback(3); + setup_savegame(kSavegameTypeEvent, kEventConcertEnd); + break; + } + + if (getEntities()->isInsideTrainCar(kEntityPlayer, kCarKronos)) { + getSound()->playSound(kEntityKronos, "Kro3001"); + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorNormal, kCursorNormal); + CURRENT_PARAMS(1, 1) = 1; + break; + } + + setup_function21(); + break; + + case kActionOpenDoor: + setCallback(2); + setup_savegame(kSavegameTypeEvent, kEventConcertLeaveWithBriefcase); + break; + + case kActionDefault: + getState()->time = kTime2115000; + getState()->timeDelta = 3; + + params->param1 = (getEntities()->isPlayerPosition(kCarKronos, 88) + || getEntities()->isPlayerPosition(kCarKronos, 84) + || getEntities()->isPlayerPosition(kCarKronos, 85) + || getEntities()->isPlayerPosition(kCarKronos, 86) + || getEntities()->isPlayerPosition(kCarKronos, 83)); + + if (getInventory()->hasItem(kItemFirebird)) + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorNormal); + else + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getObjects()->update(kObject76, kEntityKronos, kObjectLocationNone, kCursorHandKnock, kCursorHand); + + getProgress().field_40 = 1; + getEntities()->drawSequenceLeft(kEntityKronos, "201a"); + + params->param2 = 2700; + params->param3 = 2700; + break; + + case kActionDrawScene: + params->param1 = (getEntities()->isPlayerPosition(kCarKronos, 88) + || getEntities()->isPlayerPosition(kCarKronos, 84) + || getEntities()->isPlayerPosition(kCarKronos, 85) + || getEntities()->isPlayerPosition(kCarKronos, 86) + || getEntities()->isPlayerPosition(kCarKronos, 83)); + + if (getInventory()->hasItem(kItemFirebird)) + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorNormal, kCursorNormal); + else + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocationNone, kCursorHandKnock, kCursorHand); + break; + + case kActionCallback: + switch (getCallback()) { + default: + break; + + case 1: + getAction()->playAnimation(kEventKahinaWrongDoor); + + if (getInventory()->hasItem(kItemBriefcase)) + getInventory()->removeItem(kItemBriefcase); + + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarKronos, 81); + getObjects()->update(kObjectCompartmentKronos, kEntityPlayer, kObjectLocation3, kCursorNormal, kCursorNormal); + getSound()->playSound(kEntityPlayer, "LIB015"); + break; + + case 2: + getData()->entityPosition = kPosition_6000; + getAction()->playAnimation(kEventConcertLeaveWithBriefcase); + + RESET_ENTITY_STATE(kEntityKahina, Kahina, setup_function21); + + getScenes()->loadSceneFromPosition(kCarKronos, 87); + break; + + case 3: + getAction()->playAnimation(kEventConcertEnd); + getSound()->playSound(kEntityPlayer, "BUMP"); + getScenes()->loadSceneFromPosition(kCarGreenSleeping, 26); + + setup_function21(); + break; + } + break; + } } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 348a7f6937..3b47b6a405 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -450,6 +450,15 @@ void SoundManager::processEntries() { processEntry(kSoundType2); } +uint32 SoundManager::getEntryTime(EntityIndex index) { + SoundEntry *entry = getEntry(index); + + if (!entry) + return 0; + + return entry->time; +} + ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index 85dfcc2e66..517aa1b31c 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -161,6 +161,7 @@ public: void processEntries(); void removeFromQueue(Common::String filename); void removeFromQueue(EntityIndex entity); + uint32 getEntryTime(EntityIndex index); // Misc void unknownFunction4(); @@ -242,7 +243,7 @@ private: //int fileData; //int field_18; //int field_1C; - //int field_20; + uint32 time; //int field_24; //int field_28; Common::SeekableReadStream *stream; // int @@ -262,8 +263,13 @@ private: bool isStreamed; // TEMPORARY SoundEntry() { + status.status = 0; type = kSoundTypeNone; + + time = 0; + stream = NULL; + field_3C = 0; field_40 = 0; entity = kEntityPlayer; diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index daf0a0146f..235e65db7c 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -205,6 +205,7 @@ enum TimeValue { kTime2182500 = 2182500, kTime2196000 = 2196000, kTime2200500 = 2200500, + kTime2214000 = 2214000, kTime2218500 = 2218500, kTime2223000 = 2223000, kTime2241000 = 2241000, @@ -1380,7 +1381,9 @@ enum ActionIndex { ///////////////////////////// // Kahina ///////////////////////////// + kAction92186062 = 92186062, kAction137503360 = 137503360, + kAction237555748 = 237555748, ///////////////////////////// // Kronos -- cgit v1.2.3