[Scummvm-git-logs] scummvm master -> bf8c469fd84e4dbab92925bf32e2fc205b08f921

fracturehill noreply at scummvm.org
Fri Jul 14 12:48:37 UTC 2023


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
893545f9bf NANCY: Implement alarm clock
bf8c469fd8 NANCY: Disable UI clock in alarm clock scenes


Commit: 893545f9bf82d0196efa4e1e82a00950e1d2912c
    https://github.com/scummvm/scummvm/commit/893545f9bf82d0196efa4e1e82a00950e1d2912c
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-07-14T15:47:34+03:00

Commit Message:
NANCY: Implement alarm clock

Implemented the SetPlayerClock action record, which
is responsible for the alarm clock introduced in nancy3.

Changed paths:
  A engines/nancy/action/setplayerclock.cpp
  A engines/nancy/action/setplayerclock.h
    engines/nancy/action/arfactory.cpp
    engines/nancy/module.mk


diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index d94d809c34f..099a4e2af8f 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -36,6 +36,7 @@
 #include "engines/nancy/action/overridelockpuzzle.h"
 #include "engines/nancy/action/bombpuzzle.h"
 #include "engines/nancy/action/soundequalizerpuzzle.h"
+#include "engines/nancy/action/setplayerclock.h"
 
 #include "engines/nancy/state/scene.h"
 
@@ -153,6 +154,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
 		return new StopSound(); // StopAndUnloadSound, but we always unload
 	case 160:
 		return new HintSystem();
+	case 170:
+		return new SetPlayerClock();
 	case 200:
 		return new SoundEqualizerPuzzle();
 	case 201:
