aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLe Philousophe2019-05-20 20:56:35 +0200
committerEugene Sandulenko2019-06-01 22:43:48 +0200
commit01f6e2db12aa980aa316b80bc0e4b29e58cf2b5e (patch)
treedf1db24186d6e4027c01cc4f3c954ac139155f66
parentedf2fdb12880b2b96beb3a753da4c1ad44b0bbf4 (diff)
downloadscummvm-rg350-01f6e2db12aa980aa316b80bc0e4b29e58cf2b5e.tar.gz
scummvm-rg350-01f6e2db12aa980aa316b80bc0e4b29e58cf2b5e.tar.bz2
scummvm-rg350-01f6e2db12aa980aa316b80bc0e4b29e58cf2b5e.zip
CRYOMNI3D: Implement countdown
-rw-r--r--engines/cryomni3d/fixed_image.cpp2
-rw-r--r--engines/cryomni3d/versailles/engine.cpp37
-rw-r--r--engines/cryomni3d/versailles/engine.h18
-rw-r--r--engines/cryomni3d/versailles/logic.cpp80
-rw-r--r--engines/cryomni3d/versailles/menus.cpp3
-rw-r--r--engines/cryomni3d/versailles/saveload.cpp8
-rw-r--r--engines/cryomni3d/versailles/toolbar.cpp5
7 files changed, 130 insertions, 23 deletions
diff --git a/engines/cryomni3d/fixed_image.cpp b/engines/cryomni3d/fixed_image.cpp
index f4e900f333..f5f354aa0b 100644
--- a/engines/cryomni3d/fixed_image.cpp
+++ b/engines/cryomni3d/fixed_image.cpp
@@ -191,7 +191,6 @@ void ZonFixedImage::manage() {
// Force poll events even when we must refresh the cursor
if (!_engine.pollEvents() && !_refreshCursor) {
g_system->updateScreen();
- // TODO: countdown even when no events
return;
}
_refreshCursor = false;
@@ -266,7 +265,6 @@ void ZonFixedImage::manage() {
}
- // TODO: handle countdown
g_system->updateScreen();
}
diff --git a/engines/cryomni3d/versailles/engine.cpp b/engines/cryomni3d/versailles/engine.cpp
index 124f638108..fd88f8efc1 100644
--- a/engines/cryomni3d/versailles/engine.cpp
+++ b/engines/cryomni3d/versailles/engine.cpp
@@ -54,7 +54,8 @@ CryOmni3DEngine_Versailles::CryOmni3DEngine_Versailles(OSystem *syst,
_currentPlace(nullptr), _currentWarpImage(nullptr), _fixedImage(nullptr),
_transitionAnimateWarp(true), _forceRedrawWarp(false), _forcePaletteUpdate(false),
_fadedPalette(false), _loadedSave(-1), _dialogsMan(this),
- _musicVolumeFactor(1.), _musicCurrentFile(nullptr) {
+ _musicVolumeFactor(1.), _musicCurrentFile(nullptr),
+ _countingDown(false), _countdownNextEvent(0) {
}
CryOmni3DEngine_Versailles::~CryOmni3DEngine_Versailles() {
@@ -127,6 +128,8 @@ Common::Error CryOmni3DEngine_Versailles::run() {
initDocPeopleRecord();
_docManager.init(&_sprites, &_fontManager, &_messages, this);
+ _countdownSurface.create(40, 15, Graphics::PixelFormat::createFormatCLUT8());
+
initGraphics(640, 480);
setMousePos(Common::Point(320, 200));
@@ -609,7 +612,7 @@ void CryOmni3DEngine_Versailles::changeLevel(int level) {
it++) {
*it = 0;
}
- // TODO: countdown
+ initCountdown();
_inventory.clear();
} else if (_currentLevel <= 6) {
// TODO: remove this when we implemented all levels
@@ -1166,7 +1169,7 @@ int CryOmni3DEngine_Versailles::handleWarp() {
const Graphics::Surface *result = _omni3dMan.getSurface();
g_system->copyRectToScreen(result->getPixels(), result->pitch, 0, 0, result->w, result->h);
if (!exit) {
- // TODO: countdown
+ drawCountdown();
g_system->updateScreen();
if (firstDraw && _fadedPalette) {
fadeInPalette(_mainPalette);
@@ -1179,14 +1182,13 @@ int CryOmni3DEngine_Versailles::handleWarp() {
const Graphics::Surface *result = _omni3dMan.getSurface();
g_system->copyRectToScreen(result->getPixels(), result->pitch, 0, 0, result->w, result->h);
if (!exit) {
- // TODO: countdown
+ drawCountdown();
g_system->updateScreen();
}
- // TODO: cursorUseZones
moving = false;
} else {
if (!exit) {
- // TODO: countdown
+ // Countdown is updated as soon as it changes
g_system->updateScreen();
}
}
@@ -1203,6 +1205,11 @@ bool CryOmni3DEngine_Versailles::handleWarpMouse(unsigned int *actionId,
getNextKey().keycode == Common::KEYCODE_SPACE) {
// Prepare background using alpha
const Graphics::Surface *original = _omni3dMan.getSurface();
+
+ // Display surface with countdown before showing toolbar just to be sure
+ g_system->copyRectToScreen(original->getPixels(), original->pitch, 0, 0, original->w, original->h);
+ drawCountdown();
+
bool mustRedraw = displayToolbar(original);
// Don't redraw if we abort game
if (_abortCommand != AbortNoAbort) {
@@ -1216,7 +1223,16 @@ bool CryOmni3DEngine_Versailles::handleWarpMouse(unsigned int *actionId,
return false;
}
- // TODO: countdown
+ if (countDown()) {
+ // Time has changed: need redraw
+ // Don't redraw if we abort game
+ if (_abortCommand != AbortNoAbort) {
+ return true;
+ }
+
+ _forceRedrawWarp = true;
+ redrawWarp();
+ }
const Object *selectedObj = _inventory.selectedObject();
if (selectedObj) {
@@ -1323,7 +1339,7 @@ void CryOmni3DEngine_Versailles::animateWarpTransition(const Transition *transit
const Graphics::Surface *result = _omni3dMan.getSurface();
g_system->copyRectToScreen(result->getPixels(), result->pitch, 0, 0, result->w, result->h);
- // TODO: countdown
+ drawCountdown();
g_system->updateScreen();
if (fabs(oldDeltaAlpha - deltaAlpha) < 0.001 && fabs(oldDeltaBeta - deltaBeta) < 0.001) {
@@ -1344,7 +1360,7 @@ void CryOmni3DEngine_Versailles::redrawWarp() {
if (_forceRedrawWarp) {
const Graphics::Surface *result = _omni3dMan.getSurface();
g_system->copyRectToScreen(result->getPixels(), result->pitch, 0, 0, result->w, result->h);
- // TODO: countdown
+ drawCountdown();
g_system->updateScreen();
_forceRedrawWarp = false;
}
@@ -1534,7 +1550,8 @@ void CryOmni3DEngine_Versailles::playInGameVideo(const Common::String &filename,
g_system->showMouse(false);
lockPalette(0, 241);
// Videos are like music because if you mute music in game it will mute videos soundtracks
- playHNM(filename, Audio::Mixer::kMusicSoundType);
+ playHNM(filename, Audio::Mixer::kMusicSoundType, nullptr,
+ static_cast<HNMCallback>(&CryOmni3DEngine_Versailles::drawCountdownVideo));
clearKeys();
unlockPalette();
if (restoreCursorPalette) {
diff --git a/engines/cryomni3d/versailles/engine.h b/engines/cryomni3d/versailles/engine.h
index e958e3ccb5..abfb1a4026 100644
--- a/engines/cryomni3d/versailles/engine.h
+++ b/engines/cryomni3d/versailles/engine.h
@@ -155,7 +155,7 @@ struct GameVariables {
kUsedVaubanBlueprint2, // OK // 40
kSeenMemorandum, // OK
kCollectScissors, // OK
- kSavedCountdown, // TODO: calculate it in real time
+ kSavedCountdown, // OK
kMax
};
};
@@ -309,7 +309,7 @@ private:
bool canVisit() const;
Common::String getSaveFileName(bool visit, unsigned int saveNum) const;
void getSavesList(bool visit, Common::Array<Common::String> &saveNames);
- void saveGame(bool visit, unsigned int saveNum, const Common::String &saveName) const;
+ void saveGame(bool visit, unsigned int saveNum, const Common::String &saveName);
bool loadGame(bool visit, unsigned int saveNum);
void animateCursor(const Object *object);
@@ -397,6 +397,20 @@ private:
static const MsgBoxParameters kFixedimageMsgBoxParameters;
static const FixedImageConfiguration kFixedImageConfiguration;
+ // Countdown
+ void initCountdown();
+ void syncCountdown();
+ inline bool countDown() { if (_countingDown) { return doCountDown(); } else { return false; } }
+ inline void drawCountdown(Graphics::ManagedSurface *surface = nullptr) { if (_countingDown) { doDrawCountdown(surface); } }
+ void drawCountdownVideo(unsigned int frameNum) { drawCountdown(); }
+
+ bool _countingDown;
+ unsigned int _countdownNextEvent;
+ char _countdownValue[6];
+ Graphics::ManagedSurface _countdownSurface;
+ bool doCountDown();
+ void doDrawCountdown(Graphics::ManagedSurface *surface);
+
// Objects
template<unsigned int ID>
void genericDisplayObject();
diff --git a/engines/cryomni3d/versailles/logic.cpp b/engines/cryomni3d/versailles/logic.cpp
index e65d5a62dc..af20e9c3af 100644
--- a/engines/cryomni3d/versailles/logic.cpp
+++ b/engines/cryomni3d/versailles/logic.cpp
@@ -4085,5 +4085,85 @@ FILTER_EVENT(6, 19) {
#undef FILTER_EVENT
#undef INIT_PLACE
+// Countdown
+
+void CryOmni3DEngine_Versailles::initCountdown() {
+ strcpy(_countdownValue, "05:00");
+ if (_gameVariables[GameVariables::kSavedCountdown]) {
+ unsigned int counter = _gameVariables[GameVariables::kSavedCountdown];
+ _countdownValue[4] = counter;
+ counter >>= 8;
+ _countdownValue[3] = counter;
+ counter >>= 8;
+ _countdownValue[1] = counter;
+ counter >>= 8;
+ _countdownValue[0] = counter;
+ }
+}
+
+void CryOmni3DEngine_Versailles::syncCountdown() {
+ unsigned int counter = 0;
+ counter |= _countdownValue[0];
+ counter <<= 8;
+ counter |= _countdownValue[1];
+ counter <<= 8;
+ counter |= _countdownValue[3];
+ counter <<= 8;
+ counter |= _countdownValue[4];
+ _gameVariables[GameVariables::kSavedCountdown] = counter;
+}
+
+bool CryOmni3DEngine_Versailles::doCountDown() {
+ if (g_system->getMillis() > _countdownNextEvent) {
+ _countdownNextEvent = g_system->getMillis() + 1000;
+ // Decrement countdown
+ _countdownValue[4]--;
+ if (_countdownValue[4] < '0') {
+ _countdownValue[4] = '9';
+ _countdownValue[3]--;
+ if (_countdownValue[3] < '0') {
+ _countdownValue[3] = '5';
+ _countdownValue[1]--;
+ if (_countdownValue[1] < '0') {
+ _countdownValue[1] = '9';
+ _countdownValue[0]--;
+ if (_countdownValue[0] < '0') {
+ // Finished!
+ _countingDown = false;
+ playTransitionEndLevel(8);
+ _abortCommand = AbortGameOver;
+ }
+ }
+ }
+ }
+
+ // Redraw surface
+ _countdownSurface.clear(0);
+ _fontManager.setCurrentFont(3);
+ _fontManager.setTransparentBackground(true);
+ _fontManager.setForeColor(241);
+ _fontManager.setLineHeight(14);
+ _fontManager.setSpaceWidth(0);
+ _fontManager.setCharSpacing(1);
+ _fontManager.setSurface(&_countdownSurface);
+
+ _fontManager.displayStr(0, 2, _countdownValue);
+
+ // Surface changed: need redraw
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void CryOmni3DEngine_Versailles::doDrawCountdown(Graphics::ManagedSurface *surface) {
+ if (surface) {
+ surface->blitFrom(_countdownSurface, Common::Point(600, 0));
+ } else {
+ g_system->copyRectToScreen(_countdownSurface.getPixels(), _countdownSurface.pitch, 600, 0,
+ _countdownSurface.w, _countdownSurface.h);
+ }
+}
+
} // End of namespace Versailles
} // End of namespace CryOmni3D
diff --git a/engines/cryomni3d/versailles/menus.cpp b/engines/cryomni3d/versailles/menus.cpp
index f052cd7165..9a4447876c 100644
--- a/engines/cryomni3d/versailles/menus.cpp
+++ b/engines/cryomni3d/versailles/menus.cpp
@@ -882,7 +882,8 @@ void CryOmni3DEngine_Versailles::displayMessageBox(const MsgBoxParameters &param
rct.grow(-6);
_fontManager.setupBlock(rct);
_fontManager.displayBlockText(msg);
- // TODO: countdown
+
+ drawCountdown(&dstSurface);
g_system->copyRectToScreen(dstSurface.getPixels(), dstSurface.pitch, 0, 0,
dstSurface.w, dstSurface.h);
diff --git a/engines/cryomni3d/versailles/saveload.cpp b/engines/cryomni3d/versailles/saveload.cpp
index a5ea1a1beb..752cb761e4 100644
--- a/engines/cryomni3d/versailles/saveload.cpp
+++ b/engines/cryomni3d/versailles/saveload.cpp
@@ -114,7 +114,7 @@ void CryOmni3DEngine_Versailles::getSavesList(bool visit, Common::StringArray &s
}
void CryOmni3DEngine_Versailles::saveGame(bool visit, unsigned int saveNum,
- const Common::String &saveName) const {
+ const Common::String &saveName) {
if (visit && saveNum == 1) {
error("Can't erase bootstrap visit");
}
@@ -133,6 +133,9 @@ void CryOmni3DEngine_Versailles::saveGame(bool visit, unsigned int saveNum,
return;
}
+ // Sync countdown to game variable before saving it to file
+ syncCountdown();
+
// Write save name
char saveNameC[SAVE_DESCRIPTION_LEN];
memset(saveNameC, 0, sizeof(saveNameC));
@@ -292,6 +295,7 @@ bool CryOmni3DEngine_Versailles::loadGame(bool visit, unsigned int saveNum) {
if (_gameVariables[GameVariables::kCurrentTime] == 0) {
_gameVariables[GameVariables::kCurrentTime] = 1;
}
+ initCountdown();
// Everything has been loaded, setup new level
// We will set places states and warp coordinates just after that to avoid them from being reset
@@ -307,8 +311,6 @@ bool CryOmni3DEngine_Versailles::loadGame(bool visit, unsigned int saveNum) {
placeIt->state = placesStates[i];
}
- // TODO: countdown
-
return true;
}
diff --git a/engines/cryomni3d/versailles/toolbar.cpp b/engines/cryomni3d/versailles/toolbar.cpp
index e0168e29cc..2f9426beac 100644
--- a/engines/cryomni3d/versailles/toolbar.cpp
+++ b/engines/cryomni3d/versailles/toolbar.cpp
@@ -410,9 +410,6 @@ bool Toolbar::displayToolbar(const Graphics::Surface *original) {
_bgSurface.w, original->h));
_engine->makeTranslucent(_bgSurface, subset);
- // Draw the original surface on the surface to use for toolbar
- g_system->copyRectToScreen(original->getPixels(), original->pitch, 0, 0, original->w, original->h);
-
// WORKAROUND: Reset the inventory status at init to let sprites highlighted until toolbar is hidden
_inventorySelected = -1;
_inventoryHovered = -1;
@@ -479,8 +476,6 @@ void Toolbar::handleToolbarEvents(const Graphics::Surface *original) {
// No need of original surface because the toolbar is fully displayed
drawToolbar(original);
- // TODO: countdown
-
g_system->copyRectToScreen(_destSurface.getPixels(), _destSurface.pitch, 0,
original->h - _destSurface.h, _destSurface.w, _destSurface.h);
g_system->updateScreen();