aboutsummaryrefslogtreecommitdiff
path: root/engines/lastexpress/game
diff options
context:
space:
mode:
authorStrangerke2011-06-29 16:15:41 +0200
committerStrangerke2011-06-29 16:15:41 +0200
commitb0c9c9122fc678074aba30068e5b36d347208e65 (patch)
tree79a99db08ec985f2e5f1e216823b1104d5b753fb /engines/lastexpress/game
parentf2f3124246a77036f843dee2d83ad28084234ebc (diff)
parentc32a3ea0d30336771bab460ecccb58c4614e6294 (diff)
downloadscummvm-rg350-b0c9c9122fc678074aba30068e5b36d347208e65.tar.gz
scummvm-rg350-b0c9c9122fc678074aba30068e5b36d347208e65.tar.bz2
scummvm-rg350-b0c9c9122fc678074aba30068e5b36d347208e65.zip
Merge branch 'master' of github.com:scummvm/scummvm into soltys_wip2
Diffstat (limited to 'engines/lastexpress/game')
-rw-r--r--engines/lastexpress/game/action.cpp72
-rw-r--r--engines/lastexpress/game/beetle.cpp14
-rw-r--r--engines/lastexpress/game/entities.cpp28
-rw-r--r--engines/lastexpress/game/fight.cpp1583
-rw-r--r--engines/lastexpress/game/fight.h266
-rw-r--r--engines/lastexpress/game/inventory.cpp19
-rw-r--r--engines/lastexpress/game/logic.cpp29
-rw-r--r--engines/lastexpress/game/menu.cpp1541
-rw-r--r--engines/lastexpress/game/menu.h207
-rw-r--r--engines/lastexpress/game/object.cpp2
-rw-r--r--engines/lastexpress/game/savegame.cpp69
-rw-r--r--engines/lastexpress/game/savepoint.cpp6
-rw-r--r--engines/lastexpress/game/scenes.cpp24
-rw-r--r--engines/lastexpress/game/sound.cpp1951
-rw-r--r--engines/lastexpress/game/sound.h389
-rw-r--r--engines/lastexpress/game/state.cpp2
-rw-r--r--engines/lastexpress/game/state.h2
17 files changed, 142 insertions, 6062 deletions
diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp
index 7540d18ed8..2ef4c20d70 100644
--- a/engines/lastexpress/game/action.cpp
+++ b/engines/lastexpress/game/action.cpp
@@ -39,9 +39,11 @@
#include "lastexpress/game/savegame.h"
#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/sound/queue.h"
+#include "lastexpress/sound/sound.h"
+
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
@@ -405,7 +407,7 @@ SceneIndex Action::processHotspot(const SceneHotspot &hotspot) {
//////////////////////////////////////////////////////////////////////////
// Action 0
IMPLEMENT_ACTION(dummy)
- warning("Action::action_dummy: Dummy action function called (hotspot action: %d)!", hotspot.action);
+ warning("[Action::action_dummy] Dummy action function called (hotspot action: %d)", hotspot.action);
return kSceneInvalid;
}
@@ -453,7 +455,7 @@ IMPLEMENT_ACTION(savePoint)
IMPLEMENT_ACTION(playSound)
// Check that the file is not already buffered
- if (hotspot.param2 || !getSound()->isBuffered(Common::String::format("LIB%03d", hotspot.param1), true))
+ if (hotspot.param2 || !getSoundQueue()->isBuffered(Common::String::format("LIB%03d", hotspot.param1), true))
getSound()->playSoundEvent(kEntityPlayer, hotspot.param1, hotspot.param2);
return kSceneInvalid;
@@ -465,8 +467,8 @@ IMPLEMENT_ACTION(playMusic)
// Check that the file is not already buffered
Common::String filename = Common::String::format("MUS%03d", hotspot.param1);
- if (!getSound()->isBuffered(filename) && (hotspot.param1 != 50 || getProgress().chapter == kChapter5))
- getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault, hotspot.param2);
+ if (!getSoundQueue()->isBuffered(filename) && (hotspot.param1 != 50 || getProgress().chapter == kChapter5))
+ getSound()->playSound(kEntityPlayer, filename, kFlagDefault, hotspot.param2);
return kSceneInvalid;
}
@@ -481,7 +483,7 @@ IMPLEMENT_ACTION(knock)
if (getObjects()->get(object).entity) {
getSavePoints()->push(kEntityPlayer, getObjects()->get(object).entity, kActionKnock, object);
} else {
- if (!getSound()->isBuffered("LIB012", true))
+ if (!getSoundQueue()->isBuffered("LIB012", true))
getSound()->playSoundEvent(kEntityPlayer, 12);
}
@@ -516,7 +518,7 @@ IMPLEMENT_ACTION(compartment)
&& (compartment != kObjectCompartment1
|| !getInventory()->hasItem(kItemKey)
|| (getInventory()->getSelectedItem() != kItemFirebird && getInventory()->getSelectedItem() != kItemBriefcase)))) {
- if (!getSound()->isBuffered("LIB13"))
+ if (!getSoundQueue()->isBuffered("LIB13"))
getSound()->playSoundEvent(kEntityPlayer, 13);
// Stop processing further
@@ -621,7 +623,7 @@ IMPLEMENT_ACTION(updateObjetLocation2)
getObjects()->updateLocation2(object, location);
- if (object != kObject112 || getSound()->isBuffered("LIB096")) {
+ if (object != kObject112 || getSoundQueue()->isBuffered("LIB096")) {
if (object == 1)
getSound()->playSoundEvent(kEntityPlayer, 73);
} else {
@@ -805,8 +807,8 @@ IMPLEMENT_ACTION(enterCompartment)
getSound()->playSoundEvent(kEntityPlayer, 14);
getSound()->playSoundEvent(kEntityPlayer, 15, 22);
- if (getProgress().field_78 && !getSound()->isBuffered("MUS003")) {
- getSound()->playSound(kEntityPlayer, "MUS003", SoundManager::kFlagDefault);
+ if (getProgress().field_78 && !getSoundQueue()->isBuffered("MUS003")) {
+ getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault);
getProgress().field_78 = 0;
}
@@ -1083,8 +1085,8 @@ IMPLEMENT_ACTION(25)
break;
case 2:
- if (!getSound()->isBuffered("MUS021"))
- getSound()->playSound(kEntityPlayer, "MUS021", SoundManager::kFlagDefault);
+ if (!getSoundQueue()->isBuffered("MUS021"))
+ getSound()->playSound(kEntityPlayer, "MUS021", kFlagDefault);
break;
case 3:
@@ -1134,7 +1136,7 @@ IMPLEMENT_ACTION(26)
//////////////////////////////////////////////////////////////////////////
// Action 27
IMPLEMENT_ACTION(27)
- if (!getSound()->isBuffered("LIB031", true))
+ if (!getSoundQueue()->isBuffered("LIB031", true))
getSound()->playSoundEvent(kEntityPlayer, 31);
switch (getEntityData(kEntityPlayer)->car) {
@@ -1182,8 +1184,8 @@ IMPLEMENT_ACTION(29)
getSound()->playSoundEvent(kEntityPlayer, hotspot.param1, hotspot.param2);
Common::String filename = Common::String::format("MUS%03d", hotspot.param3);
- if (!getSound()->isBuffered(filename))
- getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault);
+ if (!getSoundQueue()->isBuffered(filename))
+ getSound()->playSound(kEntityPlayer, filename, kFlagDefault);
return kSceneInvalid;
}
@@ -1345,7 +1347,7 @@ IMPLEMENT_ACTION(openBed)
//////////////////////////////////////////////////////////////////////////
// Action 37
IMPLEMENT_ACTION(dialog)
- getSound()->playDialog(kEntityTables4, (EntityIndex)hotspot.param1, SoundManager::kFlagDefault, 0);
+ getSound()->playDialog(kEntityTables4, (EntityIndex)hotspot.param1, kFlagDefault, 0);
return kSceneInvalid;
}
@@ -1354,8 +1356,8 @@ IMPLEMENT_ACTION(dialog)
// Action 38
IMPLEMENT_ACTION(eggBox)
getSound()->playSoundEvent(kEntityPlayer, 43);
- if (getProgress().field_7C && !getSound()->isBuffered("MUS003")) {
- getSound()->playSound(kEntityPlayer, "MUS003", SoundManager::kFlagDefault);
+ if (getProgress().field_7C && !getSoundQueue()->isBuffered("MUS003")) {
+ getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault);
getProgress().field_7C = 0;
}
@@ -1366,8 +1368,8 @@ IMPLEMENT_ACTION(eggBox)
// Action 39
IMPLEMENT_ACTION(39)
getSound()->playSoundEvent(kEntityPlayer, 24);
- if (getProgress().field_80 && !getSound()->isBuffered("MUS003")) {
- getSound()->playSound(kEntityPlayer, "MUS003", SoundManager::kFlagDefault);
+ if (getProgress().field_80 && !getSoundQueue()->isBuffered("MUS003")) {
+ getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault);
getProgress().field_80 = 0;
}
@@ -1408,8 +1410,8 @@ IMPLEMENT_ACTION(playMusicChapter)
if (id) {
Common::String filename = Common::String::format("MUS%03d", id);
- if (!getSound()->isBuffered(filename))
- getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault);
+ if (!getSoundQueue()->isBuffered(filename))
+ getSound()->playSound(kEntityPlayer, filename, kFlagDefault);
}
return kSceneInvalid;
@@ -1440,8 +1442,8 @@ IMPLEMENT_ACTION(playMusicChapterSetupTrain)
Common::String filename = Common::String::format("MUS%03d", hotspot.param1);
- if (!getSound()->isBuffered(filename) && hotspot.param3 & id) {
- getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault);
+ if (!getSoundQueue()->isBuffered(filename) && hotspot.param3 & id) {
+ getSound()->playSound(kEntityPlayer, filename, kFlagDefault);
getSavePoints()->call(kEntityPlayer, kEntityTrain, kAction203863200, filename.c_str());
getSavePoints()->push(kEntityPlayer, kEntityTrain, kAction222746496, hotspot.param2);
@@ -1612,7 +1614,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d
if (doPlaySound)
playCompartmentSoundEvents(object);
- if (!getSound()->isBuffered(kEntityMertens))
+ if (!getSoundQueue()->isBuffered(kEntityMertens))
getSound()->playWarningCompartment(kEntityMertens, object);
getSavePoints()->push(kEntityPlayer, kEntityMertens, kAction305159806);
@@ -1628,7 +1630,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d
if (doPlaySound)
playCompartmentSoundEvents(object);
- if (!getSound()->isBuffered(kEntityMertens))
+ if (!getSoundQueue()->isBuffered(kEntityMertens))
getSound()->playSound(kEntityMertens, (rnd(2)) ? "JAC1000" : "JAC1000A");
if (doLoadScene)
@@ -1640,7 +1642,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d
if (doPlaySound)
playCompartmentSoundEvents(object);
- if (!getSound()->isBuffered(kEntityMertens))
+ if (!getSoundQueue()->isBuffered(kEntityMertens))
getSound()->playSound(kEntityMertens, (rnd(2)) ? "JAC1000" : "JAC1000A");
if (doLoadScene)
@@ -1667,7 +1669,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d
if (doPlaySound)
playCompartmentSoundEvents(object);
- if (!getSound()->isBuffered(kEntityCoudert))
+ if (!getSoundQueue()->isBuffered(kEntityCoudert))
getSound()->playWarningCompartment(kEntityCoudert, object);
getSavePoints()->push(kEntityPlayer, kEntityCoudert, kAction305159806);
@@ -1684,7 +1686,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d
if (doPlaySound)
playCompartmentSoundEvents(object);
- if (!getSound()->isBuffered(kEntityCoudert))
+ if (!getSoundQueue()->isBuffered(kEntityCoudert))
getSound()->playSound(kEntityCoudert, (rnd(2)) ? "JAC1000" : "JAC1000A");
if (doLoadScene)
@@ -1699,7 +1701,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d
if (doPlaySound)
playCompartmentSoundEvents(object);
- if (!getSound()->isBuffered(kEntityCoudert))
+ if (!getSoundQueue()->isBuffered(kEntityCoudert))
getSound()->playSound(kEntityCoudert, (rnd(2)) ? "JAC1000" : "JAC1000A");
if (doLoadScene)
@@ -1908,7 +1910,7 @@ LABEL_KEY:
// Play an animation and add delta time to global game time
void Action::playAnimation(EventIndex index, bool debugMode) const {
if (index >= _animationListSize)
- error("Action::playAnimation: invalid event index (value=%i, max=%i)", index, _animationListSize);
+ error("[Action::playAnimation] Invalid event index (value=%i, max=%i)", index, _animationListSize);
// In debug mode, just show the animation
if (debugMode) {
@@ -1930,8 +1932,8 @@ void Action::playAnimation(EventIndex index, bool debugMode) const {
if (!getFlags()->mouseRightClick) {
if (getGlobalTimer()) {
- if (getSound()->isBuffered("TIMER")) {
- getSound()->processEntry("TIMER");
+ if (getSoundQueue()->isBuffered("TIMER")) {
+ getSoundQueue()->processEntry("TIMER");
setGlobalTimer(105);
}
}
@@ -1948,8 +1950,8 @@ void Action::playAnimation(EventIndex index, bool debugMode) const {
if (animation.load(getArchive(Common::String(_animationList[index].filename) + ".nis") , processSound ? Animation::kFlagDefault : Animation::kFlagProcess))
animation.play();
- if (getSound()->isBuffered("TIMER"))
- getSound()->removeFromQueue("TIMER");
+ if (getSoundQueue()->isBuffered("TIMER"))
+ getSoundQueue()->removeFromQueue("TIMER");
}
// Show cursor
diff --git a/engines/lastexpress/game/beetle.cpp b/engines/lastexpress/game/beetle.cpp
index cb6f0a3306..ab707ddae9 100644
--- a/engines/lastexpress/game/beetle.cpp
+++ b/engines/lastexpress/game/beetle.cpp
@@ -131,7 +131,7 @@ bool Beetle::isLoaded() const {
bool Beetle::catchBeetle() {
if (!_data)
- error("Beetle::catchBeetle: sequences have not been loaded!");
+ error("[Beetle::catchBeetle] Sequences have not been loaded");
if (getInventory()->getSelectedItem() == kItemMatchBox
&& getInventory()->hasItem(kItemMatch)
@@ -148,14 +148,14 @@ bool Beetle::catchBeetle() {
bool Beetle::isCatchable() const {
if (!_data)
- error("Beetle::isCatchable: sequences have not been loaded!");
+ error("[Beetle::isCatchable] Sequences have not been loaded");
return (_data->indexes[_data->offset] >= 30);
}
void Beetle::update() {
if (!_data)
- error("Beetle::update: sequences have not been loaded!");
+ error("[Beetle::update] Sequences have not been loaded");
if (!_data->isLoaded)
return;
@@ -194,7 +194,7 @@ void Beetle::update() {
void Beetle::drawUpdate() {
if (!_data)
- error("Beetle::drawUpdate: sequences have not been loaded!");
+ error("[Beetle::drawUpdate] Sequences have not been loaded");
if (_data->frame != NULL) {
getScenes()->setCoordinates(_data->frame);
@@ -366,7 +366,7 @@ void Beetle::drawUpdate() {
void Beetle::move() {
if (!_data)
- error("Beetle::move: sequences have not been loaded!");
+ error("[Beetle::move] Sequences have not been loaded");
if (_data->indexes[_data->offset] >= 24 && _data->indexes[_data->offset] <= 29)
return;
@@ -444,7 +444,7 @@ update_data:
// Update the beetle sequence to show the correct frames in the correct place
void Beetle::updateFrame(SequenceFrame *frame) const {
if (!_data)
- error("Beetle::updateSequence: sequences have not been loaded!");
+ error("[Beetle::updateFrame] Sequences have not been loaded");
if (!frame)
return;
@@ -459,7 +459,7 @@ void Beetle::updateFrame(SequenceFrame *frame) const {
void Beetle::updateData(uint32 index) {
if (!_data)
- error("Beetle::updateData: sequences have not been loaded!");
+ error("[Beetle::updateData] Sequences have not been loaded");
if (!_data->isLoaded)
return;
diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp
index 513ad114b0..f6bb2030f0 100644
--- a/engines/lastexpress/game/entities.cpp
+++ b/engines/lastexpress/game/entities.cpp
@@ -68,9 +68,11 @@
#include "lastexpress/game/logic.h"
#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/sound/queue.h"
+#include "lastexpress/sound/sound.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
@@ -200,7 +202,7 @@ Entity *Entities::get(EntityIndex entity) {
assert((uint)entity < _entities.size());
if (entity == kEntityPlayer)
- error("Cannot get entity for index == 0!");
+ error("[Entities::get] Cannot get entity for kEntityPlayer");
return _entities[entity];
}
@@ -218,24 +220,24 @@ int Entities::getPosition(CarIndex car, Position position) const {
int index = 100 * car + position;
if (car > 10)
- error("Entities::getPosition: trying to access an invalid car (was: %d, valid:0-9)", car);
+ error("[Entities::getPosition] Trying to access an invalid car (was: %d, valid:0-9)", car);
if (position > 100)
- error("Entities::getPosition: trying to access an invalid position (was: %d, valid:0-100)", position);
+ error("[Entities::getPosition] Trying to access an invalid position (was: %d, valid:0-100)", position);
return _positions[index];
}
int Entities::getCompartments(int index) const {
if (index >= _compartmentsCount)
- error("Entities::getCompartments: trying to access an invalid compartment (was: %d, valid:0-15)", index);
+ error("[Entities::getCompartments] Trying to access an invalid compartment (was: %d, valid:0-15)", index);
return _compartments[index];
}
int Entities::getCompartments1(int index) const {
if (index >= _compartmentsCount)
- error("Entities::getCompartments: trying to access an invalid compartment (was: %d, valid:0-15)", index);
+ error("[Entities::getCompartments] Trying to access an invalid compartment (was: %d, valid:0-15)", index);
return _compartments1[index];
}
@@ -299,7 +301,7 @@ void Entities::setupChapter(ChapterIndex chapter) {
memset(&_compartments1, 0, sizeof(_compartments1));
memset(&_positions, 0, sizeof(_positions));
- getSound()->resetQueue(SoundManager::kSoundType13);
+ getSoundQueue()->resetQueue(kSoundType13);
}
// we skip the header when doing entity setup
@@ -369,8 +371,8 @@ void Entities::resetState(EntityIndex entityIndex) {
getData(entityIndex)->currentCall = 0;
getData(entityIndex)->inventoryItem = kItemNone;
- if (getSound()->isBuffered(entityIndex))
- getSound()->removeFromQueue(entityIndex);
+ if (getSoundQueue()->isBuffered(entityIndex))
+ getSoundQueue()->removeFromQueue(entityIndex);
clearSequences(entityIndex);
@@ -1780,7 +1782,7 @@ void Entities::enterCompartment(EntityIndex entity, ObjectIndex compartment, boo
// Update compartments
int index = (compartment < 32 ? compartment - 1 : compartment - 24);
if (index >= 16)
- error("Entities::exitCompartment: invalid compartment index!");
+ error("[Entities::enterCompartment] Invalid compartment index");
if (useCompartment1)
_compartments1[index] |= STORE_VALUE(entity);
@@ -1866,7 +1868,7 @@ void Entities::exitCompartment(EntityIndex entity, ObjectIndex compartment, bool
// Update compartments
int index = (compartment < 32 ? compartment - 1 : compartment - 24);
if (index >= 16)
- error("Entities::exitCompartment: invalid compartment index!");
+ error("[Entities::exitCompartment] Invalid compartment index");
if (useCompartment1)
_compartments1[index] &= ~STORE_VALUE(entity);
@@ -2355,7 +2357,7 @@ bool Entities::changeCar(EntityData::EntityCallData *data, EntityIndex entity, C
if (data->car == newCar) {
if (isInGreenCarEntrance(kEntityPlayer)) {
getSound()->playSoundEvent(kEntityPlayer, 14);
- getSound()->excuseMe(entity, kEntityPlayer, SoundManager::kFlagDefault);
+ getSound()->excuseMe(entity, kEntityPlayer, kFlagDefault);
getScenes()->loadSceneFromPosition(kCarGreenSleeping, 1);
getSound()->playSound(kEntityPlayer, "CAT1127A");
getSound()->playSoundEvent(kEntityPlayer, 15);
@@ -2374,7 +2376,7 @@ bool Entities::changeCar(EntityData::EntityCallData *data, EntityIndex entity, C
if (data->car == newCar) {
if (isInKronosCarEntrance(kEntityPlayer)) {
getSound()->playSoundEvent(kEntityPlayer, 14);
- getSound()->excuseMe(entity, kEntityPlayer, SoundManager::kFlagDefault);
+ getSound()->excuseMe(entity, kEntityPlayer, kFlagDefault);
getScenes()->loadSceneFromPosition(kCarGreenSleeping, 62);
getSound()->playSound(kEntityPlayer, "CAT1127A");
getSound()->playSoundEvent(kEntityPlayer, 15);
diff --git a/engines/lastexpress/game/fight.cpp b/engines/lastexpress/game/fight.cpp
deleted file mode 100644
index ecc43bed2b..0000000000
--- a/engines/lastexpress/game/fight.cpp
+++ /dev/null
@@ -1,1583 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "lastexpress/game/fight.h"
-
-#include "lastexpress/data/cursor.h"
-#include "lastexpress/data/scene.h"
-#include "lastexpress/data/sequence.h"
-
-#include "lastexpress/game/entities.h"
-#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/logic.h"
-#include "lastexpress/game/object.h"
-#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
-#include "lastexpress/game/state.h"
-
-#include "lastexpress/graphics.h"
-#include "lastexpress/helpers.h"
-#include "lastexpress/lastexpress.h"
-#include "lastexpress/resource.h"
-
-#include "common/func.h"
-
-namespace LastExpress {
-
-#define CALL_FUNCTION0(fighter, name) \
- (*fighter->name)(fighter)
-
-#define CALL_FUNCTION1(fighter, name, a) \
- (*fighter->name)(fighter, a)
-
-#define REGISTER_PLAYER_FUNCTIONS(name) \
- if (!_data) \
- error("Fight::load##namePlayer - invalid data!"); \
- _data->player->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleAction##name); \
- _data->player->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::update##name); \
- _data->player->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract##name);
-
-#define REGISTER_OPPONENT_FUNCTIONS(name) \
- if (!_data) \
- error("Fight::load##nameOpponent - invalid data!"); \
- _data->opponent->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleOpponentAction##name); \
- _data->opponent->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::updateOpponent##name); \
- _data->opponent->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract);
-
-#define CHECK_SEQUENCE2(fighter, value) \
- (fighter->frame->getInfo()->field_33 & value)
-
-Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {}
-
-Fight::~Fight() {
- clearData();
- _data = NULL;
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Events
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::eventMouse(const Common::Event &ev) {
- if (!_data || _data->index)
- return;
-
- // TODO move all the egg handling to inventory functions
-
- getFlags()->mouseLeftClick = false;
- getFlags()->shouldRedraw = false;
- getFlags()->mouseRightClick = false;
-
- if (ev.mouse.x < 608 || ev.mouse.y < 448 || ev.mouse.x >= 640 || ev.mouse.x >= 480) {
-
- // Handle right button click
- if (ev.type == Common::EVENT_RBUTTONUP) {
- getSound()->removeFromQueue(kEntityTables0);
- setStopped();
-
- getGlobalTimer() ? _state = 0 : ++_state;
-
- getFlags()->mouseRightClick = true;
- }
-
- if (_handleTimer) {
- // Timer expired => show with full brightness
- if (!getGlobalTimer())
- getInventory()->drawBlinkingEgg();
-
- _handleTimer = false;
- }
-
- // Check hotspots
- Scene *scene = getScenes()->get(getState()->scene);
- SceneHotspot *hotspot = NULL;
-
- if (!scene->checkHotSpot(ev.mouse, &hotspot)) {
- _engine->getCursor()->setStyle(kCursorNormal);
- } else {
- _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
-
- // Call player function
- if (CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) {
- if (ev.type == Common::EVENT_LBUTTONUP)
- CALL_FUNCTION1(_data->player, handleAction, (FightAction)hotspot->action);
- } else {
- _engine->getCursor()->setStyle(kCursorNormal);
- }
- }
- } else {
- // Handle clicks on menu icon
-
- if (!_handleTimer) {
- // Timer expired => show with full brightness
- if (!getGlobalTimer())
- getInventory()->drawBlinkingEgg();
-
- _handleTimer = true;
- }
-
- // Stop fight if clicked
- if (ev.type == Common::EVENT_LBUTTONUP) {
- _handleTimer = false;
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndExit);
- }
-
- // Reset timer on right click
- if (ev.type == Common::EVENT_RBUTTONUP) {
- if (getGlobalTimer()) {
- if (getSound()->isBuffered("TIMER"))
- getSound()->removeFromQueue("TIMER");
-
- setGlobalTimer(900);
- }
- }
- }
-
- getFlags()->shouldRedraw = true;
-}
-
-void Fight::eventTick(const Common::Event &ev) {
- handleTick(ev, true);
-}
-
-void Fight::handleTick(const Common::Event &ev, bool isProcessing) {
- // TODO move all the egg handling to inventory functions
-
- // Blink egg
- if (getGlobalTimer()) {
- warning("Fight::handleMouseMove - egg blinking not implemented!");
- }
-
- if (!_data || _data->index)
- return;
-
- SceneHotspot *hotspot = NULL;
- if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) {
- _engine->getCursor()->setStyle(kCursorNormal);
- } else {
- _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor);
- }
-
- CALL_FUNCTION0(_data->player, update);
- CALL_FUNCTION0(_data->opponent, update);
-
- // Draw sequences
- if (!_data->isRunning)
- return;
-
- if (isProcessing)
- getScenes()->drawFrames(true);
-
- if (_data->index) {
- // Set next sequence name index
- _data->index--;
- _data->sequences[_data->index] = loadSequence(_data->names[_data->index]);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Setup
-//////////////////////////////////////////////////////////////////////////
-
-Fight::FightEndType Fight::setup(FightType type) {
- if (_data)
- error("Fight::setup - calling fight setup again while a fight is already in progress!");
-
- //////////////////////////////////////////////////////////////////////////
- // Prepare UI & state
- if (_state >= 5 && (type == kFightSalko || type == kFightVesna)) {
- _state = 0;
- return kFightEndWin;
- }
-
- getInventory()->showHourGlass();
- // TODO events function
- getFlags()->flag_0 = false;
- getFlags()->mouseRightClick = false;
- getEntities()->reset();
-
- // Compute scene to use
- SceneIndex sceneIndex;
- switch(type) {
- default:
- sceneIndex = kSceneFightDefault;
- break;
-
- case kFightMilos:
- sceneIndex = (getObjects()->get(kObjectCompartment1).location2 < kObjectLocation3) ? kSceneFightMilos : kSceneFightMilosBedOpened;
- break;
-
- case kFightAnna:
- sceneIndex = kSceneFightAnna;
- break;
-
- case kFightIvo:
- sceneIndex = kSceneFightIvo;
- break;
-
- case kFightSalko:
- sceneIndex = kSceneFightSalko;
- break;
-
- case kFightVesna:
- sceneIndex = kSceneFightVesna;
- break;
- }
-
- if (getFlags()->shouldRedraw) {
- getFlags()->shouldRedraw = false;
- askForRedraw();
- //redrawScreen();
- }
-
- // Load the scene object
- Scene *scene = getScenes()->get(sceneIndex);
-
- // Update game entities and state
- getEntityData(kEntityPlayer)->entityPosition = scene->entityPosition;
- getEntityData(kEntityPlayer)->location = scene->location;
-
- getState()->scene = sceneIndex;
-
- getFlags()->flag_3 = true;
-
- // Draw the scene
- _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC);
- // FIXME move to start of fight?
- askForRedraw();
- redrawScreen();
-
- //////////////////////////////////////////////////////////////////////////
- // Setup the fight
- _data = new FightData;
- loadData(type);
-
- // Show opponents & egg button
- Common::Event emptyEvent;
- handleTick(emptyEvent, false);
- getInventory()->drawEgg();
-
- // Start fight
- _endType = kFightEndLost;
- while (_data->isRunning) {
- if (_engine->handleEvents())
- continue;
-
- getSound()->updateQueue();
- }
-
- // Cleanup after fight is over
- clearData();
-
- return _endType;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Status
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::setStopped() {
- if (_data)
- _data->isRunning = false;
-}
-
-void Fight::bailout(FightEndType type) {
- _state = 0;
- _endType = type;
- setStopped();
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Cleanup
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::clearData() {
- if (!_data)
- return;
-
- // Clear data
- clearSequences(_data->player);
- clearSequences(_data->opponent);
-
- SAFE_DELETE(_data->player);
- SAFE_DELETE(_data->opponent);
-
- SAFE_DELETE(_data);
-
- _engine->restoreEventHandlers();
-}
-
-void Fight::clearSequences(Fighter *combatant) const {
- if (!combatant)
- return;
-
- // The original game resets the function pointers to default values, just before deleting the struct
- getScenes()->removeAndRedraw(&combatant->frame, false);
-
- // Free sequences
- for (int i = 0; i < (int)combatant->sequences.size(); i++)
- SAFE_DELETE(combatant->sequences[i]);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Drawing
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::setSequenceAndDraw(Fighter *combatant, uint32 sequenceIndex, FightSequenceType type) const {
- if (combatant->sequences.size() < sequenceIndex)
- return;
-
- switch (type) {
- default:
- break;
-
- case kFightSequenceType0:
- if (combatant->sequenceIndex)
- return;
-
- combatant->sequence = combatant->sequences[sequenceIndex];
- combatant->sequenceIndex = sequenceIndex;
- draw(combatant);
- break;
-
- case kFightSequenceType1:
- combatant->sequence = combatant->sequences[sequenceIndex];
- combatant->sequenceIndex = sequenceIndex;
- combatant->sequenceIndex2 = 0;
- draw(combatant);
- break;
-
- case kFightSequenceType2:
- combatant->sequenceIndex2 = sequenceIndex;
- break;
- }
-}
-
-void Fight::draw(Fighter *combatant) const {
- getScenes()->removeAndRedraw(&combatant->frame, false);
-
- combatant->frameIndex = 0;
- combatant->field_24 = 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Loading
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadData(FightType type) {
- if (!_data)
- error("Fight::loadData - invalid data!");
-
- switch (type) {
- default:
- break;
-
- case kFightMilos:
- loadMilosPlayer();
- loadMilosOpponent();
- break;
-
- case kFightAnna:
- loadAnnaPlayer();
- loadAnnaOpponent();
- break;
-
- case kFightIvo:
- loadIvoPlayer();
- loadIvoOpponent();
- break;
-
- case kFightSalko:
- loadSalkoPlayer();
- loadSalkoOpponent();
- break;
-
- case kFightVesna:
- loadVesnaPlayer();
- loadVesnaOpponent();
- break;
- }
-
- if (!_data->player || !_data->opponent)
- error("Fight::loadData - error loading fight data (type=%d)", type);
-
- //////////////////////////////////////////////////////////////////////////
- // Start running the fight
- _data->isRunning = true;
-
- if (_state < 5) {
- setSequenceAndDraw(_data->player, 0, kFightSequenceType0);
- setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0);
- goto end_load;
- }
-
- switch(type) {
- default:
- break;
-
- case kFightMilos:
- _data->opponent->countdown = 1;
- setSequenceAndDraw(_data->player, 4, kFightSequenceType0);
- setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0);
- break;
-
- case kFightIvo:
- _data->opponent->countdown = 1;
- setSequenceAndDraw(_data->player, 3, kFightSequenceType0);
- setSequenceAndDraw(_data->opponent, 6, kFightSequenceType0);
- break;
-
- case kFightVesna:
- _data->opponent->countdown = 1;
- setSequenceAndDraw(_data->player, 0, kFightSequenceType0);
- setSequenceAndDraw(_data->player, 3, kFightSequenceType2);
- setSequenceAndDraw(_data->opponent, 5, kFightSequenceType0);
- break;
- }
-
-end_load:
- // Setup event handlers
- _engine->backupEventHandlers();
- SET_EVENT_HANDLERS(Fight, this);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Shared
-//////////////////////////////////////////////////////////////////////////
-void Fight::processFighter(Fighter *fighter) {
- if (!_data)
- error("Fight::processFighter - invalid data!");
-
- if (!fighter->sequence) {
- if (fighter->frame) {
- getScenes()->removeFromQueue(fighter->frame);
- getScenes()->setCoordinates(fighter->frame);
- }
- SAFE_DELETE(fighter->frame);
- return;
- }
-
- if (fighter->sequence->count() <= fighter->frameIndex) {
- switch(fighter->action) {
- default:
- break;
-
- case kFightAction101:
- setSequenceAndDraw(fighter, fighter->sequenceIndex2, kFightSequenceType1);
- fighter->sequenceIndex2 = 0;
- break;
-
- case kFightActionResetFrame:
- fighter->frameIndex = 0;
- break;
-
- case kFightAction103:
- setSequenceAndDraw(fighter, 0, kFightSequenceType1);
- CALL_FUNCTION1(fighter, handleAction, kFightAction101);
- setSequenceAndDraw(fighter->opponent, 0, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction101);
- CALL_FUNCTION0(fighter->opponent, update);
- break;
-
- case kFightActionWin:
- bailout(kFightEndWin);
- break;
-
- case kFightActionLost:
- bailout(kFightEndLost);
- break;
- }
- }
-
- if (_data->isRunning) {
-
- // Get the current sequence frame
- SequenceFrame *frame = new SequenceFrame(fighter->sequence, (uint16)fighter->frameIndex);
- frame->getInfo()->location = 1;
-
- if (fighter->frame == frame) {
- delete frame;
- return;
- }
-
- getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31);
-
- // Add current frame to queue and advance
- getScenes()->addToQueue(frame);
- fighter->frameIndex++;
-
- if (fighter->frame) {
- getScenes()->removeFromQueue(fighter->frame);
-
- if (!frame->getInfo()->field_2E)
- getScenes()->setCoordinates(fighter->frame);
- }
-
- // Replace by new frame
- delete fighter->frame;
- fighter->frame = frame;
- }
-}
-
-void Fight::handleAction(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- return;
-
- case kFightAction101:
- break;
-
- case kFightActionResetFrame:
- fighter->countdown--;
- break;
-
- case kFightAction103:
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame);
- break;
-
- case kFightActionWin:
- _endType = kFightEndWin;
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame);
- break;
-
- case kFightActionLost:
- _endType = kFightEndLost;
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame);
- break;
- }
-
- // Update action
- fighter->action = action;
-}
-
-bool Fight::canInteract(Fighter const *fighter, FightAction /*= (FightAction)0*/ ) {
- return (fighter->action == kFightAction101 && !fighter->sequenceIndex);
-}
-
-void Fight::update(Fighter *fighter) {
-
- processFighter(fighter);
-
- if (fighter->frame)
- fighter->frame->getInfo()->location = (fighter->action == kFightActionResetFrame ? 2 : 0);
-}
-
-void Fight::updateOpponent(Fighter *fighter) {
-
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- processFighter(opponent);
-
- if (opponent->field_38 && !opponent->sequenceIndex)
- opponent->field_38--;
-
- if (fighter->frame)
- fighter->frame->getInfo()->location = 1;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Milos
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadMilosPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Milos)
-
- _data->player->sequences.push_back(loadSequence("2001cr.seq"));
- _data->player->sequences.push_back(loadSequence("2001cdl.seq"));
- _data->player->sequences.push_back(loadSequence("2001cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2001cdm.seq"));
- _data->player->sequences.push_back(loadSequence("2001csgr.seq"));
- _data->player->sequences.push_back(loadSequence("2001csgl.seq"));
- _data->player->sequences.push_back(loadSequence("2001dbk.seq"));
-}
-
-void Fight::loadMilosOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Milos)
-
- _data->opponent->sequences.push_back(loadSequence("2001or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001oal.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001okl.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001okm.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001dbk.seq"));
- _data->opponent->sequences.push_back(loadSequence("2001wbk.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault);
-
- _data->opponent->field_38 = 35;
-}
-
-void Fight::handleActionMilos(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 6, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 3, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction2:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 6, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction128:
- if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4) || fighter->opponent->sequenceIndex != 1) {
- switch (fighter->opponent->sequenceIndex) {
- default:
- setSequenceAndDraw(fighter, rnd(3) + 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(fighter, 3, kFightSequenceType0);
- break;
- }
- } else {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- CALL_FUNCTION0(fighter, update);
- }
- break;
- }
-}
-
-void Fight::updateMilos(Fighter *fighter) {
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- // Draw sequences
- if (fighter->opponent->countdown <= 0) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1);
-
- getSound()->removeFromQueue(kEntityTables0);
- getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault);
-
- CALL_FUNCTION1(fighter, handleAction, kFightActionWin);
- }
-
- if (fighter->sequenceIndex == 4) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction4);
- _endType = kFightEndLost;
- }
- }
-
- update(fighter);
-}
-
-bool Fight::canInteractMilos(Fighter const *fighter, FightAction action) {
- if (!_data)
- error("Fight::canInteractMilos - invalid data!");
-
- if (action != kFightAction128
- || _data->player->sequenceIndex != 1
- || !fighter->frame
- || CHECK_SEQUENCE2(fighter, 4)
- || fighter->opponent->sequenceIndex != 1) {
- return canInteract(fighter);
- }
-
- _engine->getCursor()->setStyle(kCursorHand);
-
- return true;
-}
-
-void Fight::handleOpponentActionMilos(Fighter *fighter, FightAction action) {
- if (action == kFightAction4) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- } else {
- if (action != kFightAction131)
- handleAction(fighter, action);
- }
-}
-
-void Fight::updateOpponentMilos(Fighter *fighter) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 >= 2) {
- switch (rnd(5)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType1);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
- } else {
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- }
-
- // Update field_38
- if (opponent->opponent->field_34 < 5)
- opponent->field_38 = 6 * (5 - opponent->opponent->field_34);
- else
- opponent->field_38 = 0;
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
-
- if (opponent->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- CALL_FUNCTION1(opponent, handleAction, kFightActionLost);
- }
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Anna
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadAnnaPlayer() {
- if (!_data)
- error("Fight::loadAnnaPlayer - invalid data!");
-
- // Special case: we are using some shared functions directly
- _data->player->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleActionAnna);
- _data->player->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::update);
- _data->player->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract);
-
- _data->player->sequences.push_back(loadSequence("2002cr.seq"));
- _data->player->sequences.push_back(loadSequence("2002cdl.seq"));
- _data->player->sequences.push_back(loadSequence("2002cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2002cdm.seq"));
- _data->player->sequences.push_back(loadSequence("2002lbk.seq"));
-}
-
-void Fight::loadAnnaOpponent() {
- if (!_data)
- error("Fight::loadAnnaOpponent - invalid data!");
-
- // Special case: we are using some shared functions directly
- _data->opponent->handleAction = new Common::Functor2Mem<Fighter *, FightAction, void, Fight>(this, &Fight::handleAction);
- _data->opponent->update = new Common::Functor1Mem<Fighter *, void, Fight>(this, &Fight::updateOpponentAnna);
- _data->opponent->canInteract = new Common::Functor2Mem<Fighter const *, FightAction, bool, Fight>(this, &Fight::canInteract);
-
- _data->opponent->sequences.push_back(loadSequence("2002or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002oal.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002okr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002okml.seq"));
- _data->opponent->sequences.push_back(loadSequence("2002okm.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault);
-
- _data->opponent->field_38 = 30;
-}
-
-void Fight::handleActionAnna(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if ((fighter->sequenceIndex != 1 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction2:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction3:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 1) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 4, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction128:
- switch (fighter->opponent->sequenceIndex) {
- default:
- setSequenceAndDraw(fighter, 3, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(fighter, 3, kFightSequenceType0);
- break;
-
- case 3:
- setSequenceAndDraw(fighter, 2, kFightSequenceType0);
- break;
- }
- break;
- }
-
- if (fighter->field_34 > 4) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndWin);
- }
-}
-
-void Fight::updateOpponentAnna(Fighter *fighter) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 >= 2) {
- switch (rnd(6)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 3, kFightSequenceType0);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 3, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 5:
- setSequenceAndDraw(opponent, 3, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
- }
- }
-
- // Update field_38
- opponent->field_38 = (int32)rnd(15);
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 3)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
-
- if (opponent->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- CALL_FUNCTION1(opponent, handleAction, kFightActionLost);
- }
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Ivo
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadIvoPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Ivo)
-
- _data->player->sequences.push_back(loadSequence("2003cr.seq"));
- _data->player->sequences.push_back(loadSequence("2003car.seq"));
- _data->player->sequences.push_back(loadSequence("2003cal.seq"));
- _data->player->sequences.push_back(loadSequence("2003cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2003cdm.seq"));
- _data->player->sequences.push_back(loadSequence("2003chr.seq"));
- _data->player->sequences.push_back(loadSequence("2003chl.seq"));
- _data->player->sequences.push_back(loadSequence("2003ckr.seq"));
- _data->player->sequences.push_back(loadSequence("2003lbk.seq"));
- _data->player->sequences.push_back(loadSequence("2003fbk.seq"));
-
- _data->player->countdown = 5;
-}
-
-void Fight::loadIvoOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Ivo)
-
- _data->opponent->sequences.push_back(loadSequence("2003or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003oal.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003odm.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003okl.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003okj.seq"));
- _data->opponent->sequences.push_back(loadSequence("blank.seq"));
- _data->opponent->sequences.push_back(loadSequence("csdr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2003l.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault);
-
- _data->opponent->countdown = 5;
- _data->opponent->field_38 = 15;
-}
-
-void Fight::handleActionIvo(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 7, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction2:
- if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 7, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction128:
- switch (fighter->opponent->sequenceIndex) {
- default:
- case 1:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(fighter, 2, kFightSequenceType0);
- break;
- }
- break;
-
- case kFightAction129:
- setSequenceAndDraw(fighter, (fighter->opponent->countdown > 1) ? 4 : 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0);
- break;
-
- case kFightAction130:
- setSequenceAndDraw(fighter, 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0);
- break;
- }
-}
-
-void Fight::updateIvo(Fighter *fighter) {
-
- if ((fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) && !fighter->frameIndex)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction131);
-
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- // Draw sequences
- if (fighter->opponent->countdown <= 0) {
- setSequenceAndDraw(fighter, 9, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, 8, kFightSequenceType1);
- getSound()->removeFromQueue(kEntityTables0);
-
- CALL_FUNCTION1(fighter, handleAction, kFightActionWin);
- return;
- }
-
- if (fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4)
- CALL_FUNCTION1(fighter->opponent, handleAction, (FightAction)fighter->sequenceIndex);
- }
-
- update(fighter);
-}
-
-bool Fight::canInteractIvo(Fighter const *fighter, FightAction action) {
- if (action == kFightAction129 || action == kFightAction130)
- return (fighter->sequenceIndex >= 8);
-
- return canInteract(fighter);
-}
-
-void Fight::handleOpponentActionIvo(Fighter *fighter, FightAction action) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- switch (action) {
- default:
- handleAction(fighter, action);
- break;
-
- case kFightAction3:
- if ((opponent->sequenceIndex != 1 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) {
- setSequenceAndDraw(opponent, 6, kFightSequenceType1);
- setSequenceAndDraw(opponent->opponent, 6, kFightSequenceType1);
- CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103);
- }
- break;
-
- case kFightAction4:
- if ((opponent->sequenceIndex != 2 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) {
- setSequenceAndDraw(opponent, 6, kFightSequenceType1);
- setSequenceAndDraw(opponent->opponent, 5, kFightSequenceType1);
- CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103);
- }
- break;
-
- case kFightAction131:
- if (opponent->sequenceIndex)
- break;
-
- if (rnd(100) <= (unsigned int)(opponent->countdown > 2 ? 60 : 75)) {
- setSequenceAndDraw(opponent, 3 , kFightSequenceType1);
- if (opponent->opponent->sequenceIndex == 4)
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- }
- break;
- }
-}
-
-void Fight::updateOpponentIvo(Fighter *fighter) {
- // This is an opponent struct!
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 >= 2) {
- switch (rnd(5)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 0, kFightSequenceType2);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 0, kFightSequenceType1);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
- }
-
- // Update field_38
- opponent->field_38 = 3 * opponent->countdown + (int32)rnd(10);
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
-
- if (opponent->opponent->countdown <= 0) {
- setSequenceAndDraw(opponent, 7, kFightSequenceType1);
- setSequenceAndDraw(opponent->opponent, 8, kFightSequenceType1);
- getSound()->removeFromQueue(kEntityTables0);
-
- CALL_FUNCTION1(opponent->opponent, handleAction, kFightActionWin);
-
- return;
- }
-
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Salko
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadSalkoPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Salko)
-
- _data->player->sequences.push_back(loadSequence("2004cr.seq"));
- _data->player->sequences.push_back(loadSequence("2004cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2004chj.seq"));
- _data->player->sequences.push_back(loadSequence("2004bk.seq"));
-
- _data->player->countdown = 2;
-}
-
-void Fight::loadSalkoOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Salko)
-
- _data->opponent->sequences.push_back(loadSequence("2004or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004okr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2004ohm.seq"));
- _data->opponent->sequences.push_back(loadSequence("blank.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault);
-
- _data->opponent->countdown = 3;
- _data->opponent->field_38 = 30;
-}
-
-void Fight::handleActionSalko(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- case kFightAction2:
- if (fighter->sequenceIndex != 1 && CHECK_SEQUENCE2(fighter, 4)) {
- fighter->field_34 = 0;
-
- setSequenceAndDraw(fighter, 3, kFightSequenceType1);
- setSequenceAndDraw(fighter->opponent, (action == kFightAction1 ? 3 : 4), kFightSequenceType1);
-
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
-
- if (action == kFightAction2)
- fighter->countdown= 0;
-
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction5:
- if (fighter->sequenceIndex != 3) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction128:
- setSequenceAndDraw(fighter, 1, kFightSequenceType0);
- fighter->field_34 = 0;
- break;
-
- case kFightAction131:
- setSequenceAndDraw(fighter, 2, (fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0));
- break;
- }
-}
-
-void Fight::updateSalko(Fighter *fighter) {
- update(fighter);
-
- // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation)
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- if (fighter->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndWin);
-
- return;
- }
-
- if (fighter->sequenceIndex == 2)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction2);
- }
-}
-
-bool Fight::canInteractSalko(Fighter const *fighter, FightAction action) {
- if (action == kFightAction131) {
- if (fighter->sequenceIndex == 1) {
- if (fighter->opponent->countdown <= 0)
- _engine->getCursor()->setStyle(kCursorHand);
-
- return true;
- }
-
- return false;
- }
-
- return canInteract(fighter);
-}
-
-void Fight::handleOpponentActionSalko(Fighter *fighter, FightAction action) {
- if (action == kFightAction2) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- } else {
- handleAction(fighter, action);
- }
-}
-
-void Fight::updateOpponentSalko(Fighter *fighter) {
- // This is an opponent struct
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- switch (rnd(5)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
-
- // Update field_38
- opponent->field_38 = 4 * opponent->countdown;
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndLost);
-
- // Stop processing
- return;
- }
-
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
- }
-
- updateOpponent(opponent);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Vesna
-//////////////////////////////////////////////////////////////////////////
-
-void Fight::loadVesnaPlayer() {
- REGISTER_PLAYER_FUNCTIONS(Vesna)
-
- _data->player->sequences.push_back(loadSequence("2005cr.seq"));
- _data->player->sequences.push_back(loadSequence("2005cdr.seq"));
- _data->player->sequences.push_back(loadSequence("2005cbr.seq"));
- _data->player->sequences.push_back(loadSequence("2005bk.seq"));
- _data->player->sequences.push_back(loadSequence("2005cdm1.seq"));
- _data->player->sequences.push_back(loadSequence("2005chl.seq"));
-}
-
-void Fight::loadVesnaOpponent() {
- REGISTER_OPPONENT_FUNCTIONS(Vesna)
-
- _data->opponent->sequences.push_back(loadSequence("2005or.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005oam.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005oar.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005okml.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005okr.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005odm1.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005csbm.seq"));
- _data->opponent->sequences.push_back(loadSequence("2005oam4.seq"));
-
- getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault);
-
- _data->opponent->countdown = 4;
- _data->opponent->field_38 = 30;
-}
-
-void Fight::handleActionVesna(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- return;
-
- case kFightAction1:
- if (fighter->sequenceIndex != 1) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction2:
- if (fighter->sequenceIndex != 2) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- } else {
- fighter->field_34++;
- }
- break;
-
- case kFightAction5:
- if (fighter->sequenceIndex != 3) {
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- CALL_FUNCTION0(fighter, update);
- }
- break;
-
- case kFightAction128:
- if (fighter->sequenceIndex == 1 && fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) {
- setSequenceAndDraw(fighter, 5, kFightSequenceType1);
- } else {
- setSequenceAndDraw(fighter, (fighter->opponent->sequenceIndex == 5) ? 3 : 1, kFightSequenceType0);
- }
- break;
-
- case kFightAction132:
- setSequenceAndDraw(fighter, 2, kFightSequenceType0);
- break;
- }
-
- if (fighter->field_34 > 10) {
- setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType2);
- fighter->opponent->countdown = 1;
- fighter->field_34 = 0;
- }
-}
-
-void Fight::updateVesna(Fighter *fighter) {
- if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) {
-
- if (fighter->sequenceIndex == 3)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction3);
-
- if (fighter->opponent->countdown <= 0) {
- getSound()->removeFromQueue(kEntityTables0);
- bailout(kFightEndWin);
- return;
- }
-
- if (fighter->sequenceIndex == 5)
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction5);
- }
-
- update(fighter);
-}
-
-bool Fight::canInteractVesna(Fighter const *fighter, FightAction action) {
- if (action != kFightAction128)
- return canInteract(fighter);
-
- if (fighter->sequenceIndex != 1) {
-
- if (fighter->opponent->sequenceIndex == 5) {
- _engine->getCursor()->setStyle(kCursorDown);
- return true;
- }
-
- return canInteract(fighter);
- }
-
- if (fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) {
- _engine->getCursor()->setStyle(kCursorPunchLeft);
- return true;
- }
-
- return false;
-}
-
-void Fight::handleOpponentActionVesna(Fighter *fighter, FightAction action) {
- switch (action) {
- default:
- handleAction(fighter, action);
- break;
-
- case kFightAction3:
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- break;
-
- case kFightAction5:
- setSequenceAndDraw(fighter, 7, kFightSequenceType1);
- CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103);
- if (fighter->countdown <= 1)
- fighter->countdown = 1;
- break;
-
- case kFightAction131:
- break;
- }
-}
-
-void Fight::updateOpponentVesna(Fighter *fighter) {
- // This is an opponent struct
- Opponent *opponent = (Opponent *)fighter;
-
- if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) {
-
- if (opponent->opponent->field_34 == 1) {
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- } else {
- switch (rnd(6)) {
- default:
- break;
-
- case 0:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- break;
-
- case 3:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 4:
- setSequenceAndDraw(opponent, 1, kFightSequenceType0);
- setSequenceAndDraw(opponent, 2, kFightSequenceType2);
- break;
-
- case 5:
- setSequenceAndDraw(opponent, 2, kFightSequenceType0);
- setSequenceAndDraw(opponent, 1, kFightSequenceType2);
- break;
- }
- }
-
- // Update field_38
- opponent->field_38 = 4 * opponent->countdown;
- }
-
- if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) {
- if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 5)
- CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex);
-
- if (opponent->opponent->countdown <= 0) {
-
- switch (opponent->sequenceIndex) {
- default:
- break;
-
- case 1:
- setSequenceAndDraw(opponent, 3, kFightSequenceType1);
- break;
-
- case 2:
- setSequenceAndDraw(opponent, 4, kFightSequenceType1);
- break;
-
- case 5:
- setSequenceAndDraw(opponent, 6, kFightSequenceType1);
- break;
- }
-
- setSequenceAndDraw(opponent->opponent, 4, kFightSequenceType1);
-
- CALL_FUNCTION1(opponent, handleAction, kFightActionLost);
- CALL_FUNCTION0(opponent->opponent, update);
- CALL_FUNCTION0(opponent, update);
-
- getSound()->removeFromQueue(kEntityTables0);
-
- // Stop processing
- return;
- }
- }
-
- updateOpponent(opponent);
-}
-
-} // End of namespace LastExpress
diff --git a/engines/lastexpress/game/fight.h b/engines/lastexpress/game/fight.h
deleted file mode 100644
index a33cc93a29..0000000000
--- a/engines/lastexpress/game/fight.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef LASTEXPRESS_FIGHT_H
-#define LASTEXPRESS_FIGHT_H
-
-/*
- Fight structure
- ---------------
- uint32 {4} - player struct
- uint32 {4} - opponent struct
- uint32 {4} - hasLost flag
-
- byte {1} - isRunning
-
- Fight participant structure
- ---------------------------
- uint32 {4} - function pointer
- uint32 {4} - pointer to fight structure
- uint32 {4} - pointer to opponent (fight participant structure)
- uint32 {4} - array of sequences
- uint32 {4} - number of sequences
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint16 {2} - ??
- uint16 {2} - ?? - only for opponent structure
- uint32 {4} - ?? - only for opponent structure
-
-*/
-
-#include "lastexpress/shared.h"
-
-#include "lastexpress/eventhandler.h"
-
-#include "common/array.h"
-
-namespace LastExpress {
-
-class LastExpressEngine;
-class Sequence;
-class SequenceFrame;
-
-//////////////////////////////////////////////////////////////////////////
-// TODO : objectify!
-class Fight : public EventHandler {
-public:
- enum FightEndType {
- kFightEndWin = 0,
- kFightEndLost = 1,
- kFightEndExit = 2
- };
-
- Fight(LastExpressEngine *engine);
- ~Fight();
-
- FightEndType setup(FightType type);
-
- void eventMouse(const Common::Event &ev);
- void eventTick(const Common::Event &ev);
-
- void setStopped();
- void resetState() { _state = 0; }
-
-private:
- enum FightSequenceType {
- kFightSequenceType0 = 0,
- kFightSequenceType1 = 1,
- kFightSequenceType2 = 2
- };
-
- enum FightAction {
- kFightAction1 = 1,
- kFightAction2 = 2,
- kFightAction3 = 3,
- kFightAction4 = 4,
- kFightAction5 = 5,
- kFightAction101 = 101,
- kFightActionResetFrame = 102,
- kFightAction103 = 103,
- kFightActionWin = 104,
- kFightActionLost = 105,
- kFightAction128 = 128,
- kFightAction129 = 129,
- kFightAction130 = 130,
- kFightAction131 = 131,
- kFightAction132 = 132
- };
-
- struct Fighter {
- Common::Functor2<Fighter *, FightAction, void> *handleAction;
- Common::Functor1<Fighter *, void> *update;
- Common::Functor2<Fighter const *, FightAction, bool> *canInteract;
- Fighter *opponent;
- Common::Array<Sequence *> sequences;
- uint32 sequenceIndex;
- Sequence *sequence;
- SequenceFrame *frame;
- uint32 frameIndex;
- uint32 field_24;
- FightAction action;
- uint32 sequenceIndex2;
- int32 countdown; // countdown before loosing ?
- uint32 field_34;
-
- Fighter() {
- handleAction = NULL;
- update = NULL;
- canInteract = NULL;
-
- opponent = NULL;
-
- sequenceIndex = 0;
- sequence = NULL;
- frame = NULL;
- frameIndex = 0;
-
- field_24 = 0;
-
- action = kFightAction101;
- sequenceIndex2 = 0;
-
- countdown = 1;
-
- field_34 = 0;
- }
- };
-
- // Opponent struct
- struct Opponent : Fighter {
- int32 field_38;
-
- Opponent() : Fighter() {
- field_38 = 0;
- }
- };
-
- struct FightData {
- Fighter *player;
- Opponent *opponent;
- int32 index;
-
- Sequence *sequences[20];
- Common::String names[20];
-
- bool isRunning;
-
- FightData() {
- player = new Fighter();
- opponent = new Opponent();
-
- // Set opponents
- player->opponent = opponent;
- opponent->opponent = player;
-
- index = 0;
-
- isRunning = false;
- }
- };
-
- LastExpressEngine *_engine;
- FightData *_data;
- FightEndType _endType;
- int _state;
-
- bool _handleTimer;
-
- // Events
- void handleTick(const Common::Event &ev, bool unknown);
-
- // State
- void bailout(FightEndType type);
-
-
- // Drawing
- void setSequenceAndDraw(Fighter *fighter, uint32 sequenceIndex, FightSequenceType type) const;
- void draw(Fighter *fighter) const;
-
- // Cleanup
- void clearData();
- void clearSequences(Fighter *fighter) const;
-
- //////////////////////////////////////////////////////////////////////////
- // Loading
- void loadData(FightType type);
-
- // Shared
- void processFighter(Fighter *fighter);
-
- // Default functions
- void handleAction(Fighter *fighter, FightAction action);
- void update(Fighter *fighter);
- bool canInteract(Fighter const *fighter, FightAction = (FightAction)0);
- void updateOpponent(Fighter *fighter);
-
- // Milos
- void loadMilosPlayer();
- void loadMilosOpponent();
- void handleActionMilos(Fighter *fighter, FightAction action);
- void updateMilos(Fighter *fighter);
- bool canInteractMilos(Fighter const *fighter, FightAction action);
- void handleOpponentActionMilos(Fighter *fighter, FightAction action);
- void updateOpponentMilos(Fighter *fighter);
-
- // Anna
- void loadAnnaPlayer();
- void loadAnnaOpponent();
- void handleActionAnna(Fighter *fighter, FightAction action);
- void updateOpponentAnna(Fighter *fighter);
-
- // Ivo
- void loadIvoPlayer();
- void loadIvoOpponent();
- void handleActionIvo(Fighter *fighter, FightAction action);
- void updateIvo(Fighter *fighter);
- bool canInteractIvo(Fighter const *fighter, FightAction action);
- void handleOpponentActionIvo(Fighter *fighter, FightAction action);
- void updateOpponentIvo(Fighter *fighter);
-
- // Salko
- void loadSalkoPlayer();
- void loadSalkoOpponent();
- void handleActionSalko(Fighter *fighter, FightAction action);
- void updateSalko(Fighter *fighter);
- bool canInteractSalko(Fighter const *fighter, FightAction action);
- void handleOpponentActionSalko(Fighter *fighter, FightAction action);
- void updateOpponentSalko(Fighter *fighter);
-
- // Vesna
- void loadVesnaPlayer();
- void loadVesnaOpponent();
- void handleActionVesna(Fighter *fighter, FightAction action);
- void updateVesna(Fighter *fighter);
- bool canInteractVesna(Fighter const *fighter, FightAction action);
- void handleOpponentActionVesna(Fighter *fighter, FightAction action);
- void updateOpponentVesna(Fighter *fighter);
-};
-
-} // End of namespace LastExpress
-
-#endif // LASTEXPRESS_FIGHT_H
diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp
index adf6ff772e..e417b1ec0d 100644
--- a/engines/lastexpress/game/inventory.cpp
+++ b/engines/lastexpress/game/inventory.cpp
@@ -27,11 +27,14 @@
#include "lastexpress/data/snd.h"
#include "lastexpress/game/logic.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
+#include "lastexpress/sound/queue.h"
+#include "lastexpress/sound/sound.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
@@ -155,14 +158,14 @@ void Inventory::handleMouseEvent(const Common::Event &ev) {
_portraitHighlighted = false;
_isOpened = false;
- getSound()->playSoundWithSubtitles("LIB039.SND", SoundManager::kFlagMenuClock, kEntityPlayer);
+ getSound()->playSoundWithSubtitles("LIB039.SND", kFlagMenuClock, kEntityPlayer);
getMenu()->show(true, kSavegameTypeIndex, 0);
} else if (ev.type == Common::EVENT_RBUTTONDOWN) {
if (getGlobalTimer()) {
- if (getSound()->isBuffered("TIMER"))
- getSound()->removeFromQueue("TIMER");
+ if (getSoundQueue()->isBuffered("TIMER"))
+ getSoundQueue()->removeFromQueue("TIMER");
setGlobalTimer(900);
}
@@ -436,7 +439,7 @@ void Inventory::showHourGlass(){
//////////////////////////////////////////////////////////////////////////
Inventory::InventoryEntry *Inventory::get(InventoryItem item) {
if (item >= kPortraitOriginal)
- error("Inventory::getEntry: Invalid inventory item!");
+ error("[Inventory::get] Invalid inventory item");
return &_entries[item];
}
@@ -620,7 +623,7 @@ void Inventory::drawEgg() {
// Blinking egg: we need to blink the egg for delta time, with the blinking getting faster until it's always lit.
void Inventory::drawBlinkingEgg() {
- warning("Inventory::drawEgg - blinking not implemented!");
+ warning("[Inventory::drawBlinkingEgg] Blinking not implemented");
//// TODO show egg (with or without mouseover)
@@ -629,7 +632,7 @@ void Inventory::drawBlinkingEgg() {
// if (getGlobalTimer() + ticks >= 90)
// getSound()->playSoundWithSubtitles("TIMER.SND", 50331664, kEntityPlayer);
- // if (getSound()->isBuffered("TIMER"))
+ // if (getSoundQueue()->isBuffered("TIMER"))
// setGlobalTimer(0);
//}
diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp
index 0911c60de0..aeac8cff98 100644
--- a/engines/lastexpress/game/logic.cpp
+++ b/engines/lastexpress/game/logic.cpp
@@ -30,20 +30,25 @@
// Entities
#include "lastexpress/entities/chapters.h"
+// Fight
+#include "lastexpress/fight/fight.h"
+
// Game
#include "lastexpress/game/action.h"
#include "lastexpress/game/beetle.h"
#include "lastexpress/game/entities.h"
-#include "lastexpress/game/fight.h"
#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savegame.h"
#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
+#include "lastexpress/sound/queue.h"
+#include "lastexpress/sound/sound.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
@@ -149,7 +154,7 @@ void Logic::eventMouse(const Common::Event &ev) {
_engine->getCursor()->setStyle(getInventory()->get(kItemWhistle)->cursor);
// Check if clicked
- if (ev.type == Common::EVENT_LBUTTONUP && !getSound()->isBuffered("LIB045")) {
+ if (ev.type == Common::EVENT_LBUTTONUP && !getSoundQueue()->isBuffered("LIB045")) {
getSound()->playSoundEvent(kEntityPlayer, 45);
@@ -408,7 +413,7 @@ void Logic::eventTick(const Common::Event &) {
void Logic::resetState() {
getState()->scene = kSceneDefault;
- warning("Logic::resetState: not implemented! You need to restart the engine until this is implemented.");
+ warning("[Logic::resetState] Not implemented! You need to restart the engine until this is implemented.");
}
/**
@@ -421,7 +426,7 @@ void Logic::resetState() {
*/
void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, bool showScene) const {
- getSound()->processEntries();
+ getSoundQueue()->processEntries();
getEntities()->reset();
getFlags()->isGameRunning = false;
getSavePoints()->reset();
@@ -429,16 +434,16 @@ void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, boo
if (showScene) {
- getSound()->processEntry(SoundManager::kSoundType11);
+ getSoundQueue()->processEntry(kSoundType11);
if (sceneIndex && !getFlags()->mouseRightClick) {
getScenes()->loadScene(sceneIndex);
- while (getSound()->isBuffered(kEntityTables4)) {
+ while (getSoundQueue()->isBuffered(kEntityTables4)) {
if (getFlags()->mouseRightClick)
break;
- getSound()->updateQueue();
+ getSoundQueue()->updateQueue();
}
}
}
@@ -448,7 +453,7 @@ void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, boo
}
void Logic::switchChapter() const {
- getSound()->clearStatus();
+ getSoundQueue()->clearStatus();
switch(getState()->progress.chapter) {
default:
@@ -488,7 +493,7 @@ void Logic::switchChapter() const {
}
void Logic::playFinalSequence() const {
- getSound()->processEntries();
+ getSoundQueue()->processEntries();
_action->playAnimation(kEventFinalSequence);
showCredits();
@@ -501,7 +506,7 @@ void Logic::playFinalSequence() const {
}
void Logic::showCredits() const {
- error("Logic::showCredits: not implemented!");
+ error("[Logic::showCredits] Not implemented");
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/menu.cpp b/engines/lastexpress/game/menu.cpp
deleted file mode 100644
index f9eef26326..0000000000
--- a/engines/lastexpress/game/menu.cpp
+++ /dev/null
@@ -1,1541 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "lastexpress/game/menu.h"
-
-// Data
-#include "lastexpress/data/animation.h"
-#include "lastexpress/data/cursor.h"
-#include "lastexpress/data/snd.h"
-#include "lastexpress/data/scene.h"
-
-#include "lastexpress/game/fight.h"
-#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/logic.h"
-#include "lastexpress/game/savegame.h"
-#include "lastexpress/game/savepoint.h"
-#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
-#include "lastexpress/game/state.h"
-
-#include "lastexpress/graphics.h"
-#include "lastexpress/helpers.h"
-#include "lastexpress/lastexpress.h"
-#include "lastexpress/resource.h"
-
-#include "common/rational.h"
-
-#define getNextGameId() (GameId)((_gameId + 1) % 6)
-
-namespace LastExpress {
-
-// Bottom-left buttons (quit.seq)
-enum StartMenuButtons {
- kButtonVolumeDownPushed,
- kButtonVolumeDown,
- kButtonVolume,
- kButtonVolumeUp,
- kButtonVolumeUpPushed,
- kButtonBrightnessDownPushed, // 5
- kButtonBrightnessDown,
- kButtonBrightness,
- kButtonBrightnessUp,
- kButtonBrightnessUpPushed,
- kButtonQuit, // 10
- kButtonQuitPushed
-};
-
-// Egg buttons (buttns.seq)
-enum StartMenuEggButtons {
- kButtonShield,
- kButtonRewind,
- kButtonRewindPushed,
- kButtonForward,
- kButtonForwardPushed,
- kButtonCredits, // 5
- kButtonCreditsPushed,
- kButtonContinue
-};
-
-// Tooltips sequence (helpnewr.seq)
-enum StartMenuTooltips {
- kTooltipInsertCd1,
- kTooltipInsertCd2,
- kTooltipInsertCd3,
- kTooltipContinueGame,
- kTooltipReplayGame,
- kTooltipContinueRewoundGame, // 5
- kTooltipViewGameEnding,
- kTooltipStartAnotherGame,
- kTooltipVolumeUp,
- kTooltipVolumeDown,
- kTooltipBrightnessUp, // 10
- kTooltipBrightnessDown,
- kTooltipQuit,
- kTooltipRewindParis,
- kTooltipForwardStrasbourg,
- kTooltipRewindStrasbourg, // 15
- kTooltipRewindMunich,
- kTooltipForwardMunich,
- kTooltipForwardVienna,
- kTooltipRewindVienna,
- kTooltipRewindBudapest, // 20
- kTooltipForwardBudapest,
- kTooltipForwardBelgrade,
- kTooltipRewindBelgrade,
- kTooltipForwardConstantinople,
- kTooltipSwitchBlueGame, // 25
- kTooltipSwitchRedGame,
- kTooltipSwitchGoldGame,
- kTooltipSwitchGreenGame,
- kTooltipSwitchTealGame,
- kTooltipSwitchPurpleGame, // 30
- kTooltipPlayNewGame,
- kTooltipCredits,
- kTooltipFastForward,
- kTooltipRewind
-};
-
-//////////////////////////////////////////////////////////////////////////
-// DATA
-//////////////////////////////////////////////////////////////////////////
-
-// Information about the cities on the train line
-static const struct {
- uint8 frame;
- TimeValue time;
-} _trainCities[31] = {
- {0, kTimeCityParis},
- {9, kTimeCityEpernay},
- {11, kTimeCityChalons},
- {16, kTimeCityBarLeDuc},
- {21, kTimeCityNancy},
- {25, kTimeCityLuneville},
- {35, kTimeCityAvricourt},
- {37, kTimeCityDeutschAvricourt},
- {40, kTimeCityStrasbourg},
- {53, kTimeCityBadenOos},
- {56, kTimeCityKarlsruhe},
- {60, kTimeCityStuttgart},
- {63, kTimeCityGeislingen},
- {66, kTimeCityUlm},
- {68, kTimeCityAugsburg},
- {73, kTimeCityMunich},
- {84, kTimeCitySalzbourg},
- {89, kTimeCityAttnangPuchheim},
- {97, kTimeCityWels},
- {100, kTimeCityLinz},
- {104, kTimeCityAmstetten},
- {111, kTimeCityVienna},
- {120, kTimeCityPoszony},
- {124, kTimeCityGalanta},
- {132, kTimeCityBudapest},
- {148, kTimeCityBelgrade},
- /* Line 1 ends at 150 - line 2 begins at 0 */
- {157, kTimeCityNish},
- {165, kTimeCityTzaribrod},
- {174, kTimeCitySofia},
- {198, kTimeCityAdrianople},
- {210, kTimeCityConstantinople}};
-
-static const struct {
- TimeValue time;
- uint index;
- StartMenuTooltips rewind;
- StartMenuTooltips forward;
-} _cityButtonsInfo[7] = {
- {kTimeCityParis, 64, kTooltipRewindParis, kTooltipRewindParis},
- {kTimeCityStrasbourg, 128, kTooltipRewindStrasbourg, kTooltipForwardStrasbourg},
- {kTimeCityMunich, 129, kTooltipRewindMunich, kTooltipForwardMunich},
- {kTimeCityVienna, 130, kTooltipRewindVienna, kTooltipForwardVienna},
- {kTimeCityBudapest, 131, kTooltipRewindBudapest, kTooltipForwardBudapest},
- {kTimeCityBelgrade, 132, kTooltipRewindBelgrade, kTooltipForwardBelgrade},
- {kTimeCityConstantinople, 192, kTooltipForwardConstantinople, kTooltipForwardConstantinople}
-};
-
-//////////////////////////////////////////////////////////////////////////
-// Clock
-//////////////////////////////////////////////////////////////////////////
-class Clock {
-public:
- explicit Clock(LastExpressEngine *engine);
- ~Clock();
-
- void draw(uint32 time);
- void clear();
-
-private:
- LastExpressEngine *_engine;
-
- // Frames
- SequenceFrame *_frameMinutes;
- SequenceFrame *_frameHour;
- SequenceFrame *_frameSun;
- SequenceFrame *_frameDate;
-};
-
-Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) {
- _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true);
- _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true);
- _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
- _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
-}
-
-Clock::~Clock() {
- SAFE_DELETE(_frameMinutes);
- SAFE_DELETE(_frameHour);
- SAFE_DELETE(_frameSun);
- SAFE_DELETE(_frameDate);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-void Clock::clear() {
- getScenes()->removeFromQueue(_frameMinutes);
- getScenes()->removeFromQueue(_frameHour);
- getScenes()->removeFromQueue(_frameSun);
- getScenes()->removeFromQueue(_frameDate);
-}
-
-void Clock::draw(uint32 time) {
- assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
-
- // Check that sequences have been loaded
- if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate)
- error("Clock::process: clock sequences have not been loaded correctly!");
-
- // Clear existing frames
- clear();
-
- // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914
- // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914
- // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins
-
- // 15 = 1 second
- // 15 * 60 = 900 = 1 minute
- // 900 * 60 = 54000 = 1 hour
- // 54000 * 24 = 1296000 = 1 day
-
- // Calculate each sequence index from the current time
-
- uint8 hour = 0;
- uint8 minute = 0;
- State::getHourMinutes(time, &hour, &minute);
- uint32 index_date = 18 * time / 1296000;
- if (hour == 23)
- index_date += 18 * minute / 60;
-
- // Set sequences frames
- _frameMinutes->setFrame(minute);
- _frameHour->setFrame((5 * hour + minute / 12) % 60);
- _frameSun->setFrame((5 * hour + minute / 12) % 120);
- _frameDate->setFrame((uint16)index_date);
-
- // Adjust z-order and queue
- _frameMinutes->getInfo()->location = 1;
- _frameHour->getInfo()->location = 1;
- _frameSun->getInfo()->location = 1;
- _frameDate->getInfo()->location = 1;
-
- getScenes()->addToQueue(_frameMinutes);
- getScenes()->addToQueue(_frameHour);
- getScenes()->addToQueue(_frameSun);
- getScenes()->addToQueue(_frameDate);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// TrainLine
-//////////////////////////////////////////////////////////////////////////
-class TrainLine {
-public:
- explicit TrainLine(LastExpressEngine *engine);
- ~TrainLine();
-
- void draw(uint32 time);
- void clear();
-
-private:
- LastExpressEngine *_engine;
-
- // Frames
- SequenceFrame *_frameLine1;
- SequenceFrame *_frameLine2;
-};
-
-TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) {
- _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true);
- _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true);
-}
-
-TrainLine::~TrainLine() {
- SAFE_DELETE(_frameLine1);
- SAFE_DELETE(_frameLine2);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-void TrainLine::clear() {
- getScenes()->removeFromQueue(_frameLine1);
- getScenes()->removeFromQueue(_frameLine2);
-}
-
-// Draw the train line at the time
-// line1: 150 frames (=> Belgrade)
-// line2: 61 frames (=> Constantinople)
-void TrainLine::draw(uint32 time) {
- assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
-
- // Check that sequences have been loaded
- if (!_frameLine1 || !_frameLine2)
- error("TrainLine::process: Line sequences have not been loaded correctly!");
-
- // Clear existing frames
- clear();
-
- // Get the index of the last city the train has visited
- uint index = 0;
- for (uint i = 0; i < ARRAYSIZE(_trainCities); i++)
- if ((uint32)_trainCities[i].time <= time)
- index = i;
-
- uint16 frame;
- if (time > (uint32)_trainCities[index].time) {
- // Interpolate linearly to use a frame between the cities
- uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame;
- uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time);
- uint traveledTime = (time - (uint)_trainCities[index].time);
- frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities);
- } else {
- // Exactly on the city
- frame = _trainCities[index].frame;
- }
-
- // Set frame, z-order and queue
- if (frame < 150) {
- _frameLine1->setFrame(frame);
-
- _frameLine1->getInfo()->location = 1;
- getScenes()->addToQueue(_frameLine1);
- } else {
- // We passed Belgrade
- _frameLine1->setFrame(149);
- _frameLine2->setFrame(frame - 150);
-
- _frameLine1->getInfo()->location = 1;
- _frameLine2->getInfo()->location = 1;
-
- getScenes()->addToQueue(_frameLine1);
- getScenes()->addToQueue(_frameLine2);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// Menu
-//////////////////////////////////////////////////////////////////////////
-Menu::Menu(LastExpressEngine *engine) : _engine(engine),
- _seqTooltips(NULL), _seqEggButtons(NULL), _seqButtons(NULL), _seqAcorn(NULL), _seqCity1(NULL), _seqCity2(NULL), _seqCity3(NULL), _seqCredits(NULL),
- _gameId(kGameBlue), _hasShownStartScreen(false), _hasShownIntro(false),
- _isShowingCredits(false), _isGameStarted(false), _isShowingMenu(false),
- _creditsSequenceIndex(0), _checkHotspotsTicks(15), _mouseFlags(Common::EVENT_INVALID), _lastHotspot(NULL),
- _currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) {
-
- _clock = new Clock(_engine);
- _trainLine = new TrainLine(_engine);
-}
-
-Menu::~Menu() {
- SAFE_DELETE(_clock);
- SAFE_DELETE(_trainLine);
-
- SAFE_DELETE(_seqTooltips);
- SAFE_DELETE(_seqEggButtons);
- SAFE_DELETE(_seqButtons);
- SAFE_DELETE(_seqAcorn);
- SAFE_DELETE(_seqCity1);
- SAFE_DELETE(_seqCity2);
- SAFE_DELETE(_seqCity3);
- SAFE_DELETE(_seqCredits);
-
- _lastHotspot = NULL;
-
- // Cleanup frames
- for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
- SAFE_DELETE(it->_value);
-
- _frames.clear();
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Setup
-void Menu::setup() {
-
- // Clear drawing queue
- getScenes()->removeAndRedraw(&_frames[kOverlayAcorn], false);
- SAFE_DELETE(_seqAcorn);
-
- // Load Menu scene
- // + 1 = normal menu with open egg / clock
- // + 2 = shield menu, when no savegame exists (no game has been started)
- _isGameStarted = _lowerTime >= kTimeStartGame;
- getScenes()->loadScene((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2));
- getFlags()->shouldRedraw = true;
- getLogic()->updateCursor();
-
- //////////////////////////////////////////////////////////////////////////
- // Load Acorn sequence
- _seqAcorn = loadSequence(getAcornSequenceName(_isGameStarted ? getNextGameId() : kGameBlue));
-
- //////////////////////////////////////////////////////////////////////////
- // Check if we loaded sequences before
- if (_seqTooltips && _seqTooltips->count() > 0)
- return;
-
- // Load all static data
- _seqTooltips = loadSequence("helpnewr.seq");
- _seqEggButtons = loadSequence("buttns.seq");
- _seqButtons = loadSequence("quit.seq");
- _seqCity1 = loadSequence("jlinetl.seq");
- _seqCity2 = loadSequence("jlinecen.seq");
- _seqCity3 = loadSequence("jlinebr.seq");
- _seqCredits = loadSequence("credits.seq");
-
- _frames[kOverlayTooltip] = new SequenceFrame(_seqTooltips);
- _frames[kOverlayEggButtons] = new SequenceFrame(_seqEggButtons);
- _frames[kOverlayButtons] = new SequenceFrame(_seqButtons);
- _frames[kOverlayAcorn] = new SequenceFrame(_seqAcorn);
- _frames[kOverlayCity1] = new SequenceFrame(_seqCity1);
- _frames[kOverlayCity2] = new SequenceFrame(_seqCity2);
- _frames[kOverlayCity3] = new SequenceFrame(_seqCity3);
- _frames[kOverlayCredits] = new SequenceFrame(_seqCredits);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Handle events
-void Menu::eventMouse(const Common::Event &ev) {
- if (!getFlags()->shouldRedraw)
- return;
-
- bool redraw = true;
- getFlags()->shouldRedraw = false;
-
- // Update coordinates
- setCoords(ev.mouse);
- //_mouseFlags = (Common::EventType)(ev.type & Common::EVENT_LBUTTONUP);
-
- if (_isShowingCredits) {
- if (ev.type == Common::EVENT_RBUTTONUP) {
- showFrame(kOverlayCredits, -1, true);
- _isShowingCredits = false;
- }
-
- if (ev.type == Common::EVENT_LBUTTONUP) {
- // Last frame of the credits
- if (_seqCredits && _creditsSequenceIndex == _seqCredits->count() - 1) {
- showFrame(kOverlayCredits, -1, true);
- _isShowingCredits = false;
- } else {
- ++_creditsSequenceIndex;
- showFrame(kOverlayCredits, _creditsSequenceIndex, true);
- }
- }
- } else {
- // Check for hotspots
- SceneHotspot *hotspot = NULL;
- getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot);
-
- if (_lastHotspot != hotspot || ev.type == Common::EVENT_LBUTTONUP) {
- _lastHotspot = hotspot;
-
- if (ev.type == Common::EVENT_MOUSEMOVE) { /* todo check event type */
- if (!_handleTimeDelta && hasTimeDelta())
- setTime();
- }
-
- if (hotspot) {
- redraw = handleEvent((StartMenuAction)hotspot->action, ev.type);
- getFlags()->mouseRightClick = false;
- getFlags()->mouseLeftClick = false;
- } else {
- hideOverlays();
- }
- }
- }
-
- if (redraw) {
- getFlags()->shouldRedraw = true;
- askForRedraw();
- }
-}
-
-void Menu::eventTick(const Common::Event&) {
- if (hasTimeDelta())
- adjustTime();
- else if (_handleTimeDelta)
- _handleTimeDelta = false;
-
- // Check hotspots
- if (!--_checkHotspotsTicks) {
- checkHotspots();
- _checkHotspotsTicks = 15;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Show the intro and load the main menu scene
-void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
-
- if (_isShowingMenu)
- return;
-
- _isShowingMenu = true;
- getEntities()->reset();
-
- // If no blue savegame exists, this might be the first time we start the game, so we show the full intro
- if (!getFlags()->mouseRightClick) {
- if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
-
- if (!_hasShownIntro) {
- // Show Broderbrund logo
- Animation animation;
- if (animation.load(getArchive("1930.nis")))
- animation.play();
-
- getFlags()->mouseRightClick = false;
-
- // Play intro music
- getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer);
-
- // Show The Smoking Car logo
- if (animation.load(getArchive("1931.nis")))
- animation.play();
-
- _hasShownIntro = true;
- }
- } else {
- // Only show the quick intro
- if (!_hasShownStartScreen) {
- getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer);
- getScenes()->loadScene(kSceneStartScreen);
-
- // Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed
- uint32 nextFrameCount = getFrameCount() + 60;
- while (getFrameCount() < nextFrameCount) {
- _engine->pollEvents();
-
- if (getFlags()->mouseRightClick)
- break;
-
- getSound()->updateQueue();
- }
- }
- }
- }
-
- _hasShownStartScreen = true;
-
- // Init Menu
- init(doSavegame, type, value);
-
- // Setup sound
- getSound()->unknownFunction4();
- getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13);
- if (getSound()->isBuffered("TIMER"))
- getSound()->removeFromQueue("TIMER");
-
- // Init flags & misc
- _isShowingCredits = false;
- _handleTimeDelta = hasTimeDelta();
- getInventory()->unselectItem();
-
- // Set Cursor type
- _engine->getCursor()->setStyle(kCursorNormal);
- _engine->getCursor()->show(true);
-
- setup();
- checkHotspots();
-
- // Set event handlers
- SET_EVENT_HANDLERS(Menu, this);
-}
-
-bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
- bool clicked = (type == Common::EVENT_LBUTTONUP);
-
- switch(action) {
- default:
- hideOverlays();
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuCredits:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- showFrame(kOverlayEggButtons, kButtonCreditsPushed, true);
- showFrame(kOverlayTooltip, -1, true);
-
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- hideOverlays();
-
- _isShowingCredits = true;
- _creditsSequenceIndex = 0;
-
- showFrame(kOverlayCredits, 0, true);
- } else {
- // TODO check flags ?
-
- showFrame(kOverlayEggButtons, kButtonCredits, true);
- showFrame(kOverlayTooltip, kTooltipCredits, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuQuitGame:
- showFrame(kOverlayTooltip, kTooltipQuit, true);
-
- if (clicked) {
- showFrame(kOverlayButtons, kButtonQuitPushed, true);
-
- getSound()->clearStatus();
- getSound()->updateQueue();
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- // FIXME uncomment when sound queue is properly implemented
- /*while (getSound()->isBuffered("LIB046"))
- getSound()->updateQueue();*/
-
- getFlags()->shouldRedraw = false;
-
- Engine::quitGame();
-
- return false;
- } else {
- showFrame(kOverlayButtons, kButtonQuit, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuCase4:
- if (clicked)
- _index = 0;
- // fall down to kMenuContinue
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuContinue: {
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Determine the proper CD archive
- ArchiveIndex cd = kArchiveCd1;
- if (getProgress().chapter > kChapter1)
- cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2;
-
- // Show tooltips & buttons to start a game, continue a game or load the proper cd
- if (ResourceManager::isArchivePresent(cd)) {
- if (_isGameStarted) {
- showFrame(kOverlayEggButtons, kButtonContinue, true);
-
- if (_lastIndex == _index) {
- showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true);
- } else {
- showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true);
- }
-
- } else {
- showFrame(kOverlayEggButtons, kButtonShield, true);
- showFrame(kOverlayTooltip, kTooltipPlayNewGame, true);
- }
- } else {
- showFrame(kOverlayEggButtons, -1, true);
- showFrame(kOverlayTooltip, cd - 1, true);
- }
-
- if (!clicked)
- break;
-
- // Try loading the archive file
- if (!_engine->getResourceManager()->loadArchive(cd))
- break;
-
- // Load the train data file and setup game
- getScenes()->loadSceneDataFile(cd);
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- // Setup new game
- getSavePoints()->reset();
- setLogicEventHandlers();
-
- if (_index) {
- getSound()->processEntry(SoundManager::kSoundType11);
- } else {
- if (!getFlags()->mouseRightClick) {
- getScenes()->loadScene((SceneIndex)(5 * _gameId + 3));
-
- if (!getFlags()->mouseRightClick) {
- getScenes()->loadScene((SceneIndex)(5 * _gameId + 4));
-
- if (!getFlags()->mouseRightClick) {
- getScenes()->loadScene((SceneIndex)(5 * _gameId + 5));
-
- if (!getFlags()->mouseRightClick) {
- getSound()->processEntry(SoundManager::kSoundType11);
-
- // Show intro
- Animation animation;
- if (animation.load(getArchive("1601.nis")))
- animation.play();
-
- getEvent(kEventIntro) = 1;
- }
- }
- }
- }
-
- if (!getEvent(kEventIntro)) {
- getEvent(kEventIntro) = 1;
-
- getSound()->processEntry(SoundManager::kSoundType11);
- }
- }
-
- // Setup game
- getFlags()->isGameRunning = true;
- startGame();
-
- if (!_isShowingMenu)
- getInventory()->show();
-
- return false;
- }
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuSwitchSaveGame:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- showFrame(kOverlayAcorn, 1, true);
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB047");
-
- // Setup new menu screen
- switchGame();
- setup();
-
- // Set fight state to 0
- getFight()->resetState();
-
- return true;
- }
-
- // TODO Check for flag
-
- showFrame(kOverlayAcorn, 0, true);
-
- if (_isGameStarted) {
- showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
- break;
- }
-
- if (_gameId == kGameGold) {
- showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
- break;
- }
-
- if (!SaveLoad::isSavegameValid(getNextGameId())) {
- showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
- break;
- }
-
- // Stupid tooltips ids are not in order, so we can't just increment them...
- switch(_gameId) {
- default:
- break;
-
- case kGameBlue:
- showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true);
- break;
-
- case kGameRed:
- showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true);
- break;
-
- case kGameGreen:
- showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true);
- break;
-
- case kGamePurple:
- showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true);
- break;
-
- case kGameTeal:
- showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true);
- break;
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuRewindGame:
- if (!_index || _currentTime < _time) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- if (hasTimeDelta())
- _handleTimeDelta = false;
-
- showFrame(kOverlayEggButtons, kButtonRewindPushed, true);
- showFrame(kOverlayTooltip, -1, true);
-
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- rewindTime();
-
- _handleTimeDelta = false;
- } else {
- showFrame(kOverlayEggButtons, kButtonRewind, true);
- showFrame(kOverlayTooltip, kTooltipRewind, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuForwardGame:
- if (_lastIndex <= _index || _currentTime > _time) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- if (hasTimeDelta())
- _handleTimeDelta = false;
-
- showFrame(kOverlayEggButtons, kButtonForwardPushed, true);
- showFrame(kOverlayTooltip, -1, true);
-
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- forwardTime();
-
- _handleTimeDelta = false;
- } else {
- showFrame(kOverlayEggButtons, kButtonForward, true);
- showFrame(kOverlayTooltip, kTooltipFastForward, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuParis:
- moveToCity(kParis, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuStrasBourg:
- moveToCity(kStrasbourg, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuMunich:
- moveToCity(kMunich, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuVienna:
- moveToCity(kVienna, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuBudapest:
- moveToCity(kBudapest, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuBelgrade:
- moveToCity(kBelgrade, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuConstantinople:
- moveToCity(kConstantinople, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuDecreaseVolume:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot decrease volume further
- if (getVolume() == 0) {
- showFrame(kOverlayButtons, kButtonVolume, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipVolumeDown, true);
-
- // Show highlight on button & adjust volume if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonVolumeDownPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setVolume(getVolume() - 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- uint32 nextFrameCount = getFrameCount() + 15;
- while (nextFrameCount > getFrameCount()) {
- _engine->pollEvents();
-
- getSound()->updateQueue();
- }
- } else {
- showFrame(kOverlayButtons, kButtonVolumeDown, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuIncreaseVolume:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot increase volume further
- if (getVolume() >= 7) {
- showFrame(kOverlayButtons, kButtonVolume, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipVolumeUp, true);
-
- // Show highlight on button & adjust volume if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonVolumeUpPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setVolume(getVolume() + 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- uint32 nextFrameCount = getFrameCount() + 15;
- while (nextFrameCount > getFrameCount()) {
- _engine->pollEvents();
-
- getSound()->updateQueue();
- }
- } else {
- showFrame(kOverlayButtons, kButtonVolumeUp, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuDecreaseBrightness:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot increase brightness further
- if (getBrightness() == 0) {
- showFrame(kOverlayButtons, kButtonBrightness, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipBrightnessDown, true);
-
- // Show highlight on button & adjust brightness if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setBrightness(getBrightness() - 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
- _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
- showFrame(kOverlayTooltip, kTooltipBrightnessDown, false);
- showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false);
- } else {
- showFrame(kOverlayButtons, kButtonBrightnessDown, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuIncreaseBrightness:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot increase brightness further
- if (getBrightness() >= 6) {
- showFrame(kOverlayButtons, kButtonBrightness, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipBrightnessUp, true);
-
- // Show highlight on button & adjust brightness if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setBrightness(getBrightness() + 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
- _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
- showFrame(kOverlayTooltip, kTooltipBrightnessUp, false);
- showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false);
- } else {
- showFrame(kOverlayButtons, kButtonBrightnessUp, true);
- }
- break;
- }
-
- return true;
-}
-
-void Menu::setLogicEventHandlers() {
- SET_EVENT_HANDLERS(Logic, getLogic());
- clear();
- _isShowingMenu = false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Game-related
-//////////////////////////////////////////////////////////////////////////
-void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
-
- bool useSameIndex = true;
-
- if (getGlobalTimer()) {
- value = 0;
-
- // Check if the CD file is present
- ArchiveIndex index = kArchiveCd1;
- switch (getProgress().chapter) {
- default:
- case kChapter1:
- break;
-
- case kChapter2:
- case kChapter3:
- index = kArchiveCd2;
- break;
-
- case kChapter4:
- case kChapter5:
- index = kArchiveCd3;
- break;
- }
-
- if (ResourceManager::isArchivePresent(index)) {
- setGlobalTimer(0);
- useSameIndex = false;
-
- // TODO remove existing savegame and reset index & savegame name
- warning("Menu::initGame: not implemented!");
- }
-
- doSavegame = false;
- } else {
- // TODO rename saves?
- }
-
- // Create a new savegame if needed
- if (!SaveLoad::isSavegamePresent(_gameId))
- getSaveLoad()->create(_gameId);
-
- if (doSavegame)
- getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone);
-
- if (!getGlobalTimer()) {
- // TODO: remove existing savegame temp file
- }
-
- // Init savegame & menu values
- _lastIndex = getSaveLoad()->init(_gameId, true);
- _lowerTime = getSaveLoad()->getTime(_lastIndex);
-
- if (useSameIndex)
- _index = _lastIndex;
-
- //if (!getGlobalTimer())
- // _index3 = 0;
-
- if (!getProgress().chapter)
- getProgress().chapter = kChapter1;
-
- getState()->time = (TimeValue)getSaveLoad()->getTime(_index);
- getProgress().chapter = getSaveLoad()->getChapter(_index);
-
- if (_lowerTime >= kTimeStartGame) {
- _currentTime = (uint32)getState()->time;
- _time = (uint32)getState()->time;
- _clock->draw(_time);
- _trainLine->draw(_time);
-
- initTime(type, value);
- }
-}
-
-// Start a game (or load an existing savegame)
-void Menu::startGame() {
- // Clear savegame headers
- getSaveLoad()->clear();
-
- // Hide menu elements
- _clock->clear();
- _trainLine->clear();
-
- if (_lastIndex == _index) {
- setGlobalTimer(0);
- if (_index) {
- getSaveLoad()->loadGame(_gameId);
- } else {
- getLogic()->resetState();
- getEntities()->setup(true, kEntityPlayer);
- }
- } else {
- getSaveLoad()->loadGame(_gameId, _index);
- }
-}
-
-// Switch to the next savegame
-void Menu::switchGame() {
-
- // Switch back to blue game is the current game is not started
- _gameId = SaveLoad::isSavegameValid(_gameId) ? getNextGameId() : kGameBlue;
-
- // Initialize savegame if needed
- if (!SaveLoad::isSavegamePresent(_gameId))
- getSaveLoad()->create(_gameId);
-
- getState()->time = kTimeNone;
-
- // Clear menu elements
- _clock->clear();
- _trainLine->clear();
-
- // Clear loaded savegame data
- getSaveLoad()->clear(true);
-
- init(false, kSavegameTypeIndex, 0);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Overlays & elements
-//////////////////////////////////////////////////////////////////////////
-void Menu::checkHotspots() {
- if (!_isShowingMenu)
- return;
-
- if (!getFlags()->shouldRedraw)
- return;
-
- if (_isShowingCredits)
- return;
-
- SceneHotspot *hotspot = NULL;
- getScenes()->get(getState()->scene)->checkHotSpot(getCoords(), &hotspot);
-
- if (hotspot)
- handleEvent((StartMenuAction)hotspot->action, _mouseFlags);
- else
- hideOverlays();
-}
-
-void Menu::hideOverlays() {
- _lastHotspot = NULL;
-
- // Hide all menu overlays
- for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
- showFrame(it->_key, -1, false);
-
- getScenes()->drawFrames(true);
-}
-
-void Menu::showFrame(StartMenuOverlay overlayType, int index, bool redraw) {
- if (index == -1) {
- getScenes()->removeFromQueue(_frames[overlayType]);
- } else {
- // Check that the overlay is valid
- if (!_frames[overlayType])
- return;
-
- // Remove the frame and add a new one with the proper index
- getScenes()->removeFromQueue(_frames[overlayType]);
- _frames[overlayType]->setFrame((uint16)index);
- getScenes()->addToQueue(_frames[overlayType]);
- }
-
- if (redraw)
- getScenes()->drawFrames(true);
-}
-
-// Remove all frames from the queue
-void Menu::clear() {
- for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
- getScenes()->removeAndRedraw(&it->_value, false);
-
- clearBg(GraphicsManager::kBackgroundOverlay);
-}
-
-// Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame
-Common::String Menu::getAcornSequenceName(GameId id) const {
- Common::String name = "";
- switch (id) {
- default:
- case kGameBlue:
- name = "aconblu3.seq";
- break;
-
- case kGameRed:
- name = "aconred.seq";
- break;
-
- case kGameGreen:
- name = "acongren.seq";
- break;
-
- case kGamePurple:
- name = "aconpurp.seq";
- break;
-
- case kGameTeal:
- name = "aconteal.seq";
- break;
-
- case kGameGold:
- name = "acongold.seq";
- break;
- }
-
- return name;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Time
-//////////////////////////////////////////////////////////////////////////
-void Menu::initTime(SavegameType type, uint32 value) {
- if (!value)
- return;
-
- // The savegame entry index
- uint32 entryIndex = 0;
-
- switch (type) {
- default:
- break;
-
- case kSavegameTypeIndex:
- entryIndex = (_index <= value) ? 1 : _index - value;
- break;
-
- case kSavegameTypeTime:
- if (value < kTimeStartGame)
- break;
-
- entryIndex = _index;
- if (!entryIndex)
- break;
-
- // Iterate through existing entries
- do {
- if (getSaveLoad()->getTime(entryIndex) <= value)
- break;
-
- entryIndex--;
- } while (entryIndex);
- break;
-
- case kSavegameTypeEvent:
- entryIndex = _index;
- if (!entryIndex)
- break;
-
- do {
- if (getSaveLoad()->getValue(entryIndex) == value)
- break;
-
- entryIndex--;
- } while (entryIndex);
- break;
-
- case kSavegameTypeEvent2:
- // TODO rewrite in a more legible way
- if (_index > 1) {
- uint32 index = _index;
- do {
- if (getSaveLoad()->getValue(index) == value)
- break;
-
- index--;
- } while (index > 1);
-
- entryIndex = index - 1;
- } else {
- entryIndex = _index - 1;
- }
- break;
- }
-
- if (entryIndex) {
- _currentIndex = entryIndex;
- updateTime(getSaveLoad()->getTime(entryIndex));
- }
-}
-
-void Menu::updateTime(uint32 time) {
- if (_currentTime == _time)
- _delta = 0;
-
- _currentTime = time;
-
- if (_time != time) {
- if (getSound()->isBuffered(kEntityChapters))
- getSound()->removeFromQueue(kEntityChapters);
-
- getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", SoundManager::kFlagMenuClock, kEntityChapters);
- adjustIndex(_currentTime, _time, false);
- }
-}
-
-void Menu::adjustIndex(uint32 time1, uint32 time2, bool searchEntry) {
- uint32 index = 0;
- int32 timeDelta = -1;
-
- if (time1 != time2) {
-
- index = _index;
-
- if (time2 >= time1) {
- if (searchEntry) {
- uint32 currentIndex = _index;
-
- if ((int32)_index >= 0) {
- do {
- // Calculate new delta
- int32 newDelta = time1 - (uint32)getSaveLoad()->getTime(currentIndex);
-
- if (newDelta >= 0 && timeDelta >= newDelta) {
- timeDelta = newDelta;
- index = currentIndex;
- }
-
- --currentIndex;
- } while ((int32)currentIndex >= 0);
- }
- } else {
- index = _index - 1;
- }
- } else {
- if (searchEntry) {
- uint32 currentIndex = _index;
-
- if (_lastIndex >= _index) {
- do {
- // Calculate new delta
- int32 newDelta = (uint32)getSaveLoad()->getTime(currentIndex) - time1;
-
- if (newDelta >= 0 && timeDelta > newDelta) {
- timeDelta = newDelta;
- index = currentIndex;
- }
-
- ++currentIndex;
- } while (currentIndex <= _lastIndex);
- }
- } else {
- index = _index + 1;
- }
- }
-
- _index = index;
- checkHotspots();
- }
-
- if (_index == _currentIndex) {
- if (getProgress().chapter != getSaveLoad()->getChapter(index))
- getProgress().chapter = getSaveLoad()->getChapter(_index);
- }
-}
-
-void Menu::goToTime(uint32 time) {
-
- uint32 entryIndex = 0;
- uint32 deltaTime = (uint32)ABS((int32)(getSaveLoad()->getTime(0) - time));
- uint32 index = 0;
-
- do {
- uint32 deltaTime2 = (uint32)ABS((int32)(getSaveLoad()->getTime(index) - time));
- if (deltaTime2 < deltaTime) {
- deltaTime = deltaTime2;
- entryIndex = index;
- }
-
- ++index;
- } while (_lastIndex >= index);
-
- _currentIndex = entryIndex;
- updateTime(getSaveLoad()->getTime(entryIndex));
-}
-
-void Menu::setTime() {
- _currentIndex = _index;
- _currentTime = getSaveLoad()->getTime(_currentIndex);
-
- if (_time == _currentTime)
- adjustTime();
-}
-
-void Menu::forwardTime() {
- if (_lastIndex <= _index)
- return;
-
- _currentIndex = _lastIndex;
- updateTime(getSaveLoad()->getTime(_currentIndex));
-}
-
-void Menu::rewindTime() {
- if (!_index)
- return;
-
- _currentIndex = 0;
- updateTime(getSaveLoad()->getTime(_currentIndex));
-}
-
-void Menu::adjustTime() {
- uint32 originalTime = _time;
-
- // Adjust time delta
- Common::Rational timeDelta(_delta >= 90 ? 9 : (9 * _delta + 89), _delta >= 90 ? 1 : 90);
-
- if (_currentTime < _time) {
- timeDelta *= 900;
- _time -= (uint)timeDelta.toInt();
-
- if (_currentTime > _time)
- _time = _currentTime;
- } else {
- timeDelta *= 900;
- _time += (uint)timeDelta.toInt();
-
- if (_currentTime < _time)
- _time = _currentTime;
- }
-
- if (_currentTime == _time && getSound()->isBuffered(kEntityChapters))
- getSound()->removeFromQueue(kEntityChapters);
-
- _clock->draw(_time);
- _trainLine->draw(_time);
- getScenes()->drawFrames(true);
-
- adjustIndex(_time, originalTime, true);
-
- ++_delta;
-}
-
-void Menu::moveToCity(CityButton city, bool clicked) {
- uint32 time = (uint32)_cityButtonsInfo[city].time;
-
- // TODO Check if we have access (there seems to be more checks on some internal times) - probably : current_time (menu only) / game time / some other?
- if (_lowerTime < time || _time == time || _currentTime == time) {
- hideOverlays();
- return;
- }
-
- // Show city overlay
- showFrame((StartMenuOverlay)((_cityButtonsInfo[city].index >> 6) + 3), _cityButtonsInfo[city].index & 63, true);
-
- if (clicked) {
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- goToTime(time);
-
- _handleTimeDelta = true;
-
- return;
- }
-
- // Special case of first and last cities
- if (city == kParis || city == kConstantinople) {
- showFrame(kOverlayTooltip, (city == kParis) ? kTooltipRewindParis : kTooltipForwardConstantinople, true);
- return;
- }
-
- showFrame(kOverlayTooltip, (_time <= time) ? _cityButtonsInfo[city].forward : _cityButtonsInfo[city].rewind, true);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Sound / Brightness
-//////////////////////////////////////////////////////////////////////////
-
-// Get current volume (converted internal ScummVM value)
-uint32 Menu::getVolume() const {
- return getState()->volume;
-}
-
-// Set the volume (converts to ScummVM values)
-void Menu::setVolume(uint32 volume) const {
- getState()->volume = volume;
-
- // Clamp volume
- uint32 value = volume * Audio::Mixer::kMaxMixerVolume / 7;
-
- if (value > Audio::Mixer::kMaxMixerVolume)
- value = Audio::Mixer::kMaxMixerVolume;
-
- _engine->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (int32)value);
-}
-
-uint32 Menu::getBrightness() const {
- return getState()->brightness;
-}
-
-void Menu::setBrightness(uint32 brightness) const {
- getState()->brightness = brightness;
-
- // TODO reload cursor & font with adjusted brightness
-}
-
-} // End of namespace LastExpress
diff --git a/engines/lastexpress/game/menu.h b/engines/lastexpress/game/menu.h
deleted file mode 100644
index 4b84c065cb..0000000000
--- a/engines/lastexpress/game/menu.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef LASTEXPRESS_MENU_H
-#define LASTEXPRESS_MENU_H
-
-#include "lastexpress/data/sequence.h"
-
-#include "lastexpress/eventhandler.h"
-
-#include "lastexpress/shared.h"
-
-#include "common/hashmap.h"
-
-namespace LastExpress {
-
-class LastExpressEngine;
-class Scene;
-class SceneHotspot;
-
-class Clock;
-class TrainLine;
-
-class Menu : public EventHandler {
-public:
- Menu(LastExpressEngine *engine);
- ~Menu();
-
- void show(bool doSavegame, SavegameType type, uint32 value);
-
- // Event handling
- void eventMouse(const Common::Event &ev);
- void eventTick(const Common::Event &ev);
-
- bool isShown() const { return _isShowingMenu; }
-
- GameId getGameId() const { return _gameId; }
-
-private:
- // Start menu events
- enum StartMenuAction {
- kMenuContinue = 1,
- kMenuCredits = 2,
- kMenuQuitGame = 3,
- kMenuCase4 = 4,
- kMenuSwitchSaveGame = 6,
- kMenuRewindGame = 7,
- kMenuForwardGame = 8,
- kMenuParis = 10,
- kMenuStrasBourg = 11,
- kMenuMunich = 12,
- kMenuVienna = 13,
- kMenuBudapest = 14,
- kMenuBelgrade = 15,
- kMenuConstantinople = 16,
- kMenuDecreaseVolume = 17,
- kMenuIncreaseVolume = 18,
- kMenuDecreaseBrightness = 19,
- kMenuIncreaseBrightness = 20
- };
-
- // City buttons
- enum CityButton {
- kParis = 0,
- kStrasbourg = 1,
- kMunich = 2,
- kVienna = 3,
- kBudapest = 4,
- kBelgrade = 5,
- kConstantinople = 6
- };
-
- // Start menu overlay elements
- enum StartMenuOverlay {
- kOverlayTooltip, // 0
- kOverlayEggButtons,
- kOverlayButtons,
- kOverlayAcorn,
- kOverlayCity1,
- kOverlayCity2, // 5
- kOverlayCity3,
- kOverlayCredits
- };
-
- LastExpressEngine *_engine;
-
- // Sequences
- Sequence *_seqTooltips;
- Sequence *_seqEggButtons;
- Sequence *_seqButtons;
- Sequence *_seqAcorn;
- Sequence *_seqCity1;
- Sequence *_seqCity2;
- Sequence *_seqCity3;
- Sequence *_seqCredits;
-
- GameId _gameId;
-
- // Indicator to know if we need to show the start animation when showMenu is called
- bool _hasShownStartScreen;
- bool _hasShownIntro;
-
- bool _isShowingCredits;
- bool _isGameStarted;
- bool _isShowingMenu;
-
-
- uint16 _creditsSequenceIndex;
-
- //////////////////////////////////////////////////////////////////////////
- // Event handling
- uint32 _checkHotspotsTicks;
- Common::EventType _mouseFlags;
- SceneHotspot *_lastHotspot;
-
- void init(bool doSavegame, SavegameType type, uint32 value);
- void setup();
- bool handleEvent(StartMenuAction action, Common::EventType type);
- void checkHotspots();
- void setLogicEventHandlers();
-
- //////////////////////////////////////////////////////////////////////////
- // Game-related
- void startGame();
- void switchGame();
-
- //////////////////////////////////////////////////////////////////////////
- // Overlays & elements
- Clock *_clock;
- TrainLine *_trainLine;
-
- struct MenuOverlays_EqualTo {
- bool operator()(const StartMenuOverlay &x, const StartMenuOverlay &y) const { return x == y; }
- };
-
- struct MenuOverlays_Hash {
- uint operator()(const StartMenuOverlay &x) const { return x; }
- };
-
- typedef Common::HashMap<StartMenuOverlay, SequenceFrame *, MenuOverlays_Hash, MenuOverlays_EqualTo> MenuFrames;
-
- MenuFrames _frames;
-
- void hideOverlays();
- void showFrame(StartMenuOverlay overlay, int index, bool redraw);
-
- void clear();
-
- // TODO: remove?
- void moveToCity(CityButton city, bool clicked);
-
- //////////////////////////////////////////////////////////////////////////
- // Misc
- Common::String getAcornSequenceName(GameId id) const;
-
- //////////////////////////////////////////////////////////////////////////
- // Time
- uint32 _currentTime; // current game time
- uint32 _lowerTime; // lower time value
- uint32 _time;
-
- uint32 _currentIndex; // current savegame entry
- uint32 _index;
- uint32 _lastIndex;
- uint32 _delta;
- bool _handleTimeDelta;
-
- void initTime(SavegameType type, uint32 val);
- void updateTime(uint32 time);
- void adjustTime();
- void adjustIndex(uint32 time1, uint32 time2, bool searchEntry);
- void goToTime(uint32 time);
- void setTime();
- void forwardTime();
- void rewindTime();
- bool hasTimeDelta() { return (_currentTime - _time) >= 1; }
-
- //////////////////////////////////////////////////////////////////////////
- // Sound/Brightness related
- uint32 getVolume() const;
- void setVolume(uint32 volume) const;
- uint32 getBrightness() const;
- void setBrightness(uint32 brightness) const;
-};
-
-} // End of namespace LastExpress
-
-#endif // LASTEXPRESS_MENU_H
diff --git a/engines/lastexpress/game/object.cpp b/engines/lastexpress/game/object.cpp
index a600075953..d9e9e4279a 100644
--- a/engines/lastexpress/game/object.cpp
+++ b/engines/lastexpress/game/object.cpp
@@ -39,7 +39,7 @@ Objects::Objects(LastExpressEngine *engine) : _engine(engine) {}
const Objects::Object Objects::get(ObjectIndex index) const {
if (index >= kObjectMax)
- error("Objects::get - internal error: invalid object index (%d)", index);
+ error("[Objects::get] Invalid object index (%d)", index);
return _objects[index];
}
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 5d06ecab13..ebada5dd4e 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -24,11 +24,14 @@
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
+#include "lastexpress/sound/queue.h"
+
#include "lastexpress/debug.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/helpers.h"
@@ -72,10 +75,10 @@ void SaveLoad::initStream() {
void SaveLoad::flushStream(GameId id) {
Common::OutSaveFile *save = openForSaving(id);
if (!save)
- error("SaveLoad::flushStream: cannot open savegame (%s)!", getFilename(id).c_str());
+ error("[SaveLoad::flushStream] Cannot open savegame (%s)", getFilename(id).c_str());
if (!_savegame)
- error("SaveLoad::flushStream: savegame stream is invalid");
+ error("[SaveLoad::flushStream] Savegame stream is invalid");
save->write(_savegame->getData(), (uint32)_savegame->size());
@@ -106,7 +109,7 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) {
SavegameMainHeader mainHeader;
mainHeader.saveLoadWithSerializer(ser);
if (!mainHeader.isValid())
- error("SaveLoad::init - Savegame seems to be corrupted (invalid header)");
+ error("[SaveLoad::init] Savegame seems to be corrupted (invalid header)");
// Reset cached entry headers if needed
if (resetHeaders) {
@@ -124,7 +127,7 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) {
while (_savegame->pos() < _savegame->size() && !_savegame->eos() && !_savegame->err()) {
// Update sound queue while we go through the savegame
- getSound()->updateQueue();
+ getSoundQueue()->updateQueue();
SavegameEntryHeader *entry = new SavegameEntryHeader();
entry->saveLoadWithSerializer(ser);
@@ -145,10 +148,10 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) {
void SaveLoad::loadStream(GameId id) {
Common::InSaveFile *save = openForLoading(id);
if (save->size() < 32)
- error("SaveLoad::init - Savegame seems to be corrupted (not enough data: %i bytes)", save->size());
+ error("[SaveLoad::loadStream] Savegame seems to be corrupted (not enough data: %i bytes)", save->size());
if (!_savegame)
- error("SaveLoad::loadStream: savegame stream is invalid");
+ error("[SaveLoad::loadStream] Savegame stream is invalid");
// Load all savegame data
uint8* buf = new uint8[8192];
@@ -189,7 +192,7 @@ void SaveLoad::clear(bool clearStream) {
// Load game
void SaveLoad::loadGame(GameId id) {
if (!_savegame)
- error("SaveLoad::loadGame: No savegame stream present!");
+ error("[SaveLoad::loadGame] No savegame stream present");
// Rewind current savegame
_savegame->seek(0);
@@ -197,12 +200,12 @@ void SaveLoad::loadGame(GameId id) {
// Validate main header
SavegameMainHeader header;
if (!loadMainHeader(_savegame, &header)) {
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::saveGame - Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
return;
}
if (!_savegame)
- error("SaveLoad::loadGame: No savegame stream present!");
+ error("[SaveLoad::loadGame] No savegame stream present");
// Load the last entry
_savegame->seek(header.offsetEntry);
@@ -216,7 +219,7 @@ void SaveLoad::loadGame(GameId id) {
_gameTicksLastSavegame = getState()->timeTicks;
if (header.keepIndex) {
- getSound()->clearQueue();
+ getSoundQueue()->clearQueue();
readEntry(&type, &entity, &val, false);
}
@@ -227,7 +230,7 @@ void SaveLoad::loadGame(GameId id) {
// Load a specific game entry
void SaveLoad::loadGame(GameId id, uint32 index) {
- error("SaveLoad::loadGame: not implemented! (only loading the last entry is working for now)");
+ error("[SaveLoad::loadGame] Not implemented! (only loading the last entry is working for now)");
}
// Save game
@@ -238,12 +241,12 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
// Validate main header
SavegameMainHeader header;
if (!loadMainHeader(_savegame, &header)) {
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::saveGame - Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
return;
}
if (!_savegame)
- error("SaveLoad::saveGame: savegame stream is invalid");
+ error("[SaveLoad::saveGame] Savegame stream is invalid");
// Validate the current entry if it exists
if (header.count > 0) {
@@ -255,7 +258,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
entry.saveLoadWithSerializer(ser);
if (!entry.isValid()) {
- warning("SaveLoad::saveGame: Invalid entry. This savegame might be corrupted!");
+ warning("[SaveLoad::saveGame] Invalid entry. This savegame might be corrupted");
_savegame->seek(header.offset);
} else if (getState()->time < entry.time || (type == kSavegameTypeTickInterval && getState()->time == entry.time)) {
// Not ready to save a game, skipping!
@@ -293,7 +296,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
// Validate the main header
if (!header.isValid())
- error("SaveLoad::saveGame: main game header is invalid!");
+ error("[SaveLoad::saveGame] Main game header is invalid");
// Write the main header
_savegame->seek(0);
@@ -304,7 +307,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
}
void SaveLoad::saveVolumeBrightness() {
- warning("SaveLoad::saveVolumeBrightness: not implemented!");
+ warning("[SaveLoad::saveVolumeBrightness] Not implemented");
}
//////////////////////////////////////////////////////////////////////////
@@ -316,7 +319,7 @@ bool SaveLoad::loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *he
// Check there is enough data (32 bytes)
if (stream->size() < 32) {
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::loadMainHeader - Savegame seems to be corrupted (not enough data: %i bytes)!", stream->size());
+ debugC(2, kLastExpressDebugSavegame, "Savegame seems to be corrupted (not enough data: %i bytes)", stream->size());
return false;
}
@@ -328,7 +331,7 @@ bool SaveLoad::loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *he
// Validate the header
if (!header->isValid()) {
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::loadMainHeader - Cannot validate main header!");
+ debugC(2, kLastExpressDebugSavegame, "Cannot validate main header");
return false;
}
@@ -345,11 +348,11 @@ void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) {
uint32 _count = (uint32)_savegame->pos() - _prevPosition; \
debugC(kLastExpressDebugSavegame, "Savegame: Writing " #name ": %d bytes", _count); \
if (_count != val)\
- error("SaveLoad::writeEntry: Number of bytes written (%d) differ from expected count (%d)", _count, val); \
+ error("[SaveLoad::writeEntry] Number of bytes written (%d) differ from expected count (%d)", _count, val); \
}
if (!_savegame)
- error("SaveLoad::writeEntry: savegame stream is invalid");
+ error("[SaveLoad::writeEntry] Savegame stream is invalid");
SavegameEntryHeader header;
@@ -376,7 +379,7 @@ void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) {
WRITE_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32);
WRITE_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128);
WRITE_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40);
- WRITE_ENTRY("sound", getSound()->saveLoadWithSerializer(ser), 3 * 4 + getSound()->count() * 64);
+ WRITE_ENTRY("sound", getSoundQueue()->saveLoadWithSerializer(ser), 3 * 4 + getSoundQueue()->count() * 64);
WRITE_ENTRY("savepoints", getSavePoints()->saveLoadWithSerializer(ser), 128 * 16 + 4 + getSavePoints()->count() * 16);
header.offset = (uint32)_savegame->pos() - (originalPosition + 32);
@@ -392,7 +395,7 @@ void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) {
// Validate entry header
if (!header.isValid())
- error("SaveLoad::writeEntry: entry header is invalid");
+ error("[SaveLoad::writeEntry] Entry header is invalid");
// Save the header with the updated info
_savegame->seek(originalPosition);
@@ -409,7 +412,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
uint32 _count = (uint32)_savegame->pos() - _prevPosition; \
debugC(kLastExpressDebugSavegame, "Savegame: Reading " #name ": %d bytes", _count); \
if (_count != val) \
- error("SaveLoad::readEntry: Number of bytes read (%d) differ from expected count (%d)", _count, val); \
+ error("[SaveLoad::readEntry] Number of bytes read (%d) differ from expected count (%d)", _count, val); \
}
#define LOAD_ENTRY_ONLY(name, func) { \
@@ -420,10 +423,10 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
}
if (!type || !entity || !val)
- error("SaveLoad::readEntry: Invalid parameters passed!");
+ error("[SaveLoad::readEntry] Invalid parameters passed");
if (!_savegame)
- error("SaveLoad::readEntry: No savegame stream present!");
+ error("[SaveLoad::readEntry] No savegame stream present");
// Load entry header
SavegameEntryHeader entry;
@@ -431,7 +434,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
entry.saveLoadWithSerializer(ser);
if (!entry.isValid())
- error("SaveLoad::readEntry: entry header is invalid!");
+ error("[SaveLoad::readEntry] Entry header is invalid");
// Init type, entity & value
*type = entry.type;
@@ -451,7 +454,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
LOAD_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32);
LOAD_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128);
LOAD_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40);
- LOAD_ENTRY_ONLY("sound", getSound()->saveLoadWithSerializer(ser));
+ LOAD_ENTRY_ONLY("sound", getSoundQueue()->saveLoadWithSerializer(ser));
LOAD_ENTRY_ONLY("savepoints", getSavePoints()->saveLoadWithSerializer(ser));
// Update chapter
@@ -466,7 +469,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
SaveLoad::SavegameEntryHeader *SaveLoad::getEntry(uint32 index) {
if (index >= _gameHeaders.size())
- error("SaveLoad::getEntry: invalid index (was:%d, max:%d)", index, _gameHeaders.size() - 1);
+ error("[SaveLoad::getEntry] Invalid index (was:%d, max:%d)", index, _gameHeaders.size() - 1);
return _gameHeaders[index];
}
@@ -486,7 +489,7 @@ bool SaveLoad::isSavegamePresent(GameId id) {
// Check if the game has been started in the specific savegame
bool SaveLoad::isSavegameValid(GameId id) {
if (!isSavegamePresent(id)) {
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::isSavegameValid - Savegame does not exist: %s", getFilename(id).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Savegame does not exist: %s", getFilename(id).c_str());
return false;
}
@@ -549,7 +552,7 @@ bool SaveLoad::isGameFinished(uint32 menuIndex, uint32 savegameIndex) {
// Get the file name from the savegame ID
Common::String SaveLoad::getFilename(GameId id) {
if (id >= 6)
- error("SaveLoad::getName - attempting to use an invalid game id. Valid values: 0 - 5, was %d", id);
+ error("[SaveLoad::getFilename] Attempting to use an invalid game id. Valid values: 0 - 5, was %d", id);
return gameInfo[id].saveFile;
}
@@ -558,7 +561,7 @@ Common::InSaveFile *SaveLoad::openForLoading(GameId id) {
Common::InSaveFile *load = g_system->getSavefileManager()->openForLoading(getFilename(id));
if (!load)
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::openForLoading - Cannot open savegame for loading: %s", getFilename(id).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for loading: %s", getFilename(id).c_str());
return load;
}
@@ -567,7 +570,7 @@ Common::OutSaveFile *SaveLoad::openForSaving(GameId id) {
Common::OutSaveFile *save = g_system->getSavefileManager()->openForSaving(getFilename(id));
if (!save)
- debugC(2, kLastExpressDebugSavegame, "SaveLoad::openForSaving - Cannot open savegame for writing: %s", getFilename(id).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for writing: %s", getFilename(id).c_str());
return save;
}
diff --git a/engines/lastexpress/game/savepoint.cpp b/engines/lastexpress/game/savepoint.cpp
index 7ec7c241e9..64ae26c2be 100644
--- a/engines/lastexpress/game/savepoint.cpp
+++ b/engines/lastexpress/game/savepoint.cpp
@@ -128,17 +128,17 @@ void SavePoints::addData(EntityIndex entity, ActionIndex action, uint32 param) {
//////////////////////////////////////////////////////////////////////////
void SavePoints::setCallback(EntityIndex index, Entity::Callback *callback) {
if (index >= 40)
- error("SavePoints::setCallback - attempting to use an invalid entity index. Valid values 0-39, was %d", index);
+ error("[SavePoints::setCallback] Attempting to use an invalid entity index. Valid values 0-39, was %d", index);
if (!callback || !callback->isValid())
- error("SavePoints::setCallback - attempting to set an invalid callback for entity %s", ENTITY_NAME(index));
+ error("[SavePoints::setCallback] Attempting to set an invalid callback for entity %s", ENTITY_NAME(index));
_callbacks[index] = callback;
}
Entity::Callback *SavePoints::getCallback(EntityIndex index) const {
if (index >= 40)
- error("SavePoints::getCallback - attempting to use an invalid entity index. Valid values 0-39, was %d", index);
+ error("[SavePoints::getCallback] Attempting to use an invalid entity index. Valid values 0-39, was %d", index);
return _callbacks[index];
}
diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp
index e830b1d128..b886951e0b 100644
--- a/engines/lastexpress/game/scenes.cpp
+++ b/engines/lastexpress/game/scenes.cpp
@@ -31,9 +31,11 @@
#include "lastexpress/game/logic.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
-#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/sound/queue.h"
+#include "lastexpress/sound/sound.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
@@ -79,12 +81,12 @@ void SceneManager::loadSceneDataFile(ArchiveIndex archive) {
case kArchiveCd2:
case kArchiveCd3:
if (!_sceneLoader->load(getArchive(Common::String::format("CD%iTRAIN.DAT", archive))))
- error("SceneManager::loadSceneDataFile: cannot load data file CD%iTRAIN.DAT", archive);
+ error("[SceneManager::loadSceneDataFile] Cannot load data file CD%iTRAIN.DAT", archive);
break;
default:
case kArchiveAll:
- error("SceneManager::loadSceneDataFile: Invalid archive index (must be [1-3], was %d", archive);
+ error("[SceneManager::loadSceneDataFile] Invalid archive index (must be [1-3], was %d", archive);
break;
}
}
@@ -462,7 +464,7 @@ bool SceneManager::checkPosition(SceneIndex index, CheckPositionType type) const
switch (type) {
default:
- error("SceneManager::checkPosition: Invalid position type: %d", type);
+ error("[SceneManager::checkPosition] Invalid position type: %d", type);
case kCheckPositionLookingUp:
return isInSleepingCar && (position >= 1 && position <= 19);
@@ -1057,9 +1059,9 @@ void SceneManager::preProcessScene(SceneIndex *index) {
// Sound processing
Scene *newScene = getScenes()->get(*index);
- if (getSound()->isBuffered(kEntityTables4)) {
+ if (getSoundQueue()->isBuffered(kEntityTables4)) {
if (newScene->type != Scene::kTypeReadText || newScene->param1)
- getSound()->processEntry(kEntityTables4);
+ getSoundQueue()->processEntry(kEntityTables4);
}
// Cleanup beetle sequences
@@ -1089,8 +1091,8 @@ void SceneManager::postProcessScene() {
if (getFlags()->mouseRightClick)
break;
- getSound()->updateQueue();
- getSound()->updateSubtitles();
+ getSoundQueue()->updateQueue();
+ getSoundQueue()->updateSubtitles();
}
}
@@ -1132,7 +1134,7 @@ void SceneManager::postProcessScene() {
}
if (progress)
- getSound()->excuseMe((progress == 1) ? entities[0] : entities[rnd(progress)], kEntityPlayer, SoundManager::kFlagDefault);
+ getSound()->excuseMe((progress == 1) ? entities[0] : entities[rnd(progress)], kEntityPlayer, kFlagDefault);
}
if (hotspot->scene)
@@ -1157,8 +1159,8 @@ void SceneManager::postProcessScene() {
if (getState()->time >= kTimeCityGalanta || getProgress().field_18 == 4)
break;
- getSound()->processEntry(SoundManager::kSoundType7);
- getSound()->playSound(kEntityTrain, "LIB050", SoundManager::kFlagDefault);
+ getSoundQueue()->processEntry(kSoundType7);
+ getSound()->playSound(kEntityTrain, "LIB050", kFlagDefault);
switch (getProgress().chapter) {
default:
diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp
deleted file mode 100644
index 3f98ac79ea..0000000000
--- a/engines/lastexpress/game/sound.cpp
+++ /dev/null
@@ -1,1951 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "lastexpress/game/sound.h"
-
-#include "lastexpress/game/action.h"
-#include "lastexpress/game/entities.h"
-#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/logic.h"
-#include "lastexpress/game/savepoint.h"
-#include "lastexpress/game/state.h"
-
-#include "lastexpress/helpers.h"
-#include "lastexpress/graphics.h"
-#include "lastexpress/lastexpress.h"
-#include "lastexpress/resource.h"
-
-namespace LastExpress {
-
-#define SOUNDCACHE_ENTRY_SIZE 92160
-#define SOUNDCACHE_MAX_SIZE 6
-
-// Letters & messages
-const char *messages[24] = {
- "",
- "TXT1001", // 1
- "TXT1001A", // 2
- "TXT1011", // 3
- "TXT1012", // 4
- "TXT1013", // 5
- "TXT1014", // 6
- "TXT1020", // 7
- "TXT1030", // 8
- "END1009B", // 50
- "END1046", // 51
- "END1047", // 52
- "END1112", // 53
- "END1112A", // 54
- "END1503", // 55
- "END1505A", // 56
- "END1505B", // 57
- "END1610", // 58
- "END1612A", // 59
- "END1612C", // 61
- "END1612D", // 62
- "ENDALRM1", // 63
- "ENDALRM2", // 64
- "ENDALRM3" // 65
-};
-
-const char *cities[17] = {
- "EPERNAY",
- "CHALONS",
- "BARLEDUC",
- "NANCY",
- "LUNEVILL",
- "AVRICOUR",
- "DEUTSCHA",
- "STRASBOU",
- "BADENOOS",
- "SALZBURG",
- "ATTNANG",
- "WELS",
- "LINZ",
- "VIENNA",
- "POZSONY",
- "GALANTA",
- "POLICE"
-};
-
-const char *locomotiveSounds[5] = {
- "ZFX1005",
- "ZFX1006",
- "ZFX1007",
- "ZFX1007A",
- "ZFX1007B"
-};
-
-static const SoundManager::FlagType soundFlags[32] = {
- SoundManager::kFlagDefault, SoundManager::kFlag15, SoundManager::kFlag14, SoundManager::kFlag13, SoundManager::kFlag12,
- SoundManager::kFlag11, SoundManager::kFlag11, SoundManager::kFlag10, SoundManager::kFlag10, SoundManager::kFlag9, SoundManager::kFlag9, SoundManager::kFlag8, SoundManager::kFlag8,
- SoundManager::kFlag7, SoundManager::kFlag7, SoundManager::kFlag7, SoundManager::kFlag6, SoundManager::kFlag6, SoundManager::kFlag6,
- SoundManager::kFlag5, SoundManager::kFlag5, SoundManager::kFlag5, SoundManager::kFlag5, SoundManager::kFlag4, SoundManager::kFlag4, SoundManager::kFlag4, SoundManager::kFlag4,
- SoundManager::kFlag3, SoundManager::kFlag3, SoundManager::kFlag3, SoundManager::kFlag3, SoundManager::kFlag3
-};
-
-SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine), _state(0), _currentType(kSoundType16), _flag(0) {
- // Initialize unknown data
- _data0 = 0;
- _data1 = 0;
- _data2 = 0;
-
- memset(&_buffer, 0, sizeof(_buffer));
- memset(&_lastWarning, 0, sizeof(_lastWarning));
-
- // Sound cache
- _soundCacheData = malloc(6 * SOUNDCACHE_ENTRY_SIZE);
-
- _drawSubtitles = 0;
- _currentSubtitle = NULL;
-}
-
-SoundManager::~SoundManager() {
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
- SAFE_DELETE(*i);
- _soundList.clear();
-
- // Entries in the cache are just pointers to sound list entries
- _soundCache.clear();
-
- for (Common::List<SubtitleEntry *>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i)
- SAFE_DELETE(*i);
- _subtitles.clear();
-
- _currentSubtitle = NULL;
-
- free(_soundCacheData);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Timer
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::handleTimer() {
- Common::StackLock locker(_mutex);
-
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- SoundEntry *entry = (*i);
- if (entry->stream == NULL) {
- SAFE_DELETE(*i);
- i = _soundList.reverse_erase(i);
- continue;
- } else if (!entry->soundStream) {
- entry->soundStream = new StreamedSound();
-
- // TODO: stream any sound in the queue after filtering
- entry->soundStream->load(entry->stream);
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Sound queue management
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::updateQueue() {
- // TODO add mutex lock!
- warning("Sound::updateQueue: not implemented!");
-}
-
-void SoundManager::resetQueue(SoundType type1, SoundType type2) {
- if (!type2)
- type2 = type1;
-
- Common::StackLock locker(_mutex);
-
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- if ((*i)->type != type1 && (*i)->type != type2)
- resetEntry(*i);
- }
-}
-
-void SoundManager::removeFromQueue(EntityIndex entity) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(entity);
- if (entry)
- resetEntry(entry);
-}
-
-void SoundManager::removeFromQueue(Common::String filename) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(filename);
- if (entry)
- resetEntry(entry);
-}
-
-void SoundManager::clearQueue() {
- _flag |= 4;
-
- // FIXME: Wait a while for a flag to be set
- //for (int i = 0; i < 3000000; i++)
- // if (_flag & 8)
- // break;
-
- _flag |= 8;
-
- Common::StackLock locker(_mutex);
-
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- SoundEntry *entry = (*i);
-
- // Delete entry
- removeEntry(entry);
- SAFE_DELETE(entry);
-
- i = _soundList.reverse_erase(i);
- }
-
- updateSubtitles();
-}
-
-bool SoundManager::isBuffered(EntityIndex entity) {
- Common::StackLock locker(_mutex);
-
- return (getEntry(entity) != NULL);
-}
-
-bool SoundManager::isBuffered(Common::String filename, bool testForEntity) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(filename);
-
- if (testForEntity)
- return entry != NULL && !entry->entity;
-
- return (entry != NULL);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Entry
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::setupEntry(SoundEntry *entry, Common::String name, FlagType flag, int a4) {
- if (!entry)
- error("SoundManager::setupEntry: Invalid entry!");
-
- entry->field_4C = a4;
- setEntryType(entry, flag);
- setEntryStatus(entry, flag);
-
- // Add entry to sound list
- _soundList.push_back(entry);
-
- // TODO Add entry to cache and load sound data
- //setupCache(entry);
- loadSoundData(entry, name);
-}
-
-void SoundManager::setEntryType(SoundEntry *entry, FlagType flag) {
- switch (flag & kFlagType9) {
- default:
- case kFlagNone:
- entry->type = _currentType;
- _currentType = (SoundType)(_currentType + 1);
- break;
-
- case kFlagType1_2: {
- SoundEntry *previous2 = getEntry(kSoundType2);
- if (previous2)
- updateEntry(previous2, 0);
-
- SoundEntry *previous = getEntry(kSoundType1);
- if (previous) {
- previous->type = kSoundType2;
- updateEntry(previous, 0);
- }
-
- entry->type = kSoundType1;
- }
- break;
-
- case kFlagType3: {
- SoundEntry *previous = getEntry(kSoundType3);
- if (previous) {
- previous->type = kSoundType4;
- updateEntry(previous, 0);
- }
-
- entry->type = kSoundType11;
- }
- break;
-
- case kFlagType7: {
- SoundEntry *previous = getEntry(kSoundType7);
- if (previous)
- previous->type = kSoundType8;
-
- entry->type = kSoundType7;
- }
- break;
-
- case kFlagType9: {
- SoundEntry *previous = getEntry(kSoundType9);
- if (previous)
- previous->type = kSoundType10;
-
- entry->type = kSoundType9;
- }
- break;
-
- case kFlagType11: {
- SoundEntry *previous = getEntry(kSoundType11);
- if (previous)
- previous->type = kSoundType14;
-
- entry->type = kSoundType11;
- }
- break;
-
- case kFlagType13: {
- SoundEntry *previous = getEntry(kSoundType13);
- if (previous)
- previous->type = kSoundType14;
-
- entry->type = kSoundType13;
- }
- break;
- }
-}
-
-void SoundManager::setEntryStatus(SoundEntry *entry, FlagType flag) const {
- SoundStatus status = (SoundStatus)flag;
- if (!((status & 0xFF) & kSoundStatusClear1))
- status = (SoundStatus)(status | kSoundStatusClear2);
-
- if (((status & 0xFF00) >> 8) & kSoundStatusClear0)
- entry->status.status = (uint32)status;
- else
- entry->status.status = (status | kSoundStatusClear4);
-}
-
-void SoundManager::setInCache(SoundEntry *entry) {
- entry->status.status |= kSoundStatusClear2;
-}
-
-bool SoundManager::setupCache(SoundEntry *entry) {
- if (entry->soundData)
- return true;
-
- if (_soundCache.size() >= SOUNDCACHE_MAX_SIZE) {
-
- SoundEntry *cacheEntry = NULL;
- uint32 size = 1000;
-
- for (Common::List<SoundEntry *>::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) {
- if (!((*i)->status.status & kSoundStatus_180)) {
- uint32 newSize = (*i)->field_4C + ((*i)->status.status & kSoundStatusClear1);
-
- if (newSize < size) {
- cacheEntry = (*i);
- size = newSize;
- }
- }
- }
-
- if (entry->field_4C <= size)
- return false;
-
- if (cacheEntry)
- setInCache(cacheEntry);
-
- // TODO: Wait until the cache entry is ready to be removed
- while (!(cacheEntry->status.status1 & 1))
- ;
-
- if (cacheEntry->soundData)
- removeFromCache(cacheEntry);
-
- _soundCache.push_back(entry);
- entry->soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1);
- } else {
- _soundCache.push_back(entry);
- entry->soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1);
- }
-
- return true;
-}
-
-void SoundManager::removeFromCache(SoundEntry *entry) {
- for (Common::List<SoundEntry *>::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) {
- if ((*i) == entry) {
- // Remove sound buffer
- entry->soundData = NULL;
-
- // Remove entry from sound cache
- i = _soundCache.reverse_erase(i);
- }
- }
-}
-
-void SoundManager::clearStatus() {
- Common::StackLock locker(_mutex);
-
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
- (*i)->status.status |= kSoundStatusClear3;
-}
-
-void SoundManager::loadSoundData(SoundEntry *entry, Common::String name) {
- entry->name2 = name;
-
- // Load sound data
- entry->stream = getArchive(name);
-
- if (!entry->stream)
- entry->stream = getArchive("DEFAULT.SND");
-
- if (entry->stream) {
- warning("Sound::loadSoundData: not implemented!");
- } else {
- entry->status.status = kSoundStatusRemoved;
- }
-}
-
-void SoundManager::resetEntry(SoundEntry *entry) const {
- entry->status.status |= kSoundStatusRemoved;
- entry->entity = kEntityPlayer;
-
- if (entry->stream) {
- if (!entry->soundStream) {
- SAFE_DELETE(entry->stream);
- } else {
- entry->soundStream->stop();
- SAFE_DELETE(entry->soundStream);
- }
-
- entry->stream = NULL;
- }
-}
-
-
-void SoundManager::removeEntry(SoundEntry *entry) {
- entry->status.status |= kSoundStatusRemoved;
-
- // Loop until ready
- while (!(entry->status.status1 & 4) && !(_flag & 8) && (_flag & 1))
- ; // empty loop body
-
- // The original game remove the entry from the cache here,
- // but since we are called from within an iterator loop
- // we will remove the entry there
- // removeFromCache(entry);
-
- if (entry->subtitle) {
- drawSubtitle(entry->subtitle);
- SAFE_DELETE(entry->subtitle);
- }
-
- if (entry->entity) {
- if (entry->entity == kEntitySteam)
- playLoopingSound();
- else if (entry->entity != kEntityTrain)
- getSavePoints()->push(kEntityPlayer, entry->entity, kActionEndSound);
- }
-}
-
-void SoundManager::updateEntry(SoundEntry *entry, uint value) const {
- if (!(entry->status.status3 & 64)) {
- int value2 = value;
-
- entry->status.status |= kSoundStatus_100000;
-
- if (value) {
- if (_flag & 32) {
- entry->field_40 = value;
- value2 = value * 2 + 1;
- }
-
- entry->field_3C = value2;
- } else {
- entry->field_3C = 0;
- entry->status.status |= kSoundStatus_40000000;
- }
- }
-}
-
-void SoundManager::updateEntryState(SoundEntry *entry) const {
- if (_flag & 32) {
- if (entry->type != kSoundType9 && entry->type != kSoundType7 && entry->type != kSoundType5) {
- uint32 status = entry->status.status & kSoundStatusClear1;
-
- entry->status.status &= kSoundStatusClearAll;
-
- entry->field_40 = status;
- entry->status.status |= status * 2 + 1;
- }
- }
-
- entry->status.status |= kSoundStatus_20;
-}
-
-void SoundManager::processEntry(EntityIndex entity) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(entity);
- if (entry) {
- updateEntry(entry, 0);
- entry->entity = kEntityPlayer;
- }
-}
-
-void SoundManager::processEntry(SoundType type) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(type);
- if (entry)
- updateEntry(entry, 0);
-}
-
-void SoundManager::setupEntry(SoundType type, EntityIndex index) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(type);
- if (entry)
- entry->entity = index;
-}
-
-void SoundManager::processEntry(Common::String filename) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(filename);
- if (entry) {
- updateEntry(entry, 0);
- entry->entity = kEntityPlayer;
- }
-}
-
-void SoundManager::processEntries() {
- _state = 0;
-
- processEntry(kSoundType1);
- processEntry(kSoundType2);
-}
-
-uint32 SoundManager::getEntryTime(EntityIndex index) {
- Common::StackLock locker(_mutex);
-
- SoundEntry *entry = getEntry(index);
- if (entry)
- return entry->time;
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Misc
-//////////////////////////////////////////////////////////////////////////
-
-void SoundManager::unknownFunction4() {
- // TODO: Add mutex ?
- warning("Sound::unknownFunction4: not implemented!");
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Entry search
-//////////////////////////////////////////////////////////////////////////
-SoundManager::SoundEntry *SoundManager::getEntry(EntityIndex index) {
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- if ((*i)->entity == index)
- return *i;
- }
-
- return NULL;
-}
-
-SoundManager::SoundEntry *SoundManager::getEntry(Common::String name) {
- if (!name.contains('.'))
- name += ".SND";
-
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- if ((*i)->name2 == name)
- return *i;
- }
-
- return NULL;
-}
-
-SoundManager::SoundEntry *SoundManager::getEntry(SoundType type) {
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- if ((*i)->type == type)
- return *i;
- }
-
- return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Savegame
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::saveLoadWithSerializer(Common::Serializer &s) {
- s.syncAsUint32LE(_state);
- s.syncAsUint32LE(_currentType);
-
- // Compute the number of entries to save
- uint32 numEntries = count();
- s.syncAsUint32LE(numEntries);
-
- Common::StackLock locker(_mutex);
-
- // Save or load each entry data
- if (s.isSaving()) {
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
- SoundEntry *entry = *i;
- if (entry->name2.matchString("NISSND?") && (entry->status.status & kFlagType7) != kFlag3) {
- s.syncAsUint32LE(entry->status.status); // status;
- s.syncAsUint32LE(entry->type); // type;
- s.syncAsUint32LE(entry->field_1C); // field_8;
- s.syncAsUint32LE(entry->time); // time;
- s.syncAsUint32LE(entry->field_34); // field_10;
- s.syncAsUint32LE(entry->field_38); // field_14;
- s.syncAsUint32LE(entry->entity); // entity;
-
- uint32 field_1C = (uint32)entry->field_48 - _data2;
- if (field_1C > kFlag8)
- field_1C = 0;
- s.syncAsUint32LE(field_1C); // field_1C;
-
- s.syncAsUint32LE(entry->field_4C); // field_20;
-
- char name1[16];
- strcpy((char *)&name1, entry->name1.c_str());
- s.syncBytes((byte *)&name1, 16);
-
- char name2[16];
- strcpy((char *)&name2, entry->name2.c_str());
- s.syncBytes((byte *)&name2, 16);
- }
- }
- } else {
- warning("Sound::saveLoadWithSerializer: not implemented!");
- s.skip(numEntries * 64);
- }
-}
-
-
-// FIXME: We probably need another mutex here to protect during the whole savegame process
-// as we could have removed an entry between the time we check the count and the time we
-// save the entries
-uint32 SoundManager::count() {
- Common::StackLock locker(_mutex);
-
- uint32 numEntries = 0;
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
- if ((*i)->name2.matchString("NISSND?"))
- ++numEntries;
-
- return numEntries;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Game-related functions
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::playSound(EntityIndex entity, Common::String filename, FlagType flag, byte a4) {
- if (isBuffered(entity) && entity)
- removeFromQueue(entity);
-
- FlagType currentFlag = (flag == -1) ? getSoundFlag(entity) : (FlagType)(flag | 0x80000);
-
- // Add .SND at the end of the filename if needed
- if (!filename.contains('.'))
- filename += ".SND";
-
- if (!playSoundWithSubtitles(filename, currentFlag, entity, a4))
- if (entity)
- getSavePoints()->push(kEntityPlayer, entity, kActionEndSound);
-}
-
-bool SoundManager::playSoundWithSubtitles(Common::String filename, FlagType flag, EntityIndex entity, byte a4) {
- SoundEntry *entry = new SoundEntry();
-
- Common::StackLock locker(_mutex);
-
- setupEntry(entry, filename, flag, 30);
- entry->entity = entity;
-
- if (a4) {
- entry->field_48 = _data2 + 2 * a4;
- entry->status.status |= kSoundStatus_8000;
- } else {
- // Get subtitles name
- while (filename.size() > 4)
- filename.deleteLastChar();
-
- showSubtitle(entry, filename);
- updateEntryState(entry);
- }
-
- return (entry->type != kSoundTypeNone);
-}
-
-void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) {
- int values[5];
-
- if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car)
- return;
-
- if (getEntities()->isInSalon(entity) != getEntities()->isInSalon(kEntityPlayer))
- return;
-
- int _action = (int)action;
- FlagType flag = getSoundFlag(entity);
-
- switch (action) {
- case 36: {
- int _param3 = (flag <= 9) ? flag + 7 : 16;
-
- if (_param3 > 7) {
- _data0 = (uint)_param3;
- _data1 = _data2 + 2 * a3;
- }
- break;
- }
-
- case 37:
- _data0 = 7;
- _data1 = _data2 + 2 * a3;
- break;
-
- case 150:
- case 156:
- case 162:
- case 168:
- case 188:
- case 198:
- _action += 1 + (int)rnd(5);
- break;
-
- case 174:
- case 184:
- case 194:
- _action += 1 + (int)rnd(3);
- break;
-
- case 180:
- _action += 1 + (int)rnd(4);
- break;
-
- case 246:
- values[0] = 0;
- values[1] = 104;
- values[2] = 105;
- values[3] = 106;
- values[4] = 116;
- _action = values[rnd(5)];
- break;
-
- case 247:
- values[0] = 11;
- values[1] = 123;
- values[2] = 124;
- _action = values[rnd(3)];
- break;
-
- case 248:
- values[0] = 0;
- values[1] = 103;
- values[2] = 108;
- values[3] = 109;
- _action = values[rnd(4)];
- break;
-
- case 249:
- values[0] = 0;
- values[1] = 56;
- values[2] = 112;
- values[3] = 113;
- _action = values[rnd(4)];
- break;
-
- case 250:
- values[0] = 0;
- values[1] = 107;
- values[2] = 115;
- values[3] = 117;
- _action = values[rnd(4)];
- break;
-
- case 251:
- values[0] = 0;
- values[1] = 11;
- values[2] = 56;
- values[3] = 113;
- _action = values[rnd(4)];
- break;
-
- case 252:
- values[0] = 0;
- values[1] = 6;
- values[2] = 109;
- values[3] = 121;
- _action = values[rnd(4)];
- break;
-
- case 254:
- values[0] = 0;
- values[1] = 104;
- values[2] = 120;
- values[3] = 121;
- _action = values[rnd(4)];
- break;
-
- case 255:
- values[0] = 0;
- values[1] = 106;
- values[2] = 115;
- _action = values[rnd(3)];
- break;
-
- default:
- break;
- }
-
- if (_action && flag)
- playSoundWithSubtitles(Common::String::format("LIB%03d.SND", _action), flag, kEntityPlayer, a3);
-}
-
-void SoundManager::playSteam(CityIndex index) {
- if (index >= ARRAYSIZE(cities))
- error("SoundManager::playSteam: invalid city index (was %d, max %d)", index, ARRAYSIZE(cities));
-
- _state |= kSoundState2;
-
- if (!getEntry(kSoundType1))
- playSoundWithSubtitles("STEAM.SND", kFlagSteam, kEntitySteam);
-
- // Get the new sound entry and show subtitles
- SoundEntry *entry = getEntry(kSoundType1);
- if (entry)
- showSubtitle(entry, cities[index]);
-}
-
-void SoundManager::playFightSound(byte action, byte a4) {
- int _action = (int)action;
- int values[5];
-
- switch (action) {
- default:
- break;
-
- case 174:
- case 184:
- case 194:
- values[0] = action + 1;
- values[1] = action + 2;
- values[2] = action + 3;
- _action = values[rnd(3)];
- break;
-
- case 180:
- values[0] = action + 1;
- values[1] = action + 2;
- values[2] = action + 3;
- values[3] = action + 4;
- _action = values[rnd(4)];
- break;
-
- case 150:
- case 156:
- case 162:
- case 168:
- case 188:
- case 198:
- values[0] = action + 1;
- values[1] = action + 2;
- values[2] = action + 3;
- values[3] = action + 4;
- values[4] = action + 5;
- _action = values[rnd(5)];
- break;
- }
-
- if (_action)
- playSound(kEntityTrain, Common::String::format("LIB%03d.SND", _action), kFlagDefault, a4);
-}
-
-void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, FlagType flag, byte a4) {
- if (isBuffered(getDialogName(entityDialog)))
- removeFromQueue(getDialogName(entityDialog));
-
- playSound(entity, getDialogName(entityDialog), flag, a4);
-}
-
-void SoundManager::playLocomotiveSound() {
- playSound(kEntityPlayer, locomotiveSounds[rnd(5)], (FlagType)(rnd(15) + 2));
-}
-
-const char *SoundManager::getDialogName(EntityIndex entity) const {
- switch (entity) {
- case kEntityAnna:
- if (getEvent(kEventAnnaDialogGoToJerusalem))
- return "XANN12";
-
- if (getEvent(kEventLocomotiveRestartTrain))
- return "XANN11";
-
- if (getEvent(kEventAnnaBaggageTies) || getEvent(kEventAnnaBaggageTies2) || getEvent(kEventAnnaBaggageTies3) || getEvent(kEventAnnaBaggageTies4))
- return "XANN10";
-
- if (getEvent(kEventAnnaTired) || getEvent(kEventAnnaTiredKiss))
- return "XANN9";
-
- if (getEvent(kEventAnnaBaggageArgument))
- return "XANN8";
-
- if (getEvent(kEventKronosVisit))
- return "XANN7";
-
- if (getEvent(kEventAbbotIntroduction))
- return "XANN6A";
-
- if (getEvent(kEventVassiliSeizure))
- return "XANN6";
-
- if (getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction))
- return "XANN5";
-
- if (getProgress().field_60)
- return "XANN4";
-
- if (getEvent(kEventAnnaGiveScarf) || getEvent(kEventAnnaGiveScarfDiner) || getEvent(kEventAnnaGiveScarfSalon)
- || getEvent(kEventAnnaGiveScarfMonogram) || getEvent(kEventAnnaGiveScarfDinerMonogram) || getEvent(kEventAnnaGiveScarfSalonMonogram))
- return "XANN3";
-
- if (getEvent(kEventDinerMindJoin))
- return "XANN2";
-
- if (getEvent(kEventGotALight) || getEvent(kEventGotALightD))
- return "XANN1";
-
- break;
-
- case kEntityAugust:
- if (getEvent(kEventAugustTalkCigar))
- return "XAUG6";
-
- if (getEvent(kEventAugustBringBriefcase))
- return "XAUG5";
-
- // Getting closer to Vienna...
- if (getState()->time > kTime2200500 && !getEvent(kEventAugustMerchandise))
- return "XAUG4A";
-
- if (getEvent(kEventAugustMerchandise))
- return "XAUG4";
-
- if (getEvent(kEventDinerAugust) || getEvent(kEventDinerAugustAlexeiBackground) || getEvent(kEventMeetAugustTylerCompartment)
- || getEvent(kEventMeetAugustTylerCompartmentBed) || getEvent(kEventMeetAugustHisCompartment) || getEvent(kEventMeetAugustHisCompartmentBed))
- return "XAUG3";
-
- if (getEvent(kEventAugustPresentAnnaFirstIntroduction))
- return "XAUG2";
-
- if (getProgress().eventMertensAugustWaiting)
- return "XAUG1";
-
- break;
-
- case kEntityTatiana:
- if (getEvent(kEventTatianaTylerCompartment))
- return "XTAT6";
-
- if (getEvent(kEventTatianaCompartmentStealEgg))
- return "XTAT5";
-
- if (getEvent(kEventTatianaGivePoem))
- return "XTAT3";
-
- if (getProgress().field_64)
- return "XTAT1";
-
- break;
-
- case kEntityVassili:
- if (getEvent(kEventCathFreePassengers))
- return "XVAS4";
-
- if (getEvent(kEventVassiliCompartmentStealEgg))
- return "XVAS3";
-
- if (getEvent(kEventAbbotIntroduction))
- return "XVAS2";
-
- if (getEvent(kEventVassiliSeizure))
- return "XVAS1A";
-
- if (getProgress().field_64)
- return "XVAS1";
-
- break;
-
- case kEntityAlexei:
- if (getProgress().field_88)
- return "XALX6";
-
- if (getProgress().field_8C)
- return "XALX5";
-
- if (getProgress().field_90)
- return "XALX4A";
-
- if (getProgress().field_68)
- return "XALX4";
-
- if (getEvent(kEventAlexeiSalonPoem))
- return "XALX3";
-
- if (getEvent(kEventAlexeiSalonVassili))
- return "XALX2";
-
- if (getEvent(kEventAlexeiDiner) || getEvent(kEventAlexeiDinerOriginalJacket))
- return "XALX1";
-
- break;
-
- case kEntityAbbot:
- if (getEvent(kEventAbbotDrinkDefuse))
- return "XABB4";
-
- if (getEvent(kEventAbbotInvitationDrink) || getEvent(kEventDefuseBomb))
- return "XABB3";
-
- if (getEvent(kEventAbbotWrongCompartment) || getEvent(kEventAbbotWrongCompartmentBed))
- return "XABB2";
-
- if (getEvent(kEventAbbotIntroduction))
- return "XABB1";
-
- break;
-
- case kEntityMilos:
- if (getEvent(kEventLocomotiveMilosDay) || getEvent(kEventLocomotiveMilosNight))
- return "XMIL5";
-
- if (getEvent(kEventMilosCompartmentVisitTyler) && (getProgress().chapter == kChapter3 || getProgress().chapter == kChapter4))
- return "XMIL4";
-
- if (getEvent(kEventMilosCorridorThanks) || getProgress().chapter == kChapter5)
- return "XMIL3";
-
- if (getEvent(kEventMilosCompartmentVisitAugust))
- return "XMIL2";
-
- if (getEvent(kEventMilosTylerCompartmentDefeat))
- return "XMIL1";
-
- break;
-
- case kEntityVesna:
- if (getProgress().field_94)
- return "XVES2";
-
- if (getProgress().field_98)
- return "XVES1";
-
- break;
-
- case kEntityKronos:
- if (getEvent(kEventKronosReturnBriefcase))
- return "XKRO6";
-
- if (getEvent(kEventKronosBringEggCeiling) || getEvent(kEventKronosBringEgg))
- return "XKRO5";
-
- if (getEvent(kEventKronosConversation) || getEvent(kEventKronosConversationFirebird)) {
- ObjectLocation location = getInventory()->get(kItemFirebird)->location;
- if (location != kObjectLocation6 && location != kObjectLocation5 && location != kObjectLocation2 && location != kObjectLocation1)
- return "XKRO4A";
- }
-
- if (getEvent(kEventKronosConversationFirebird))
- return "XKRO4";
-
- if (getEvent(kEventKronosConversation)) {
- if (!getEvent(kEventMilosCompartmentVisitAugust))
- return "XKRO3";
- else
- return "XKRO2";
- }
-
- if (getProgress().eventMertensKronosInvitation)
- return "XKRO1";
-
- break;
-
- case kEntityFrancois:
- if (getProgress().field_9C)
- return "XFRA3";
-
- if (getProgress().field_A0
- || getEvent(kEventFrancoisWhistle) || getEvent(kEventFrancoisWhistleD)
- || getEvent(kEventFrancoisWhistleNight) || getEvent(kEventFrancoisWhistleNightD))
- return "XFRA2";
-
- if (getState()->time > kTimeParisEpernay) // Between Paris and Epernay
- return "XFRA1";
-
- break;
-
- case kEntityMmeBoutarel:
- if (getProgress().field_A4)
- return "XMME4";
-
- if (getProgress().field_A8)
- return "XMME3";
-
- if (getProgress().field_A0)
- return "XMME2";
-
- if (getProgress().field_AC)
- return "XMME1";
-
- break;
-
- case kEntityBoutarel:
- if (getProgress().eventMetBoutarel)
- return "XMRB1";
-
- break;
-
- case kEntityRebecca:
- if (getProgress().field_B4)
- return "XREB1A";
-
- if (getProgress().field_B8)
- return "XREB1";
-
- break;
-
- case kEntitySophie:
- if (getProgress().field_B0)
- return "XSOP2";
-
- if (getProgress().field_BC)
- return "XSOP1B";
-
- if (getProgress().field_B4)
- return "XSOP1A";
-
- if (getProgress().field_B8)
- return "XSOP1";
-
- break;
-
- case kEntityMahmud:
- if (getProgress().field_C4)
- return "XMAH1";
-
- break;
-
- case kEntityYasmin:
- if (getProgress().eventMetYasmin)
- return "XHAR2";
-
- break;
-
- case kEntityHadija:
- if (getProgress().eventMetHadija)
- return "XHAR1";
-
- break;
-
- case kEntityAlouan:
- if (getProgress().field_DC)
- return "XHAR3";
-
- break;
-
- case kEntityGendarmes:
- if (getProgress().field_E0)
- return "XHAR4";
-
- break;
-
- case kEntityChapters:
- if (getEvent(kEventCathDream) || getEvent(kEventCathWakingUp))
- return "XTYL3";
-
- return "XTYL1";
-
- default:
- break;
- }
-
- return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Letters & Messages
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::readText(int id){
- if (!isBuffered(kEntityTables4))
- return;
-
- if (id < 0 || (id > 8 && id < 50) || id > 64)
- error("Sound::readText - attempting to use invalid id. Valid values [1;8] - [50;64], was %d", id);
-
- // Get proper message file (names are stored in sequence in the array but id is [1;8] - [50;64])
- const char *text = messages[id <= 8 ? id : id - 41];
-
- // Check if file is in cache for id [1;8]
- if (id <= 8)
- if (isBuffered(text))
- removeFromQueue(text);
-
- playSound(kEntityTables4, text, kFlagDefault);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Sound bites
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compartment) {
-
-#define PLAY_WARNING(index, sound1, sound2, sound3, sound4, sound5, sound6) { \
- if (_lastWarning[index] + 450 >= getState()->timeTicks) { \
- if (rnd(2)) \
- playSound(kEntityMertens, sound1, kFlagDefault); \
- else \
- playSound(kEntityMertens, rnd(2) ? sound2 : sound3, kFlagDefault); \
- } else { \
- if (rnd(2)) \
- playSound(kEntityMertens, sound4, kFlagDefault); \
- else \
- playSound(kEntityMertens, rnd(2) ? sound5 : sound6, kFlagDefault); \
- } \
- _lastWarning[index] = getState()->timeTicks; \
-}
-
- if (entity != kEntityMertens && entity != kEntityCoudert)
- return;
-
- //////////////////////////////////////////////////////////////////////////
- // Mertens
- if (entity == kEntityMertens) {
-
- switch (compartment) {
- default:
- break;
-
- case kObjectCompartment2:
- PLAY_WARNING(0, "Con1502A", "Con1500B", "Con1500C", "Con1502", "Con1500", "Con1500A");
- break;
-
- case kObjectCompartment3:
- PLAY_WARNING(1, "Con1501A", "Con1500B", "Con1500C", "Con1501", "Con1500", "Con1500A");
- break;
-
- case kObjectCompartment4:
- PLAY_WARNING(2, "Con1503", "Con1500B", "Con1500C", "Con1503", "Con1500", "Con1500A");
- break;
-
- case kObjectCompartment5:
- case kObjectCompartment6:
- case kObjectCompartment7:
- case kObjectCompartment8:
- ++_lastWarning[3];
-
- switch (_lastWarning[3]) {
- default:
- break;
-
- case 1:
- getSound()->playSound(kEntityMertens, "Con1503C", kFlagDefault);
- break;
-
- case 2:
- getSound()->playSound(kEntityMertens, rnd(2) ? "Con1503E" : "Con1503A", kFlagDefault);
- break;
-
- case 3:
- getSound()->playSound(kEntityMertens, rnd(2) ? "Con1503B" : "Con1503D", kFlagDefault);
- _lastWarning[3] = 0;
- break;
- }
- }
-
- return;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Coudert
- switch (compartment) {
- default:
- break;
-
- case kObjectCompartmentA:
- if (_lastWarning[4] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1508" : "Jac1508A", kFlagDefault);
- break;
-
- case kObjectCompartmentB:
- if (_lastWarning[5] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- if (getProgress().field_40 || (getState()->time > kTimeCityLinz && getState()->time < kTime2133000))
- getSound()->playSound(kEntityCoudert, "Jac1507A", kFlagDefault);
- else
- getSound()->playSound(kEntityCoudert, "Jac1507", kFlagDefault);
- break;
-
- case kObjectCompartmentC:
- if (_lastWarning[6] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- if (getProgress().chapter < kChapter3)
- getSound()->playSound(kEntityCoudert, "Jac1506", kFlagDefault);
- else
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1506A" : "Jac1506B", kFlagDefault);
- break;
-
- case kObjectCompartmentD:
- if (_lastWarning[7] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- getSound()->playSound(kEntityCoudert, "Jac1505", kFlagDefault);
- break;
-
- case kObjectCompartmentE:
- if (_lastWarning[8] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- if (getProgress().field_40 || (getState()->time > kTime2115000 && getState()->time < kTime2133000)) {
- getSound()->playSound(kEntityCoudert, "Jac1504B", kFlagDefault);
- break;
- }
-
- if (getEntities()->isInsideCompartment(kEntityRebecca, kCarRedSleeping, kPosition_4840))
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- else
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1504" : "Jac1504A", kFlagDefault);
- break;
-
- case kObjectCompartmentF:
- if (_lastWarning[9] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- if (getProgress().field_40 || (getState()->time > kTime2083500 && getState()->time < kTime2133000)) {
- getSound()->playSound(kEntityCoudert, "Jac1503B", kFlagDefault);
- break;
- }
-
- if (rnd(2) || getEntities()->isInsideCompartment(kEntityAnna, kCarRedSleeping, kPosition_4070))
- getSound()->playSound(kEntityCoudert, "Jac1503", kFlagDefault);
- else
- getSound()->playSound(kEntityCoudert, "Jac1503A", kFlagDefault);
- break;
-
- case kObjectCompartmentG:
- if (_lastWarning[10] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- if (rnd(2) || getEntities()->isInsideCompartment(kEntityMilos, kCarRedSleeping, kPosition_3050))
- getSound()->playSound(kEntityCoudert, "Jac1502", kFlagDefault);
- else
- getSound()->playSound(kEntityCoudert, "Jac1502A", kFlagDefault);
- break;
-
- case kObjectCompartmentH:
- if (_lastWarning[11] + 450 >= getState()->timeTicks) {
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- break;
- }
-
- if (getEntities()->isInsideCompartment(kEntityIvo, kCarRedSleeping, kPosition_2740))
- getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault);
- else
- getSound()->playSound(kEntityCoudert, "Jac1501", kFlagDefault);
- break;
- }
-
- // Update ticks (Compartments A - H are indexes 4 - 11)
- _lastWarning[compartment - 28] = getState()->timeTicks;
-}
-
-void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, FlagType flag) {
- if (isBuffered(entity) && entity != kEntityPlayer && entity != kEntityChapters && entity != kEntityTrain)
- return;
-
- if (entity2 == kEntityFrancois || entity2 == kEntityMax)
- return;
-
- if (entity == kEntityFrancois && getEntityData(kEntityFrancois)->field_4A3 != 30)
- return;
-
- if (flag == kFlagNone)
- flag = getSoundFlag(entity);
-
- switch (entity) {
- default:
- break;
-
- case kEntityAnna:
- playSound(kEntityPlayer, "ANN1107A", flag);
- break;
-
- case kEntityAugust:
- switch(rnd(4)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, "AUG1100A", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, "AUG1100B", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, "AUG1100C", flag);
- break;
-
- case 3:
- playSound(kEntityPlayer, "AUG1100D", flag);
- break;
- }
- break;
-
- case kEntityMertens:
- if (Entities::isFemale(entity2)) {
- playSound(kEntityPlayer, (rnd(2) ? "CON1111" : "CON1111A"), flag);
- } else {
- if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) {
- switch(rnd(3)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, "CON1110A", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, "CON1110C", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, "CON1110", flag);
- break;
- }
- } else {
- if (isNight()) {
- playSound(kEntityPlayer, (getProgress().field_18 == 2 ? "CON1110F" : "CON1110E"));
- } else {
- playSound(kEntityPlayer, "CON1110D");
- }
- }
- }
- break;
-
- case kEntityCoudert:
- if (Entities::isFemale(entity2)) {
- playSound(kEntityPlayer, "JAC1111D", flag);
- } else {
- if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) {
- switch(rnd(4)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, "JAC1111", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, "JAC1111A", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, "JAC1111B", flag);
- break;
-
- case 3:
- playSound(kEntityPlayer, "JAC1111C", flag);
- break;
- }
- } else {
- playSound(kEntityPlayer, "JAC1113B", flag);
- }
- }
- break;
-
- case kEntityPascale:
- playSound(kEntityPlayer, (rnd(2) ? "HDE1002" : "HED1002A"), flag);
- break;
-
- case kEntityServers0:
- case kEntityServers1:
- switch(rnd(3)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002" : "WAT1003", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002A" : "WAT1003A", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002B" : "WAT1003B", flag);
- break;
- }
- break;
-
- case kEntityVerges:
- if (Entities::isFemale(entity2)) {
- playSound(kEntityPlayer, (rnd(2) ? "TRA1113A" : "TRA1113B"));
- } else {
- playSound(kEntityPlayer, "TRA1112", flag);
- }
- break;
-
- case kEntityTatiana:
- playSound(kEntityPlayer, (rnd(2) ? "TAT1102A" : "TAT1102B"), flag);
- break;
-
- case kEntityAlexei:
- playSound(kEntityPlayer, (rnd(2) ? "ALX1099C" : "ALX1099D"), flag);
- break;
-
- case kEntityAbbot:
- if (Entities::isFemale(entity2)) {
- playSound(kEntityPlayer, "ABB3002C", flag);
- } else {
- switch(rnd(3)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, "ABB3002", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, "ABB3002A", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, "ABB3002B", flag);
- break;
- }
- }
- break;
-
- case kEntityVesna:
- switch(rnd(3)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, "VES1109A", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, "VES1109B", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, "VES1109C", flag);
- break;
- }
- break;
-
- case kEntityKahina:
- playSound(kEntityPlayer, (rnd(2) ? "KAH1001" : "KAH1001A"), flag);
- break;
-
- case kEntityFrancois:
- case kEntityMmeBoutarel:
- switch(rnd(4)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001" : "MME1103A", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001A" : "MME1103B", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001B" : "MME1103C", flag);
- break;
-
- case 3:
- playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001C" : "MME1103D", flag);
- break;
- }
- break;
-
- case kEntityBoutarel:
- playSound(kEntityPlayer, "MRB1104", flag);
- if (flag > 2)
- getProgress().eventMetBoutarel = true;
- break;
-
- case kEntityRebecca:
- playSound(kEntityPlayer, (rnd(2) ? "REB1106" : "REB110A"), flag);
- break;
-
- case kEntitySophie: {
- switch(rnd(3)) {
- default:
- break;
-
- case 0:
- playSound(kEntityPlayer, "SOP1105", flag);
- break;
-
- case 1:
- playSound(kEntityPlayer, Entities::isFemale(entity2) ? "SOP1105C" : "SOP1105A", flag);
- break;
-
- case 2:
- playSound(kEntityPlayer, Entities::isFemale(entity2) ? "SOP1105D" : "SOP1105B", flag);
- break;
- }
- break;
- }
-
- case kEntityMahmud:
- playSound(kEntityPlayer, "MAH1101", flag);
- break;
-
- case kEntityYasmin:
- playSound(kEntityPlayer, "HAR1002", flag);
- if (flag > 2)
- getProgress().eventMetYasmin = true;
- break;
-
- case kEntityHadija:
- playSound(kEntityPlayer, (rnd(2) ? "HAR1001" : "HAR1001A"), flag);
- if (flag > 2)
- getProgress().eventMetHadija = true;
- break;
-
- case kEntityAlouan:
- playSound(kEntityPlayer, "HAR1004", flag);
- break;
- }
-}
-
-void SoundManager::excuseMeCath() {
- switch(rnd(3)) {
- default:
- playSound(kEntityPlayer, "CAT1126B");
- break;
-
- case 1:
- playSound(kEntityPlayer, "CAT1126C");
- break;
-
- case 2:
- playSound(kEntityPlayer, "CAT1126D");
- break;
- }
-}
-
-const char *SoundManager::justCheckingCath() const {
- switch(rnd(4)) {
- default:
- break;
-
- case 0:
- return "CAT5001";
-
- case 1:
- return "CAT5001A";
-
- case 2:
- return "CAT5001B";
-
- case 3:
- return "CAT5001C";
- }
-
- return "CAT5001";
-}
-
-const char *SoundManager::wrongDoorCath() const {
- switch(rnd(5)) {
- default:
- break;
-
- case 0:
- return "CAT1125";
-
- case 1:
- return "CAT1125A";
-
- case 2:
- return "CAT1125B";
-
- case 3:
- return "CAT1125C";
-
- case 4:
- return "CAT1125D";
- }
-
- return "CAT1125";
-}
-
-const char *SoundManager::justAMinuteCath() const {
- switch(rnd(3)) {
- default:
- break;
-
- case 0:
- return "CAT1520";
-
- case 1:
- return "CAT1521";
-
- case 2:
- return "CAT1125"; // ?? is this a bug in the original?
- }
-
- return "CAT1520";
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Sound flags
-//////////////////////////////////////////////////////////////////////////
-SoundManager::FlagType SoundManager::getSoundFlag(EntityIndex entity) const {
- if (entity == kEntityPlayer)
- return kFlagDefault;
-
- if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car)
- return kFlagNone;
-
- // Compute sound value
- FlagType ret = kFlag2;
-
- // Get default value if valid
- int index = ABS(getEntityData(entity)->entityPosition - getEntityData(kEntityPlayer)->entityPosition) / 230;
- if (index < 32)
- ret = soundFlags[index];
-
- if (getEntityData(entity)->location == kLocationOutsideTrain) {
- if (getEntityData(entity)->car != kCarKronos
- && !getEntities()->isOutsideAlexeiWindow()
- && !getEntities()->isOutsideAnnaWindow())
- return kFlagNone;
-
- return (FlagType)(ret / 6);
- }
-
- switch (getEntityData(entity)->car) {
- default:
- break;
-
- case kCarKronos:
- if (getEntities()->isInKronosSalon(entity) != getEntities()->isInKronosSalon(kEntityPlayer))
- ret = (FlagType)(ret * 2);
- break;
-
- case kCarGreenSleeping:
- case kCarRedSleeping:
- if (getEntities()->isInGreenCarEntrance(kEntityPlayer) && !getEntities()->isInKronosSalon(entity))
- ret = (FlagType)(ret * 2);
-
- if (getEntityData(kEntityPlayer)->location
- && (getEntityData(entity)->entityPosition != kPosition_1 || !getEntities()->isDistanceBetweenEntities(kEntityPlayer, entity, 400)))
- ret = (FlagType)(ret * 2);
- break;
-
- case kCarRestaurant:
- if (getEntities()->isInSalon(entity) == getEntities()->isInSalon(kEntityPlayer)
- && (getEntities()->isInRestaurant(entity) != getEntities()->isInRestaurant(kEntityPlayer)))
- ret = (FlagType)(ret * 2);
- else
- ret = (FlagType)(ret * 4);
- break;
- }
-
- return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Subtitles
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::updateSubtitles() {
- Common::StackLock locker(_mutex);
-
- uint32 index = 0;
- SubtitleEntry *subtitle = NULL;
-
- for (Common::List<SubtitleEntry *>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
- uint32 current_index = 0;
- SoundEntry *soundEntry = (*i)->sound;
- SoundStatus status = (SoundStatus)soundEntry->status.status;
-
- if (!(status & kSoundStatus_40)
- || status & 0x180
- || soundEntry->time == 0
- || (status & 0x1F) < 6
- || ((getFlags()->nis & 0x8000) && soundEntry->field_4C < 90)) {
- current_index = 0;
- } else {
- current_index = soundEntry->field_4C + (status & 0x1F);
-
- if (_currentSubtitle == (*i))
- current_index += 4;
- }
-
- if (index < current_index) {
- index = current_index;
- subtitle = (*i);
- }
- }
-
- if (_currentSubtitle == subtitle) {
- if (subtitle)
- setupSubtitleAndDraw(subtitle);
-
- return;
- }
-
- if (_drawSubtitles & 1)
- drawSubtitleOnScreen(subtitle);
-
- if (subtitle) {
- loadSubtitleData(subtitle);
- setupSubtitleAndDraw(subtitle);
- }
-}
-
-void SoundManager::showSubtitle(SoundEntry *entry, Common::String filename) {
- entry->subtitle = loadSubtitle(filename, entry);
-
- if (entry->subtitle->status.status2 & 4) {
- drawSubtitle(entry->subtitle);
- SAFE_DELETE(entry->subtitle);
- } else {
- entry->status.status |= kSoundStatus_20000;
- }
-}
-
-SoundManager::SubtitleEntry *SoundManager::loadSubtitle(Common::String filename, SoundEntry *soundEntry) {
- SubtitleEntry *entry = new SubtitleEntry();
- _subtitles.push_back(entry);
-
- // Set sound entry and filename
- entry->filename = filename + ".SBE";
- entry->sound = soundEntry;
-
- // Load subtitle data
- if (_engine->getResourceManager()->hasFile(filename)) {
- if (_drawSubtitles & 2)
- return entry;
-
- loadSubtitleData(entry);
- } else {
- entry->status.status = kSoundStatus_400;
- }
-
- return entry;
-}
-
-void SoundManager::loadSubtitleData(SubtitleEntry * entry) {
- entry->data = new SubtitleManager(_engine->getFont());
- entry->data->load(getArchive(entry->filename));
-
- _drawSubtitles |= 2;
- _currentSubtitle = entry;
-}
-
-void SoundManager::setupSubtitleAndDraw(SubtitleEntry *subtitle) {
- if (!subtitle->data) {
- subtitle->data = new SubtitleManager(_engine->getFont());
- subtitle->data->load(getArchive(subtitle->filename));
- }
-
- if (subtitle->data->getMaxTime() > subtitle->sound->time) {
- subtitle->status.status = kSoundStatus_400;
- } else {
- subtitle->data->setTime((uint16)subtitle->sound->time);
-
- if (_drawSubtitles & 1)
- drawSubtitleOnScreen(subtitle);
- }
-
- _currentSubtitle = subtitle;
-}
-
-void SoundManager::drawSubtitle(SubtitleEntry *subtitle) {
- // Remove subtitle from queue
- _subtitles.remove(subtitle);
-
- if (subtitle == _currentSubtitle) {
- drawSubtitleOnScreen(subtitle);
-
- _currentSubtitle = NULL;
- _drawSubtitles = 0;
- }
-}
-
-void SoundManager::drawSubtitleOnScreen(SubtitleEntry *subtitle) {
- if (!subtitle)
- error("SoundManager::drawSubtitleOnScreen: Invalid subtitle entry!");
-
- _drawSubtitles &= ~1;
-
- if (subtitle->data == NULL)
- return;
-
- if (_drawSubtitles & 1)
- _engine->getGraphicsManager()->draw(subtitle->data, GraphicsManager::kBackgroundOverlay);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Misc
-//////////////////////////////////////////////////////////////////////////
-void SoundManager::playLoopingSound() {
- warning("SoundManager::playLoopingSound: not implemented!");
-}
-
-void SoundManager::stopAllSound() {
- Common::StackLock locker(_mutex);
-
- for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
- (*i)->soundStream->stop();
-}
-
-} // End of namespace LastExpress
diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h
deleted file mode 100644
index ddafc21829..0000000000
--- a/engines/lastexpress/game/sound.h
+++ /dev/null
@@ -1,389 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef LASTEXPRESS_SOUND_H
-#define LASTEXPRESS_SOUND_H
-
-/*
-
- Sound entry: 68 bytes (this is what appears in the savegames)
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - entity
- uint32 {4} - ??
- uint32 {4} - ??
- char {16} - name 1
- char {16} - name 2
-
- Sound queue entry: 120 bytes
- uint16 {2} - status
- byte {1} - ??
- byte {1} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - file data pointer
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - archive structure pointer
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - ??
- uint32 {4} - entity
- uint32 {4} - ??
- uint32 {4} - ??
- char {16} - name 1
- char {16} - name 2
- uint32 {4} - pointer to next entry in the queue
- uint32 {4} - subtitle data pointer
-
-*/
-
-#include "lastexpress/data/snd.h"
-#include "lastexpress/data/subtitle.h"
-
-#include "lastexpress/shared.h"
-
-#include "lastexpress/helpers.h"
-
-#include "common/list.h"
-#include "common/mutex.h"
-#include "common/system.h"
-#include "common/serializer.h"
-
-namespace LastExpress {
-
-class LastExpressEngine;
-class SubtitleManager;
-
-class SoundManager : Common::Serializable {
-public:
- enum SoundType {
- kSoundTypeNone = 0,
- kSoundType1,
- kSoundType2,
- kSoundType3,
- kSoundType4,
- kSoundType5,
- kSoundType6,
- kSoundType7,
- kSoundType8,
- kSoundType9,
- kSoundType10,
- kSoundType11,
- kSoundType12,
- kSoundType13,
- kSoundType14,
- kSoundType15,
- kSoundType16
- };
-
- enum FlagType {
- kFlagInvalid = -1,
- kFlagNone = 0x0,
- kFlag2 = 0x2,
- kFlag3 = 0x3,
- kFlag4 = 0x4,
- kFlag5 = 0x5,
- kFlag6 = 0x6,
- kFlag7 = 0x7,
- kFlag8 = 0x8,
- kFlag9 = 0x9,
- kFlag10 = 0xA,
- kFlag11 = 0xB,
- kFlag12 = 0xC,
- kFlag13 = 0xD,
- kFlag14 = 0xE,
- kFlag15 = 0xF,
- kFlagDefault = 0x10,
-
- kFlagType1_2 = 0x1000000,
- kFlagSteam = 0x1001007,
- kFlagType13 = 0x3000000,
- kFlagMenuClock = 0x3080010,
- kFlagType7 = 0x4000000,
- kFlagType11 = 0x5000000,
- kFlagMusic = 0x5000010,
- kFlagType3 = 0x6000000,
- kFlagLoop = 0x6001008,
- kFlagType9 = 0x7000000
- };
-
- SoundManager(LastExpressEngine *engine);
- ~SoundManager();
-
- // Timer
- void handleTimer();
-
- // State
- void resetState() { _state |= kSoundType1; }
-
- // Sound queue
- void updateQueue();
- void resetQueue(SoundType type1, SoundType type2 = kSoundTypeNone);
- void clearQueue();
-
- // Subtitles
- void updateSubtitles();
-
- // Entry
- bool isBuffered(Common::String filename, bool testForEntity = false);
- bool isBuffered(EntityIndex entity);
- void setupEntry(SoundType type, EntityIndex index);
- void processEntry(EntityIndex entity);
- void processEntry(SoundType type);
- void processEntry(Common::String filename);
- void processEntries();
- void removeFromQueue(Common::String filename);
- void removeFromQueue(EntityIndex entity);
- uint32 getEntryTime(EntityIndex index);
-
- // Misc
- void unknownFunction4();
- void clearStatus();
-
- // Sound playing
- void playSound(EntityIndex entity, Common::String filename, FlagType flag = kFlagInvalid, byte a4 = 0);
- bool playSoundWithSubtitles(Common::String filename, FlagType flag, EntityIndex entity, byte a4 = 0);
- void playSoundEvent(EntityIndex entity, byte action, byte a3 = 0);
- void playDialog(EntityIndex entity, EntityIndex entityDialog, FlagType flag, byte a4);
- void playSteam(CityIndex index);
- void playFightSound(byte action, byte a4);
- void playLocomotiveSound();
- void playWarningCompartment(EntityIndex entity, ObjectIndex compartment);
-
- // Dialog & Letters
- void readText(int id);
- const char *getDialogName(EntityIndex entity) const;
-
- // Sound bites
- void excuseMe(EntityIndex entity, EntityIndex entity2 = kEntityPlayer, FlagType flag = kFlagNone);
- void excuseMeCath();
- const char *justCheckingCath() const;
- const char *wrongDoorCath() const;
- const char *justAMinuteCath() const;
-
- // FLags
- SoundManager::FlagType getSoundFlag(EntityIndex index) const;
-
- // Debug
- void stopAllSound();
-
- // Serializable
- void saveLoadWithSerializer(Common::Serializer &ser);
- uint32 count();
-
-private:
- typedef int32 *SoundBuffer;
-
- enum SoundStatus {
- kSoundStatus_20 = 0x20,
- kSoundStatus_40 = 0x40,
- kSoundStatus_180 = 0x180,
- kSoundStatusRemoved = 0x200,
- kSoundStatus_400 = 0x400,
-
- kSoundStatus_8000 = 0x8000,
- kSoundStatus_20000 = 0x20000,
- kSoundStatus_100000 = 0x100000,
- kSoundStatus_40000000 = 0x40000000,
-
- kSoundStatusClear0 = 0x10,
- kSoundStatusClear1 = 0x1F,
- kSoundStatusClear2 = 0x80,
- kSoundStatusClear3 = 0x200,
- kSoundStatusClear4 = 0x800,
- kSoundStatusClearAll = 0xFFFFFFE0
- };
-
- enum SoundState {
- kSoundState0 = 0,
- kSoundState1 = 1,
- kSoundState2 = 2
- };
-
- union SoundStatusUnion {
- uint32 status;
- byte status1;
- byte status2;
- byte status3;
- byte status4;
-
- SoundStatusUnion() {
- status = 0;
- }
- };
-
- struct SubtitleEntry;
-
- struct SoundEntry {
- SoundStatusUnion status;
- SoundType type; // int
- //int field_8;
- //int field_C;
- int processedFrameCount;
- void *soundData;
- //int field_18;
- int field_1C;
- uint32 time;
- //int field_24;
- //int field_28;
- Common::SeekableReadStream *stream; // int
- //int field_30;
- int field_34;
- int field_38;
- int field_3C;
- int field_40;
- EntityIndex entity;
- int field_48;
- uint32 field_4C;
- Common::String name1; //char[16];
- Common::String name2; //char[16];
- //int next; // offset to the next structure in the list (not used)
- SubtitleEntry *subtitle;
-
- // Sound stream
- StreamedSound *soundStream;
-
- SoundEntry() {
- status.status = 0;
- type = kSoundTypeNone;
-
- processedFrameCount = 0;
- soundData = NULL;
-
- field_1C = 0;
- time = 0;
-
- stream = NULL;
-
- field_34 = 0;
- field_38 = 0;
- field_3C = 0;
- field_40 = 0;
- entity = kEntityPlayer;
- field_48 = 0;
- field_4C = 0;
-
- subtitle = NULL;
-
- soundStream = NULL;
- }
-
- ~SoundEntry() {
- // Entries that have been queued would have their streamed disposed automatically
- if (!soundStream)
- SAFE_DELETE(stream);
-
- delete soundStream;
- }
- };
-
- struct SubtitleEntry {
- Common::String filename;
- SoundStatusUnion status;
- SoundEntry *sound;
- SubtitleManager *data;
-
- SubtitleEntry() {
- status.status = 0;
- sound = NULL;
- data = NULL;
- }
-
- ~SubtitleEntry() {
- SAFE_DELETE(data);
- }
- };
-
- // Engine
- LastExpressEngine *_engine;
-
- // State flag
- int _state;
- SoundType _currentType;
-
- Common::Mutex _mutex;
-
- // Unknown data
- uint32 _data0;
- uint32 _data1;
- uint32 _data2;
- uint32 _flag;
-
- // Filters
- int32 _buffer[2940]; ///< Static sound buffer
-
- // Compartment warnings by Mertens or Coudert
- uint32 _lastWarning[12];
-
- // Looping sound
- void playLoopingSound();
-
- // Sound entries
- Common::List<SoundEntry *> _soundList; ///< List of all sound entries
- Common::List<SoundEntry *> _soundCache; ///< List of entries with a data buffer
- void *_soundCacheData;
-
- SoundEntry *getEntry(EntityIndex index);
- SoundEntry *getEntry(Common::String name);
- SoundEntry *getEntry(SoundType type);
-
- void setupEntry(SoundEntry *entry, Common::String name, FlagType flag, int a4);
- void setEntryType(SoundEntry *entry, FlagType flag);
- void setEntryStatus(SoundEntry *entry, FlagType flag) const;
- void setInCache(SoundEntry *entry);
- bool setupCache(SoundEntry *entry);
- void removeFromCache(SoundEntry *entry);
- void loadSoundData(SoundEntry *entry, Common::String name);
-
- void updateEntry(SoundEntry *entry, uint value) const;
- void updateEntryState(SoundEntry *entry) const;
- void resetEntry(SoundEntry *entry) const;
- void removeEntry(SoundEntry *entry);
-
- // Subtitles
- int _drawSubtitles;
- Common::List<SubtitleEntry *> _subtitles;
- SubtitleEntry *_currentSubtitle;
- void showSubtitle(SoundEntry *entry, Common::String filename);
- SubtitleEntry *loadSubtitle(Common::String filename, SoundEntry *soundEntry);
- void loadSubtitleData(SubtitleEntry * entry);
- void setupSubtitleAndDraw(SubtitleEntry *subtitle);
- void drawSubtitle(SubtitleEntry *subtitle);
- void drawSubtitleOnScreen(SubtitleEntry *subtitle);
-
- // Sound filter
- void applyFilter(SoundEntry *entry, SoundBuffer buffer);
-};
-
-} // End of namespace LastExpress
-
-#endif // LASTEXPRESS_SOUND_H
diff --git a/engines/lastexpress/game/state.cpp b/engines/lastexpress/game/state.cpp
index 0cf2ddba40..f3fd9720b1 100644
--- a/engines/lastexpress/game/state.cpp
+++ b/engines/lastexpress/game/state.cpp
@@ -57,7 +57,7 @@ bool State::isNightTime() const {
void State::getHourMinutes(uint32 time, uint8 *hours, uint8 *minutes) {
if (hours == NULL || minutes == NULL)
- error("State::getHourMinutes: invalid parameters passed!");
+ error("[State::getHourMinutes] Invalid parameters passed");
*hours = (uint8)((time % 1296000) / 54000);
*minutes = (uint8)((time % 54000) / 900);
diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h
index 8f71e7d424..c937fdce9f 100644
--- a/engines/lastexpress/game/state.h
+++ b/engines/lastexpress/game/state.h
@@ -325,7 +325,7 @@ public:
switch (index) {
default:
- error("GameProgress::isEqual: invalid index value (was: %d, max:127)", index);
+ error("[GameProgress::getValueName] Invalid index value (was: %d, max:127)", index);
break;
EXPOSE_VALUE(0, field_0);