diff --git a/engines/nancy/action/setplayerclock.cpp b/engines/nancy/action/setplayerclock.cpp
new file mode 100644
index 00000000000..f74a0f65252
--- /dev/null
+++ b/engines/nancy/action/setplayerclock.cpp
@@ -0,0 +1,275 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "engines/nancy/action/setplayerclock.h"
+#include "engines/nancy/state/scene.h"
+
+#include "engines/nancy/nancy.h"
+#include "engines/nancy/input.h"
+#include "engines/nancy/graphics.h"
+#include "engines/nancy/util.h"
+#include "engines/nancy/resource.h"
+#include "engines/nancy/sound.h"
+
+namespace Nancy {
+namespace Action {
+
+void SetPlayerClock::init() {
+	Common::Rect screenBounds = NancySceneState.getViewport().getBounds();
+	_drawSurface.create(screenBounds.width(), screenBounds.height(), g_nancy->_graphicsManager->getInputPixelFormat());
+	_drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
+	setTransparent(true);
+	setVisible(true);
+	moveTo(screenBounds);
+
+	g_nancy->_resource->loadImage(_imageName, _image);
+	_image.setTransparentColor(_drawSurface.getTransparentColor());
+}
+
+void SetPlayerClock::readData(Common::SeekableReadStream &stream) {
+	readFilename(stream, _imageName);
+
+	readRect(stream, _minutesDest);
+	readRect(stream, _hoursDest);
+	readRect(stream, _AMPMDest);
+	readRect(stream, _timeButtonDest);
+	readRect(stream, _alarmButtonDest);
+	readRect(stream, _setButtonDest);
+	readRect(stream, _cancelButtonDest);
+	readRect(stream, _upButtonDest);
+	readRect(stream, _downButtonDest);
+	readRect(stream, _modeLightDest);
+
+	readRectArray(stream, _minutesSrc, 4);
+	readRectArray(stream, _hoursSrc, 12);
+
+	readRect(stream, _AMSrc);
+	readRect(stream, _PMSrc);
+	readRect(stream, _timeButtonSrc);
+	readRect(stream, _alarmButtonSrc);
+	readRect(stream, _setButtonSrc);
+	readRect(stream, _cancelButtonSrc);
+	readRect(stream, _upButtonSrc);
+	readRect(stream, _downButtonSrc);
+	readRect(stream, _timeLightSrc);
+	readRect(stream, _alarmLightSrc);
+
+	stream.skip(2);
+
+	_buttonSound.readNormal(stream);
+	_alarmSetScene.readData(stream);
+	_alarmSoundDelay = stream.readUint16LE();
+	_alarmRingSound.readNormal(stream);
+	_exitScene.readData(stream);
+}
+
+void SetPlayerClock::execute() {
+	switch (_state) {
+	case kBegin:
+		init();
+		registerGraphics();
+
+		g_nancy->_sound->loadSound(_buttonSound);
+		g_nancy->_sound->loadSound(_alarmRingSound);
+
+		_alarmHours = NancySceneState.getPlayerTime().getHours();
+
+		_state = kRun;
+		// fall through
+	case kRun:
+		if (_alarmState == kTimeMode) {
+			Time currentTime = NancySceneState.getPlayerTime();
+			int8 hours = currentTime.getHours();
+			int8 minutes = currentTime.getMinutes();
+
+			if (_clearButton && !g_nancy->_sound->isSoundPlaying(_buttonSound)) {
+				_drawSurface.fillRect(_timeButtonDest, _drawSurface.getTransparentColor());
+				_drawSurface.fillRect(_modeLightDest, _drawSurface.getTransparentColor());
+				_drawSurface.blitFrom(_image, _timeLightSrc, _modeLightDest);
+				_clearButton = false;
+				_needsRedraw = true;
+			}
+
+			if (_lastDrawnHours != hours || _lastDrawnMinutes / 15 != minutes / 15) {
+				drawTime(currentTime.getHours(), currentTime.getMinutes());
+				_lastDrawnHours = hours;
+				_lastDrawnMinutes = minutes;
+			}
+		} else {
+			if (_clearButton && !g_nancy->_sound->isSoundPlaying(_buttonSound)) {
+				_drawSurface.fillRect(_alarmButtonDest, _drawSurface.getTransparentColor());
+				_drawSurface.fillRect(_upButtonDest, _drawSurface.getTransparentColor());
+				_drawSurface.fillRect(_downButtonDest, _drawSurface.getTransparentColor());
+				_drawSurface.fillRect(_modeLightDest, _drawSurface.getTransparentColor());
+				_drawSurface.blitFrom(_image, _alarmLightSrc, _modeLightDest);
+				drawTime(_alarmHours, 0);
+				_clearButton = false;
+				_needsRedraw = true;
+			}
+		}
+
+		break;
+	case kActionTrigger:
+		if (g_nancy->_sound->isSoundPlaying(_buttonSound)) {
+			return;
+		}
+
+		if (_clearButton) {
+			g_nancy->_sound->stopSound(_buttonSound);
+			_drawSurface.fillRect(_setButtonDest, _drawSurface.getTransparentColor());
+			_clearButton = false;
+		}
+
+		if (_alarmState == kWait) {
+			// Alarm has been set, wait for timer
+			if (g_system->getMillis() > _sceneChangeTime) {
+				NancySceneState.setPlayerTime(_alarmHours * 3600000, false);
+				_alarmSetScene.execute();
+				finishExecution();
+			}
+		} else {
+			// Cancel button pressed, go to exit scene
+			_exitScene.execute();
+			finishExecution();
+		}
+	}
+}
+
+void SetPlayerClock::handleInput(NancyInput &input) {
+	if (_alarmState == kWait) {
+		return;
+	}
+
+	// Cancel button is active in both time and alarm mode
+	if (NancySceneState.getViewport().convertViewportToScreen(_cancelButtonDest).contains(input.mousePos)) {
+		g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+		if (input.input & NancyInput::kLeftMouseButtonUp) {
+			// Cancel button pressed
+			_drawSurface.blitFrom(_image, _cancelButtonSrc, _cancelButtonDest);
+			_needsRedraw = true;
+
+			g_nancy->_sound->playSound(_buttonSound);
+			
+			_state = kActionTrigger;
+			return;
+		}
+	}
+
+	if (_alarmState == kTimeMode) {
+		// Alarm button is active only in time mode
+		if (NancySceneState.getViewport().convertViewportToScreen(_alarmButtonDest).contains(input.mousePos)) {
+			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+			if (input.input & NancyInput::kLeftMouseButtonUp) {
+				// Alarm button pressed
+				_drawSurface.blitFrom(_image, _alarmButtonSrc, _alarmButtonDest);
+				_needsRedraw = true;
+
+				g_nancy->_sound->playSound(_buttonSound);
+				_lastDrawnHours = _lastDrawnMinutes = -1;
+				
+				_alarmState = kAlarmMode;
+				_clearButton = true;
+				return;
+			}
+		}
+	} else {
+		if (NancySceneState.getViewport().convertViewportToScreen(_timeButtonDest).contains(input.mousePos)) {
+			// Time button is active only in alarm mode
+			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+			if (input.input & NancyInput::kLeftMouseButtonUp) {
+				// Alarm button pressed
+				_drawSurface.blitFrom(_image, _timeButtonSrc, _timeButtonDest);
+				_needsRedraw = true;
+
+				g_nancy->_sound->playSound(_buttonSound);
+				
+				_alarmState = kTimeMode;
+				_clearButton = true;
+				return;
+			}
+		} else if (NancySceneState.getViewport().convertViewportToScreen(_upButtonDest).contains(input.mousePos)) {
+			// Up button is active only in alarm mode
+			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+			if (input.input & NancyInput::kLeftMouseButtonUp) {
+				// Up button pressed
+				_drawSurface.blitFrom(_image, _upButtonSrc, _upButtonDest);
+				_needsRedraw = true;
+
+				g_nancy->_sound->playSound(_buttonSound);
+				_alarmHours = _alarmHours + 1 > 23 ? 0 : _alarmHours + 1;
+				
+				_clearButton = true;
+				return;
+			}
+		} else if (NancySceneState.getViewport().convertViewportToScreen(_downButtonDest).contains(input.mousePos)) {
+			// Down button is active only in alarm mode
+			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+			if (input.input & NancyInput::kLeftMouseButtonUp) {
+				// Down button pressed
+				_drawSurface.blitFrom(_image, _downButtonSrc, _downButtonDest);
+				_needsRedraw = true;
+
+				g_nancy->_sound->playSound(_buttonSound);
+				_alarmHours = _alarmHours - 1 < 0 ? 23 : _alarmHours - 1;
+				
+				_clearButton = true;
+				return;
+			}
+		} else if (NancySceneState.getViewport().convertViewportToScreen(_setButtonDest).contains(input.mousePos)) {
+			// Set button is active only in alarm mode
+			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+			if (input.input & NancyInput::kLeftMouseButtonUp) {
+				// Down button pressed
+				_drawSurface.blitFrom(_image, _setButtonSrc, _setButtonDest);
+				_needsRedraw = true;
+
+				g_nancy->_sound->playSound(_buttonSound);
+				
+				_clearButton = true;
+				_state = kActionTrigger;
+				_alarmState = kWait;
+				_sceneChangeTime = g_system->getMillis() + (_alarmSoundDelay * 1000);
+				return;
+			}
+		}
+	}
+}
+
+void SetPlayerClock::drawTime(uint16 hours, uint16 minutes) {
+	_drawSurface.fillRect(_hoursDest, _drawSurface.getTransparentColor());
+	_drawSurface.fillRect(_minutesDest, _drawSurface.getTransparentColor());
+	_drawSurface.fillRect(_AMPMDest, _drawSurface.getTransparentColor());
+
+	_drawSurface.blitFrom(_image, _hoursSrc[(hours - 1 < 0 ? 11 : hours - 1) % 12], _hoursDest);
+	_drawSurface.blitFrom(_image, _minutesSrc[minutes / 15], _minutesDest);
+	_drawSurface.blitFrom(_image, hours / 12 == 0 ? _AMSrc : _PMSrc, _AMPMDest);
+
+	_needsRedraw = true;
+}
+
+} // End of namespace Action
+} // End of namespace Nancy
diff --git a/engines/nancy/action/setplayerclock.h b/engines/nancy/action/setplayerclock.h
new file mode 100644
index 00000000000..0702bb42a94
--- /dev/null
+++ b/engines/nancy/action/setplayerclock.h
@@ -0,0 +1,95 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NANCY_ACTION_SETPLAYERCLOCK_H
+#define NANCY_ACTION_SETPLAYERCLOCK_H
+
+#include "engines/nancy/action/actionrecord.h"
+
+namespace Nancy {
+namespace Action {
+
+// Action record implementing an alarm clock. First used in nancy3
+class SetPlayerClock : public RenderActionRecord {
+public:
+	enum AlarmState { kTimeMode, kAlarmMode, kWait };
+	SetPlayerClock() : RenderActionRecord(7) {}
+	virtual ~SetPlayerClock() {}
+
+	void init() override;
+
+	void readData(Common::SeekableReadStream &stream) override;
+	void execute() override;
+	void handleInput(NancyInput &input) override;
+
+protected:
+	Common::String getRecordTypeName() const override { return "SetPlayerClock"; }
+	bool isViewportRelative() const override { return true; }
+
+	void drawTime(uint16 hours, uint16 minutes);
+
+	Common::String _imageName;
+
+	Common::Rect _minutesDest;
+	Common::Rect _hoursDest;
+	Common::Rect _AMPMDest;
+	Common::Rect _timeButtonDest;
+	Common::Rect _alarmButtonDest;
+	Common::Rect _setButtonDest;
+	Common::Rect _cancelButtonDest;
+	Common::Rect _upButtonDest;
+	Common::Rect _downButtonDest;
+	Common::Rect _modeLightDest;
+
+	Common::Array<Common::Rect> _minutesSrc;
+	Common::Array<Common::Rect> _hoursSrc;
+	Common::Rect _AMSrc;
+	Common::Rect _PMSrc;
+	Common::Rect _timeButtonSrc;
+	Common::Rect _alarmButtonSrc;
+	Common::Rect _setButtonSrc;
+	Common::Rect _cancelButtonSrc;
+	Common::Rect _upButtonSrc;
+	Common::Rect _downButtonSrc;
+	Common::Rect _timeLightSrc;
+	Common::Rect _alarmLightSrc;
+
+	SoundDescription _buttonSound;
+	SceneChangeWithFlag _alarmSetScene;
+	uint16 _alarmSoundDelay;
+	SoundDescription _alarmRingSound; // NO SOUND in MHM
+	SceneChangeWithFlag _exitScene;
+
+	Graphics::ManagedSurface _image;
+
+	int8 _lastDrawnHours = -1;
+	int8 _lastDrawnMinutes = -1;
+	int8 _alarmHours = -1;
+	bool _clearButton = true;
+	Time _sceneChangeTime;
+
+	AlarmState _alarmState = kTimeMode;
+};
+
+} // End of namespace Action
+} // End of namespace Nancy
+
+#endif // NANCY_ACTION_SETPLAYERCLOCK_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index d06009945d4..c2fc6266216 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS = \
   action/riddlepuzzle.o \
   action/secondarymovie.o \
   action/secondaryvideo.o \
+  action/setplayerclock.o \
   action/sliderpuzzle.o \
   action/soundequalizerpuzzle.o \
   action/towerpuzzle.o \


Commit: bf8c469fd84e4dbab92925bf32e2fc205b08f921
    https://github.com/scummvm/scummvm/commit/bf8c469fd84e4dbab92925bf32e2fc205b08f921
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-07-14T15:47:34+03:00

Commit Message:
NANCY: Disable UI clock in alarm clock scenes

Added facilities to disable the UI clock (in the bottom
left corner of the screen) when playing an alarm clock scene.

Changed paths:
    engines/nancy/action/setplayerclock.cpp
    engines/nancy/action/setplayerclock.h
    engines/nancy/state/scene.h
    engines/nancy/ui/clock.cpp
    engines/nancy/ui/clock.h


diff --git a/engines/nancy/action/setplayerclock.cpp b/engines/nancy/action/setplayerclock.cpp
index f74a0f65252..49403395632 100644
--- a/engines/nancy/action/setplayerclock.cpp
+++ b/engines/nancy/action/setplayerclock.cpp
@@ -21,6 +21,7 @@
 
 #include "engines/nancy/action/setplayerclock.h"
 #include "engines/nancy/state/scene.h"
+#include "engines/nancy/ui/clock.h"
 
 #include "engines/nancy/nancy.h"
 #include "engines/nancy/input.h"
@@ -32,6 +33,13 @@
 namespace Nancy {
 namespace Action {
 
+SetPlayerClock::~SetPlayerClock() {
+	Nancy::UI::Clock *clock = NancySceneState.getClock();
+	if (clock) {
+		clock->lockClock(false);
+	}
+}
+
 void SetPlayerClock::init() {
 	Common::Rect screenBounds = NancySceneState.getViewport().getBounds();
 	_drawSurface.create(screenBounds.width(), screenBounds.height(), g_nancy->_graphicsManager->getInputPixelFormat());
@@ -83,7 +91,7 @@ void SetPlayerClock::readData(Common::SeekableReadStream &stream) {
 
 void SetPlayerClock::execute() {
 	switch (_state) {
-	case kBegin:
+	case kBegin: {
 		init();
 		registerGraphics();
 
@@ -91,8 +99,14 @@ void SetPlayerClock::execute() {
 		g_nancy->_sound->loadSound(_alarmRingSound);
 
 		_alarmHours = NancySceneState.getPlayerTime().getHours();
+		
+		Nancy::UI::Clock *clock = NancySceneState.getClock();
+		if (clock) {
+			clock->lockClock(true);
+		}
 
 		_state = kRun;
+	}
 		// fall through
 	case kRun:
 		if (_alarmState == kTimeMode) {
diff --git a/engines/nancy/action/setplayerclock.h b/engines/nancy/action/setplayerclock.h
index 0702bb42a94..d0eb9ae2fb8 100644
--- a/engines/nancy/action/setplayerclock.h
+++ b/engines/nancy/action/setplayerclock.h
@@ -32,7 +32,7 @@ class SetPlayerClock : public RenderActionRecord {
 public:
 	enum AlarmState { kTimeMode, kAlarmMode, kWait };
 	SetPlayerClock() : RenderActionRecord(7) {}
-	virtual ~SetPlayerClock() {}
+	virtual ~SetPlayerClock();
 
 	void init() override;
 
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 506b0044a57..3dfedf8bd2e 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -176,6 +176,7 @@ public:
 	UI::Viewport &getViewport() { return _viewport; }
 	UI::Textbox &getTextbox() { return _textbox; }
 	UI::InventoryBox &getInventoryBox() { return _inventoryBox; }
+	UI::Clock *getClock() { return _clock; }
 
 	Action::ActionManager &getActionManager() { return _actionManager; }
 
diff --git a/engines/nancy/ui/clock.cpp b/engines/nancy/ui/clock.cpp
index 71487abc59a..27ec3a6fda5 100644
--- a/engines/nancy/ui/clock.cpp
+++ b/engines/nancy/ui/clock.cpp
@@ -37,7 +37,8 @@ namespace UI {
 Clock::Clock() : 	RenderObject(g_nancy->getGameType() == kGameTypeVampire ? 11 : 10),
 					_animation(g_nancy->getGameType() == kGameTypeVampire ? 10 : 11, this),
 					_staticImage(9),
-					_clockData(nullptr) {}
+					_clockData(nullptr),
+					_locked(false) {}
 
 void Clock::init() {
 	Graphics::ManagedSurface &object0 = g_nancy->_graphicsManager->_object0;
@@ -99,7 +100,9 @@ void Clock::updateGraphics() {
 }
 
 void Clock::handleInput(NancyInput &input) {
-	_animation.handleInput(input);
+	if (!_locked) {
+		_animation.handleInput(input);
+	}
 }
 
 void Clock::drawClockHands() {
@@ -142,7 +145,7 @@ void Clock::ClockAnim::init() {
 
 void Clock::ClockAnim::updateGraphics() {
 	AnimatedButton::updateGraphics();
-	if (_isOpen && !isPlaying() && g_nancy->getTotalPlayTime() > _closeTime && _isVisible) {
+	if (_isOpen && !isPlaying() && (g_nancy->getTotalPlayTime() > _closeTime || _owner->_locked) && _isVisible) {
 		setOpen(false);
 		if (g_nancy->getGameType() == kGameTypeVampire) {
 			_owner->_staticImage.setVisible(false);
diff --git a/engines/nancy/ui/clock.h b/engines/nancy/ui/clock.h
index 9a41bd80ec2..76361c7b42a 100644
--- a/engines/nancy/ui/clock.h
+++ b/engines/nancy/ui/clock.h
@@ -45,6 +45,9 @@ public:
 	void updateGraphics() override;
 	void handleInput(NancyInput &input);
 
+	// Used to disable the UI clock when a scene can change the in-game time (e.g. SetPlayerClock)
+	void lockClock(bool val) { _locked = val; }
+
 	void drawClockHands();
 
 protected:
@@ -72,6 +75,7 @@ protected:
 	RenderObject _staticImage;
 
 	Time _playerTime;
+	bool _locked;
 };
 
 } // End of namespace UI




More information about the Scummvm-git-logs mailing list